Skip to content

Commit

Permalink
dlang#562: Expand on --import-paths to support other build settings a…
Browse files Browse the repository at this point in the history
…nd optional recursion into dependencies.
  • Loading branch information
Nick Sabalausky authored and Nick Sabalausky committed May 5, 2015
1 parent e3bf00c commit 888e59e
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 23 deletions.
54 changes: 46 additions & 8 deletions source/dub/commandline.d
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ class DescribeCommand : PackageBuildCommand {
private {
bool m_importPaths = false;
bool m_stringImportPaths = false;
string[] m_data;
}

this()
Expand All @@ -761,14 +762,38 @@ class DescribeCommand : PackageBuildCommand {
"their dependencies in a format similar to a JSON package "
"description file. This is useful mostly for IDEs.",
"",
"When --import-paths is supplied, the import paths for a project ",
"will be printed line-by-line instead. The paths for D source "
"files across all dependent projects will be included.",
"All usual options that are also used for build/run/generate apply.",
"",
"--string-import-paths can can supplied to print the string "
"import paths for a project.",
"When --data=VALUE is supplied, specific build settings for a project ",
"will be printed instead (by default, line-by-line). The VALUE must "
`be prefixed with either "recursive-" or "package-" to indicate `
`whether to include dependencies ("recursive-") or just this `
`package alone ("package-").`,
"",
"All usual options that are also used for build/run/generate apply."
"The --data=VALUE option can be specified multiple times to retrieve "
"several pieces of information at once. The data will be output in "
"the same order requested on the command line.",
"",
"The accepted values for --data=VALUE are:",
"package-target-path, recursive-target-path",
"package-target-name, recursive-target-name",
"package-working-directory, recursive-working-directory",
"package-main-source-file, recursive-main-source-file",
"package-dflags, recursive-dflags",
"package-lflags, recursive-lflags",
"package-libs, recursive-libs",
"package-source-files, recursive-source-files",
"package-copy-files, recursive-copy-files",
"package-versions, recursive-versions",
"package-debug-versions, recursive-debug-versions",
"package-import-paths, recursive-import-paths",
"package-string-import-paths, recursive-string-import-paths",
"package-import-files, recursive-import-files",
"package-string-import-files, recursive-string-import-files",
"package-pre-generate-commands, recursive-pre-generate-commands",
"package-post-generate-commands, recursive-post-generate-commands",
"package-pre-build-commands, recursive-pre-build-commands",
"package-post-build-commands, recursive-post-build-commands",
];
}

Expand All @@ -777,11 +802,17 @@ class DescribeCommand : PackageBuildCommand {
super.prepare(args);

args.getopt("import-paths", &m_importPaths, [
"List the import paths for project."
"Shortcut for --data=recursive-import-paths"
]);

args.getopt("string-import-paths", &m_stringImportPaths, [
"List the string import paths for project."
"Shortcut for --data=recursive-string-import-paths"
]);

args.getopt("data", &m_data, [
"Just list the values of a particular build setting, either for this "~
"package alone or recursively including all dependencies. See "~
"above for more details and accepted possibilities for VALUE."
]);
}

Expand All @@ -792,6 +823,11 @@ class DescribeCommand : PackageBuildCommand {
"--import-paths and --string-import-paths may not be used together."
);

enforceUsage(
!(m_data && (m_importPaths || m_stringImportPaths)),
"--data may not be used together with --import-paths or --string-import-paths."
);

// disable all log output and use "writeln" to output the JSON description
auto ll = getLogLevel();
setLogLevel(LogLevel.none);
Expand All @@ -810,6 +846,8 @@ class DescribeCommand : PackageBuildCommand {
dub.listImportPaths(m_buildPlatform, config);
} else if (m_stringImportPaths) {
dub.listStringImportPaths(m_buildPlatform, config);
} else if (m_data) {
dub.listProjectData(m_buildPlatform, config, m_data);
} else {
dub.describeProject(m_buildPlatform, config);
}
Expand Down
9 changes: 9 additions & 0 deletions source/dub/dub.d
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,15 @@ class Dub {
}
}

void listProjectData(BuildPlatform platform, string config, string[] requestedData)
{
import std.stdio;

foreach(data; m_project.listBuildSettings(platform, config, requestedData)) {
writeln(data);
}
}

/// Cleans intermediate/cache files of the given package
void cleanPackage(Path path)
{
Expand Down
96 changes: 81 additions & 15 deletions source/dub/project.d
Original file line number Diff line number Diff line change
Expand Up @@ -582,45 +582,111 @@ class Project {
}
}

private string[] listPaths(string attributeName)(BuildPlatform platform, string config)
// recursive: Should settings from dependencies be included?
private string[] listBuildSetting(string attributeName)(BuildPlatform platform, string config, bool recursive=true)
{
return listBuildSetting!attributeName(platform, getPackageConfigs(platform, config), recursive);
}

private string[] listBuildSetting(string attributeName)(BuildPlatform platform, string[string] configs, bool recursive=true)
{
import std.path : buildPath, dirSeparator;

auto configs = getPackageConfigs(platform, config);
import std.traits : isArray;

string[] list;

auto fullPackagePaths(Package pack) {
auto getPackageBuildSetting(Package pack) {
auto values = __traits(getMember, pack.getBuildSettings(platform, configs[pack.name]), attributeName);

// Return full paths for the import paths, making sure a
// directory separator is on the end of each path.
return __traits(getMember, pack.getBuildSettings(platform, configs[pack.name]), attributeName)
.map!(importPath => buildPath(pack.path.toString(), importPath))
.map!(path => path.endsWith(dirSeparator) ? path : path ~ dirSeparator);
static if(attributeName == "importPaths" || attributeName == "stringImportPaths")
{
return values
.map!(importPath => buildPath(pack.path.toString(), importPath))
.map!(path => path.endsWith(dirSeparator) ? path : path ~ dirSeparator);
}
else static if( is(typeof(values) == string[]) ) // Is a string[]?
return values;
else
return values.empty()? null : [values];
}

foreach(path; fullPackagePaths(m_rootPackage)) {
list ~= path;
foreach(value; getPackageBuildSetting(m_rootPackage)) {
list ~= value;
}

foreach (dep; m_dependencies) {
foreach(path; fullPackagePaths(dep)) {
list ~= path;
if(recursive) {
foreach(dep; m_dependencies) {
foreach(value; getPackageBuildSetting(dep)) {
list ~= value;
}
}
}

return list;
}

// requestedData is of the form "package-(attr-name)" or "recursive-(attr-name)",
// for example: "package-main-source-file" or "recursive-import-paths"
private string[] listBuildSetting(BuildPlatform platform, string[string] configs, string requestedData)
{
auto requestedDataParts = requestedData.findSplit("-");
enforce(requestedDataParts[0] == "package" || requestedDataParts[0] == "recursive",
"The name of requested data, '"~requestedData~"', doesn't begin with 'package-' or 'recursive-' as required.");

bool recursive = requestedDataParts[0] == "recursive";
switch(requestedDataParts[2])
{
case "target-path": return listBuildSetting!"targetPath"(platform, configs, recursive);
case "target-name": return listBuildSetting!"targetName"(platform, configs, recursive);
case "working-directory": return listBuildSetting!"workingDirectory"(platform, configs, recursive);
case "main-source-file": return listBuildSetting!"mainSourceFile"(platform, configs, recursive);
case "dflags": return listBuildSetting!"dflags"(platform, configs, recursive);
case "lflags": return listBuildSetting!"lflags"(platform, configs, recursive);
case "libs": return listBuildSetting!"libs"(platform, configs, recursive);
case "source-files": return listBuildSetting!"sourceFiles"(platform, configs, recursive);
case "copy-files": return listBuildSetting!"copyFiles"(platform, configs, recursive);
case "versions": return listBuildSetting!"versions"(platform, configs, recursive);
case "debug-versions": return listBuildSetting!"debugVersions"(platform, configs, recursive);
case "import-paths": return listBuildSetting!"importPaths"(platform, configs, recursive);
case "string-import-paths": return listBuildSetting!"stringImportPaths"(platform, configs, recursive);
case "import-files": return listBuildSetting!"importFiles"(platform, configs, recursive);
case "string-import-files": return listBuildSetting!"stringImportFiles"(platform, configs, recursive);
case "pre-generate-commands": return listBuildSetting!"preGenerateCommands"(platform, configs, recursive);
case "post-generate-commands": return listBuildSetting!"postGenerateCommands"(platform, configs, recursive);
case "pre-build-commands": return listBuildSetting!"preBuildCommands"(platform, configs, recursive);
case "post-build-commands": return listBuildSetting!"postBuildCommands"(platform, configs, recursive);

default:
enforce(false, "'"~requestedData~
"' is not a valid name for requested data. See 'dub describe --help' for accepted values.");
}

assert(0);
}

/// Outputs requested data for the project, optionally including its dependencies.
string[] listBuildSettings(BuildPlatform platform, string config, string[] requestedData)
{
auto configs = getPackageConfigs(platform, config);

return requestedData
.map!(dataName => listBuildSetting(platform, configs, dataName))
.joiner([""]) // Blank line between each type of requestedData
.array();
}

/// Outputs the import paths for the project, including its dependencies.
string [] listImportPaths(BuildPlatform platform, string config)
string[] listImportPaths(BuildPlatform platform, string config)
{
return listPaths!"importPaths"(platform, config);
return listBuildSetting!"importPaths"(platform, config);
}

/// Outputs the string import paths for the project, including its dependencies.
string[] listStringImportPaths(BuildPlatform platform, string config)
{
return listPaths!"stringImportPaths"(platform, config);
return listBuildSetting!"stringImportPaths"(platform, config);
}

void saveSelections()
Expand Down

0 comments on commit 888e59e

Please sign in to comment.