diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 8b97305..4e0932c 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -560,6 +560,7 @@ Variant value; string names; string[] helpText; + bool hidden; } private { string[] m_args; @@ -608,7 +609,7 @@ */ @property const(Arg)[] recognizedArgs() { return m_recognizedArgs; } - void getopt(T)(string names, T* var, string[] help_text = null) + void getopt(T)(string names, T* var, string[] help_text = null, bool hidden=false) { foreach (ref arg; m_recognizedArgs) if (names == arg.names) { @@ -621,6 +622,7 @@ arg.defaultValue = *var; arg.names = names; arg.helpText = help_text; + arg.hidden = hidden; m_args.getopt(config.passThrough, names, var); arg.value = *var; m_recognizedArgs ~= arg; @@ -898,7 +900,7 @@ p.description = input("Description", p.description); p.authors = input("Author name", author).split(",").map!(a => a.strip).array; p.license = input("License", p.license); - string copyrightString = format("Copyright © %s, %-(%s, %)", Clock.currTime().year, p.authors); + string copyrightString = .format("Copyright © %s, %-(%s, %)", Clock.currTime().year, p.authors); p.copyright = input("Copyright string", copyrightString); while (true) { @@ -1087,7 +1089,7 @@ this() @safe pure nothrow { this.name = "generate"; - this.argumentsPattern = " []"; + this.argumentsPattern = " [[@]]"; this.description = "Generates project files using the specified generator"; this.helpText = [ "Generates project files using one of the supported generators:", @@ -1184,7 +1186,7 @@ this() @safe pure nothrow { this.name = "build"; - this.argumentsPattern = "[]"; + this.argumentsPattern = "[[@]]"; this.description = "Builds a package (uses the main package in the current working directory by default)"; this.helpText = [ "Builds a package (uses the main package in the current working directory by default)" @@ -1287,7 +1289,7 @@ this() @safe pure nothrow { this.name = "run"; - this.argumentsPattern = "[]"; + this.argumentsPattern = "[[@]]"; this.description = "Builds and runs a package (default command)"; this.helpText = [ "Builds and runs a package (uses the main package in the current working directory by default)" @@ -1322,7 +1324,7 @@ this() @safe pure nothrow { this.name = "test"; - this.argumentsPattern = "[]"; + this.argumentsPattern = "[[@]]"; this.description = "Executes the tests of the selected package"; this.helpText = [ `Builds the package and executes all contained unit tests.`, @@ -1411,7 +1413,7 @@ this() @safe pure nothrow { this.name = "lint"; - this.argumentsPattern = "[]"; + this.argumentsPattern = "[[@]]"; this.description = "Executes the linter tests of the selected package"; this.helpText = [ `Builds the package and executes D-Scanner linter tests.` @@ -1496,7 +1498,7 @@ this() @safe pure nothrow { this.name = "describe"; - this.argumentsPattern = "[]"; + 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 " ~ @@ -1777,7 +1779,7 @@ args.getopt("version", &m_version, [ "Use the specified version/branch instead of the latest available match", "The remove command also accepts \"*\" here as a wildcard to remove all versions of the package from the specified location" - ]); + ], true); // hide --version from help args.getopt("force-remove", &m_forceRemove, [ "Deprecated option that does nothing" @@ -1791,7 +1793,7 @@ this() @safe pure nothrow { this.name = "fetch"; - this.argumentsPattern = "[@]"; + this.argumentsPattern = "[@]"; this.description = "Manually retrieves and caches a package"; this.helpText = [ "Note: Use \"dub add \" if you just want to use a certain package as a dependency, you don't have to explicitly fetch packages.", @@ -1826,8 +1828,11 @@ FetchOptions fetchOpts; fetchOpts |= FetchOptions.forceBranchUpgrade; - if (m_version.length) dub.fetch(name, Dependency(m_version), location, fetchOpts); - else if (name.canFind("@", "=")) { + if (m_version.length) { // remove then --version removed + enforceUsage(!name.canFindVersionSplitter, "Double version spec not allowed."); + logWarn("The '--version' parameter was deprecated, use %s@%s. Please update your scripts.", name, m_version); + dub.fetch(name, Dependency(m_version), location, fetchOpts); + } else if (name.canFindVersionSplitter) { const parts = name.splitPackageName; dub.fetch(parts.name, Dependency(parts.version_), location, fetchOpts); } else { @@ -1870,7 +1875,7 @@ this() @safe pure nothrow { this.name = "remove"; - this.argumentsPattern = ""; + this.argumentsPattern = "[@]"; this.description = "Removes a cached package"; this.helpText = [ "Removes a package that is cached on the local system." @@ -1918,10 +1923,18 @@ } } - if (m_nonInteractive || !m_version.empty) + if (!m_version.empty) { // remove then --version removed + enforceUsage(!package_id.canFindVersionSplitter, "Double version spec not allowed."); + logWarn("The '--version' parameter was deprecated, use %s@%s. Please update your scripts.", package_id, m_version); dub.remove(package_id, m_version, location); - else - dub.remove(package_id, location, &resolveVersion); + } else { + const parts = package_id.splitPackageName; + if (m_nonInteractive || parts.version_.length) { + dub.remove(parts.name, parts.version_, location); + } else { + dub.remove(package_id, location, &resolveVersion); + } + } return 0; } } @@ -2596,6 +2609,7 @@ private void writeOptions(CommandArgs args) { foreach (arg; args.recognizedArgs) { + if (arg.hidden) continue; auto names = arg.names.split("|"); assert(names.length == 1 || names.length == 2); string sarg = names[0].length == 1 ? names[0] : null; @@ -2736,3 +2750,20 @@ assert(splitPackageName("foo@~>1.0.1") == PackageAndVersion("foo", "~>1.0.1")); assert(splitPackageName("foo@<1.0.1") == PackageAndVersion("foo", "<1.0.1")); } + +private ulong canFindVersionSplitter(string packageName) +{ + // see splitPackageName + return packageName.canFind("@", "="); +} + +unittest +{ + assert(!canFindVersionSplitter("foo")); + assert(canFindVersionSplitter("foo=1.0.1")); + assert(canFindVersionSplitter("foo@1.0.1")); + assert(canFindVersionSplitter("foo@==1.0.1")); + assert(canFindVersionSplitter("foo@>=1.0.1")); + assert(canFindVersionSplitter("foo@~>1.0.1")); + assert(canFindVersionSplitter("foo@<1.0.1")); +} diff --git a/test/.gitignore b/test/.gitignore index 471c344..e8ce8bd 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -16,4 +16,4 @@ version-spec/**/foo.cmake version-spec/**/foo -/test_registry \ No newline at end of file +/test_registry diff --git a/test/version-spec.sh b/test/version-spec.sh index 7add456..25e78b7 100755 --- a/test/version-spec.sh +++ b/test/version-spec.sh @@ -30,4 +30,12 @@ [[ $($DUB run -n foo@0.1.0 | tail -1) == 'old-foo' ]] || false $DUB remove-local "$CURR_DIR/version-spec/newfoo" -$DUB remove-local "$CURR_DIR/version-spec/oldfoo" \ No newline at end of file +$DUB remove-local "$CURR_DIR/version-spec/oldfoo" + +$DUB fetch dub@1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] +$DUB fetch dub=1.10.0 && [ -d $HOME/.dub/packages/dub-1.10.0/dub ] +$DUB remove dub@1.9.0 +$DUB remove dub=1.10.0 +if [ -d $HOME/.dub/packages/dub-1.9.0/dub ] || [ -d $HOME/.dub/packages/dub-1.10.0/dub ]; then + die $LINENO 'Failed to remove specified versions' +fi diff --git a/test/version-spec/newfoo/dub.sdl b/test/version-spec/newfoo/dub.sdl index b5f6277..f1d06a6 100644 --- a/test/version-spec/newfoo/dub.sdl +++ b/test/version-spec/newfoo/dub.sdl @@ -1,3 +1,3 @@ name "foo" version "1.0.0" -targetType "executable" \ No newline at end of file +targetType "executable" diff --git a/test/version-spec/oldfoo/dub.sdl b/test/version-spec/oldfoo/dub.sdl index 7f571c0..bb3a51c 100644 --- a/test/version-spec/oldfoo/dub.sdl +++ b/test/version-spec/oldfoo/dub.sdl @@ -1,3 +1,3 @@ name "foo" version "0.1.0" -targetType "executable" \ No newline at end of file +targetType "executable"