diff --git a/changelog/addcommand.dd b/changelog/addcommand.dd index d3ee0bd..55e9e2e 100644 --- a/changelog/addcommand.dd +++ b/changelog/addcommand.dd @@ -1,11 +1,30 @@ Add Command -The `add` command adds a dependency to the dub.json/dub.sdl file. +The `add` command adds a dependency to the dub.json/dub.sdl recipe file. -Running `dub add vibe-d` is equivalent to manually adding the following line to dub.sdl (X.Y.Z represents the latest version): +Running `dub add vibe-d` queries the latest version for vibe-d from the +registry, then rewrites your recipe file with the new dependency added. + +dub.json: +------ + "dependencies": { + "vibe-d": "~>X.Y.Z" + } +------ + +dub.sdl: +------ dependency "vibe-d" version="~>X.Y.Z" +------ -Or the following in dub.json: -"dependencies": { - "vibe-d": "~>X.Y.Z" -} +It is also possible to add multiple packages at once and explicitly add a +simple $(LINK2 version specification,http://code.dlang.org/package-format?lang=json#version-specs) +for some of them. + +For example the command `dub add vibe-d='~>0.8.2' mir-algorithm=3.1.21` would +add the given 2 dependencies to the recipe file without querying the registry. + +Packages with and without version-specifier can be mixed in a single invocation. + +The can also be used to overwrite existing dependencies of the same name with +different version specifications. diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 759dc45..0f7e1dc 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -559,17 +559,9 @@ p.copyright = input("Copyright string", copyrightString); while (true) { - auto depname = input("Add dependency (leave empty to skip)", null); - if (!depname.length) break; - try { - auto ver = dub.getLatestVersion(depname); - auto dep = ver.isBranch ? Dependency(ver) : Dependency("~>" ~ ver.toString()); - p.buildSettings.dependencies[depname] = dep; - logInfo("Added dependency %s %s", depname, dep.versionSpec); - } catch (Exception e) { - logError("Could not find package '%s'.", depname); - logDebug("Full error: %s", e.toString().sanitize); - } + auto depspec = input("Add dependency (leave empty to skip)", null); + if (!depspec.length) break; + addDependency(dub, p, depspec); } } @@ -1154,12 +1146,13 @@ this() { this.name = "add"; - this.argumentsPattern = ""; + this.argumentsPattern = "[=] []"; this.description = "Adds dependencies to the package file."; this.helpText = [ "Adds as dependencies.", "", - "Running \"dub add \" is the same as adding to the \"dependencies\" section in dub.json/dub.sdl." + "Running \"dub add \" is the same as adding to the \"dependencies\" section in dub.json/dub.sdl.", + "If no version is specified for one of the packages, dub will query the registry for the latest version." ]; } @@ -1172,22 +1165,14 @@ enforceUsage(free_args.length != 0, "Expected one or more arguments."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); - string filetype = existsFile(dub.rootPath ~ "dub.json") ? "json" : "sdl"; - foreach (depname; free_args) { - try { - auto ver = dub.getLatestVersion(depname); - auto dep = ver.isBranch ? Dependency(ver) : Dependency("~>" ~ ver.toString()); - auto pkg = readPackageRecipe(dub.rootPath ~ ("dub." ~ filetype)); + if (!loadCwdPackage(dub, true)) return 1; + auto recipe = dub.project.rootPackage.rawRecipe.clone; - pkg.buildSettings.dependencies[depname] = dep; - writePackageRecipe(dub.rootPath ~ ("dub." ~ filetype), pkg); - - logInfo("Added dependency %s %s", depname, dep.versionSpec); - } catch (Exception e) { - logError("Could not find package '%s'.", depname); - logDebug("Full error: %s", e.toString().sanitize); - } + foreach (depspec; free_args) { + if (!addDependency(dub, recipe, depspec)) + return 1; } + writePackageRecipe(dub.project.rootPackage.recipePath, recipe); return 0; } @@ -2150,3 +2135,27 @@ { logWarn("The '%s' Command was renamed to '%s'. Please update your scripts.", prev, curr); } + +private bool addDependency(Dub dub, ref PackageRecipe recipe, string depspec) +{ + Dependency dep; + // split = + auto parts = depspec.findSplit("="); + auto depname = parts[0]; + if (!parts[1].empty) + dep = Dependency(parts[2]); + else + { + try { + auto ver = dub.getLatestVersion(depname); + dep = ver.isBranch ? Dependency(ver) : Dependency("~>" ~ ver.toString()); + } catch (Exception e) { + logError("Could not find package '%s'.", depname); + logDebug("Full error: %s", e.toString().sanitize); + return false; + } + } + recipe.buildSettings.dependencies[depname] = dep; + logInfo("Adding dependency %s %s", depname, dep.versionSpec); + return true; +} diff --git a/test/issue1574-addcommand.sh b/test/issue1574-addcommand.sh index c2fb1c7..002acb1 100755 --- a/test/issue1574-addcommand.sh +++ b/test/issue1574-addcommand.sh @@ -19,14 +19,18 @@ trap cleanup EXIT -$DUB init -n $tempDir +$DUB init --non-interactive --format=json $tempDir cd $tempDir echo "import gitcompatibledubpackage.subdir.file; void main(){}" > source/app.d - $DUB add gitcompatibledubpackage --skip-registry=all --registry=http://localhost:$PORT - -#if dub fails to compile, that means that the "import mir.math.common" did not work -if ! $DUB build; then - die "Add command failed" +grep -q '"gitcompatibledubpackage"\s*:\s*"~>1\.0\.4"' dub.json +$DUB add gitcompatibledubpackage=1.0.2 non-existing-issue1574-pkg='~>9.8.7' --skip-registry=all +grep -q '"gitcompatibledubpackage"\s*:\s*"1\.0\.2"' dub.json +grep -q '"non-existing-issue1574-pkg"\s*:\s*"~>9\.8\.7"' dub.json +if $DUB add foo=1.2.3 gitcompatibledubpackage='~>a.b.c' --skip-registry=all; then + die $LINENO 'Adding non-semver spec should error' +fi +if grep -q '"foo"' dub.json; then + die $LINENO 'Failing add command should not write recipe file' fi