diff --git a/.gitignore b/.gitignore index a5e949d..7981eaa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,22 @@ *.o *.obj -.dub/ +.dub +.directory dub.selections.json -bin/dub docs.json __dummy.html + +# Ignore build files. +/bin/dub +/bin/__test__library-nonet__ +/bin/__test__library__ + +# Ignore files or directories created by the test suite. +/test/custom-source-main-bug487/custom-source-main-bug487 +/test/3-copyFiles/bin/ +/test/ignore-hidden-1/ignore-hidden-1 +/test/ignore-hidden-2/ignore-hidden-2 +/test/expected-import-path-output +/test/expected-string-import-path-output diff --git a/source/dub/commandline.d b/source/dub/commandline.d index a00410e..420447b 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -746,13 +746,28 @@ } class DescribeCommand : PackageBuildCommand { + private { + bool m_importPaths = false; + bool m_stringImportPaths = false; + } + this() { this.name = "describe"; this.argumentsPattern = "[]"; this.description = "Prints a JSON description of the project and its dependencies"; this.helpText = [ - "Prints a JSON build description for the root package an all of their dependencies in a format similar to a JSON package description file. This is useful mostly for IDEs.", + "Prints a JSON build description for the root package an all of " + "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.", + "", + "--string-import-paths can can supplied to print the string " + "import paths for a project.", + "", "All usual options that are also used for build/run/generate apply." ]; } @@ -760,10 +775,23 @@ override void prepare(scope CommandArgs args) { super.prepare(args); + + args.getopt("import-paths", &m_importPaths, [ + "List the import paths for project." + ]); + + args.getopt("string-import-paths", &m_stringImportPaths, [ + "List the string import paths for project." + ]); } override int execute(Dub dub, string[] free_args, string[] app_args) { + enforceUsage( + !(m_importPaths && m_stringImportPaths), + "--import-paths and --string-import-paths may not be used together." + ); + // disable all log output and use "writeln" to output the JSON description auto ll = getLogLevel(); setLogLevel(LogLevel.none); @@ -776,7 +804,16 @@ m_defaultConfig = dub.project.getDefaultConfiguration(m_buildPlatform); - dub.describeProject(m_buildPlatform, m_buildConfig.length ? m_buildConfig : m_defaultConfig); + auto config = m_buildConfig.length ? m_buildConfig : m_defaultConfig; + + if (m_importPaths) { + dub.listImportPaths(m_buildPlatform, config); + } else if (m_stringImportPaths) { + dub.listStringImportPaths(m_buildPlatform, config); + } else { + dub.describeProject(m_buildPlatform, config); + } + return 0; } } @@ -1634,3 +1671,4 @@ { logWarn("The '%s' Command was renamed to '%s'. Please update your scripts.", prev, curr); } + diff --git a/source/dub/dub.d b/source/dub/dub.d index c933c83..31eb84e 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -422,6 +422,24 @@ write(dst.toPrettyString()); } + void listImportPaths(BuildPlatform platform, string config) + { + import std.stdio; + + foreach(path; m_project.listImportPaths(platform, config)) { + writeln(path); + } + } + + void listStringImportPaths(BuildPlatform platform, string config) + { + import std.stdio; + + foreach(path; m_project.listStringImportPaths(platform, config)) { + writeln(path); + } + } + /// Cleans intermediate/cache files of the given package void cleanPackage(Path path) { @@ -1027,3 +1045,4 @@ return null; } } + diff --git a/source/dub/project.d b/source/dub/project.d index 540f6c6..34b0dc6 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -181,7 +181,7 @@ logWarn(`WARNING: DUB package names may only contain alphanumeric characters, ` ~ `as well as '-' and '_', please modify the "name" field in %s ` ~ `accordingly. You can use {"targetName": "%s"} to keep the current ` - ~ `executable name.`, + ~ `executable name.`, m_rootPackage.packageInfoFilename.toNativeString(), m_rootPackage.name); } enforce(!m_rootPackage.name.canFind(' '), "Aborting due to the package name containing spaces."); @@ -582,6 +582,47 @@ } } + private string[] listPaths(string attributeName)(BuildPlatform platform, string config) + { + import std.path : buildPath, dirSeparator; + + auto configs = getPackageConfigs(platform, config); + + string[] list; + + auto fullPackagePaths(Package pack) { + // 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, config), attributeName) + .map!(importPath => buildPath(pack.path.toString(), importPath)) + .map!(path => path.endsWith(dirSeparator) ? path : path ~ dirSeparator); + } + + foreach(path; fullPackagePaths(m_rootPackage)) { + list ~= path; + } + + foreach (dep; m_dependencies) { + foreach(path; fullPackagePaths(dep)) { + list ~= path; + } + } + + return list; + } + + /// Outputs the import paths for the project, including its dependencies. + string [] listImportPaths(BuildPlatform platform, string config) + { + return listPaths!"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); + } + void saveSelections() { assert(m_selections !is null, "Cannot save selections for non-disk based project (has no selections)."); @@ -972,3 +1013,4 @@ m_selections[p] = Selected(dependencyFromJson(v)); } } + diff --git a/test/4-describe-import-paths.sh b/test/4-describe-import-paths.sh new file mode 100755 index 0000000..b896daf --- /dev/null +++ b/test/4-describe-import-paths.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e -o pipefail + +cd "$CURR_DIR"/describe-project + +temp_file=`mktemp` + +function cleanup { + rm $temp_file +} + +trap cleanup EXIT + +if ! $DUB describe --compiler=$COMPILER --import-paths > "$temp_file"; then + die 'Printing import paths failed!' +fi + +# Create the expected output path file to compare against. +echo "$CURR_DIR/describe-project/src/" > "$CURR_DIR/expected-import-path-output" +echo "$CURR_DIR/describe-dependency-1/source/" >> "$CURR_DIR/expected-import-path-output" +echo "$CURR_DIR/describe-dependency-2/some-path/" >> "$CURR_DIR/expected-import-path-output" + +if ! diff "$CURR_DIR"/expected-import-path-output "$temp_file"; then + die 'The import paths did not match the expected output!' +fi + diff --git a/test/4-describe-json.sh b/test/4-describe-json.sh new file mode 100755 index 0000000..f457249 --- /dev/null +++ b/test/4-describe-json.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e -o pipefail + +cd "$CURR_DIR"/describe-project + +temp_file=`mktemp` + +function cleanup { + rm $temp_file +} + +trap cleanup EXIT + +if ! $DUB describe --compiler=$COMPILER > "$temp_file"; then + die 'Printing describe JSON failed!' +fi + diff --git a/test/4-describe-string-importh-paths.sh b/test/4-describe-string-importh-paths.sh new file mode 100755 index 0000000..790af85 --- /dev/null +++ b/test/4-describe-string-importh-paths.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e -o pipefail + +cd "$CURR_DIR"/describe-project + +temp_file=`mktemp` + +function cleanup { + rm $temp_file +} + +trap cleanup EXIT + +if ! $DUB describe --compiler=$COMPILER --string-import-paths > "$temp_file"; then + die 'Printing string import paths failed!' +fi + +# Create the expected output path file to compare against. +echo "$CURR_DIR/describe-project/views/" > "$CURR_DIR/expected-string-import-path-output" +echo "$CURR_DIR/describe-dependency-2/some-extra-string-import-path/" >> "$CURR_DIR/expected-string-import-path-output" + +if ! diff "$CURR_DIR"/expected-string-import-path-output "$temp_file"; then + die 'The string import paths did not match the expected output!' +fi + diff --git a/test/describe-dependency-1/.no_build b/test/describe-dependency-1/.no_build new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-dependency-1/.no_build @@ -0,0 +1 @@ + diff --git a/test/describe-dependency-1/dub.json b/test/describe-dependency-1/dub.json new file mode 100644 index 0000000..239e6b1 --- /dev/null +++ b/test/describe-dependency-1/dub.json @@ -0,0 +1,9 @@ +{ + "name": "describe-dependency-1", + "targetType": "sourceLibrary", + "description": "A test describe project", + "authors": ["nobody"], + "homepage": "fake.com", + "license": "BSD 2-clause", + "copyright": "Copyright © 2015, nobody" +} diff --git a/test/describe-dependency-1/otherdir/dummy.d b/test/describe-dependency-1/otherdir/dummy.d new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-dependency-1/otherdir/dummy.d @@ -0,0 +1 @@ + diff --git a/test/describe-dependency-1/source/dummy.d b/test/describe-dependency-1/source/dummy.d new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-dependency-1/source/dummy.d @@ -0,0 +1 @@ + diff --git a/test/describe-dependency-2/.no_build b/test/describe-dependency-2/.no_build new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-dependency-2/.no_build @@ -0,0 +1 @@ + diff --git a/test/describe-dependency-2/dub.json b/test/describe-dependency-2/dub.json new file mode 100644 index 0000000..0b62a92 --- /dev/null +++ b/test/describe-dependency-2/dub.json @@ -0,0 +1,11 @@ +{ + "name": "describe-dependency-2", + "targetType": "sourceLibrary", + "description": "A test describe project", + "authors": ["nobody"], + "homepage": "fake.com", + "license": "BSD 2-clause", + "copyright": "Copyright © 2015, nobody", + "importPaths": ["some-path"], + "stringImportPaths": ["some-extra-string-import-path"], +} diff --git a/test/describe-dependency-2/some-extra-string-import-path/dummy.d b/test/describe-dependency-2/some-extra-string-import-path/dummy.d new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-dependency-2/some-extra-string-import-path/dummy.d @@ -0,0 +1 @@ + diff --git a/test/describe-dependency-2/some-path/dummy.d b/test/describe-dependency-2/some-path/dummy.d new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-dependency-2/some-path/dummy.d @@ -0,0 +1 @@ + diff --git a/test/describe-project/.no_build b/test/describe-project/.no_build new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-project/.no_build @@ -0,0 +1 @@ + diff --git a/test/describe-project/dub.json b/test/describe-project/dub.json new file mode 100644 index 0000000..8adf13f --- /dev/null +++ b/test/describe-project/dub.json @@ -0,0 +1,19 @@ +{ + "name": "describe-project", + "targetType": "sourceLibrary", + "description": "A test describe project", + "authors": ["nobody"], + "homepage": "fake.com", + "license": "BSD 2-clause", + "copyright": "Copyright © 2015, nobody", + "dependencies": { + "describe-dependency-1": { + "version": "1.0", + "path": "../describe-dependency-1" + }, + "describe-dependency-2": { + "version": "1.0", + "path": "../describe-dependency-2" + } + } +} diff --git a/test/describe-project/src/dummy.d b/test/describe-project/src/dummy.d new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-project/src/dummy.d @@ -0,0 +1 @@ + diff --git a/test/describe-project/views/dummy.d b/test/describe-project/views/dummy.d new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/test/describe-project/views/dummy.d @@ -0,0 +1 @@ + diff --git a/test/run-unittest.sh b/test/run-unittest.sh index ad0a219..ccd0831 100755 --- a/test/run-unittest.sh +++ b/test/run-unittest.sh @@ -5,10 +5,14 @@ exit 1 } +export -f die + function log() { echo -e "\033[0;33m[INFO] "$@"\033[0m" } +export -f log + if [ -z ${DUB} ]; then die 'Error: Variable $DUB must be defined to run the tests.' fi @@ -23,7 +27,7 @@ for script in $(ls $CURR_DIR/*.sh); do if [ "$script" = "$(readlink -f ${BASH_SOURCE[0]})" ]; then continue; fi log "Running $script..." - DUB=$DUB COMPILER=$COMPILER $script || die "Script failure." + DUB=$DUB COMPILER=$COMPILER CURR_DIR="$CURR_DIR" $script || die "Script failure." done for pack in $(ls -d $CURR_DIR/*/); do