diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index a5b705f..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,4 +0,0 @@ -# https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository - -open_collective: dlang -custom: https://dlang.org/foundation/donate.html diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index caba05c..23a03ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ matrix: # Latest stable version, update at will os: [ macOS-10.15, ubuntu-18.04, windows-2019 ] - dc: [ dmd-2.092.0, ldc-1.21.0, dmd-master, ldc-master ] + dc: [ dmd-2.093.1, ldc-1.23.0, dmd-master, ldc-master ] runs-on: ${{ matrix.os }} steps: @@ -39,11 +39,12 @@ if: runner.os == 'macOS' run: | brew install pkg-config coreutils + echo ::set-env name=PKG_CONFIG_PATH::/usr/local/opt/openssl@1.1/lib/pkgconfig/ - name: '[Linux] Install dependencies' if: runner.os == 'Linux' run: | - sudo apt-get install -y libcurl4-openssl-dev netcat + sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev netcat # Compiler to test with - name: Prepare compiler @@ -60,7 +61,7 @@ env: COVERAGE: false # The value doesn't matter as long as it's > 2.087 - FRONTEND: 2.091.0 + FRONTEND: 2.093.0 run: | ./scripts/ci/travis.sh diff --git a/.travis.yml b/.travis.yml index 15b0105..72fc2ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,20 +14,18 @@ - d: gdc include: - stage: test - d: dmd-2.090.1 - env: [FRONTEND=2.090] + d: dmd-2.093.0 + env: [FRONTEND=2.093, COVERAGE=true] - d: dmd-2.089.1,dub env: [FRONTEND=2.089] - - d: dmd-2.077.1,dub - env: [FRONTEND=2.077, COVERAGE=true] - - d: dmd-2.076.1,dub - env: [FRONTEND=2.076] - - d: ldc-1.20.0 + - d: dmd-2.083.1,dub + env: [FRONTEND=2.083] + - d: ldc-1.22.0 + env: [FRONTEND=2.092] + - d: ldc-1.20.0,dub env: [FRONTEND=2.090] - - d: ldc-1.19.0,dub - env: [FRONTEND=2.089] - stage: deploy - d: ldc-1.20.0,dub + d: ldc-1.22.0,dub os: osx script: echo "Deploying to GitHub releases ..." && ./scripts/ci/release.sh deploy: @@ -38,7 +36,7 @@ api_key: $GH_REPO_TOKEN on: tags: true - - d: ldc-1.20.0,dub + - d: ldc-1.22.0,dub script: echo "Deploying to GitHub releases ..." && ./scripts/ci/release.sh env: [ARCH=32] addons: @@ -54,7 +52,7 @@ api_key: $GH_REPO_TOKEN on: tags: true - - d: ldc-1.20.0,dub + - d: ldc-1.22.0,dub script: echo "Deploying to GitHub releases ..." && ./scripts/ci/release.sh deploy: - provider: releases @@ -64,7 +62,7 @@ api_key: $GH_REPO_TOKEN on: tags: true - - d: ldc-1.20.0,dub + - d: ldc-1.22.0,dub script: echo "Deploying to GitHub releases (win32) ..." && ./scripts/ci/release-windows.sh addons: apt: @@ -78,7 +76,7 @@ api_key: $GH_REPO_TOKEN on: tags: true - - d: ldc-1.20.0,dub + - d: ldc-1.22.0,dub script: echo "Deploying to GitHub releases (win64) ..." && ARCH=64 ./scripts/ci/release-windows.sh addons: apt: diff --git a/changelog/add_x86_omf.dd b/changelog/add_x86_omf.dd new file mode 100644 index 0000000..dab726c --- /dev/null +++ b/changelog/add_x86_omf.dd @@ -0,0 +1,5 @@ +Added architecture x86_omf for windows-dmd + +On windows dmd the x86_omf architecture can now be used as platform +specification using `--arch=x86_omf`. This is currently equivalent to +the previously existing `--arch=x86` argument. diff --git a/changelog/dub-remove.dd b/changelog/dub-remove.dd new file mode 100644 index 0000000..b297d45 --- /dev/null +++ b/changelog/dub-remove.dd @@ -0,0 +1,9 @@ +`dub remove --non-interactive` will now remove all packages by default + +When calling a command with a package name and no version specification, +the latest version is usually assumed. +While this behavior makes sense for `dub fetch` or `dub run`, +it can come as a surprise when cleaning up local packages through `dub remove`, +and so previous version would simply error out when more than one version was available. +From this version, `dub remove -n $PKGNAME` will just remove all cached versions +of the package named `$PKGNAME`, without asking you to use `$PKGNAME@*`. diff --git a/changelog/enforce_proper_package_loading.dd b/changelog/enforce_proper_package_loading.dd new file mode 100644 index 0000000..6faa00f --- /dev/null +++ b/changelog/enforce_proper_package_loading.dd @@ -0,0 +1,8 @@ +Running `dub upgrade` on a package-less folder is now a no-op + +Prior to this change, accidentally running `dub upgrade` in a folder +where no `dub.json` / `dub.sdl` was present would leave you with a +`dub.selections.json` and, in some instances, an empty `.dub` folder. +This has been fixed and running `dub upgrade` where one shouldn't +will now only generate a friendly error message. + diff --git a/changelog/git-paths.dd b/changelog/git-paths.dd new file mode 100644 index 0000000..33447b7 --- /dev/null +++ b/changelog/git-paths.dd @@ -0,0 +1,16 @@ +Support dependencies as git url with exact commit + +Git repositories can be directly used by dub as dependencies. + +dub.json: +------- +{ + "name": "git-dependency", + "dependencies": { + "gitcompatibledubpackage": { + "repository": "git+https://github.com/dlang-community/gitcompatibledubpackage.git", + "version": "ccb31bf6a655437176ec02e04c2305a8c7c90d67" + } + } +} +------- diff --git a/changelog/version.dd b/changelog/version.dd new file mode 100644 index 0000000..9f16b53 --- /dev/null +++ b/changelog/version.dd @@ -0,0 +1,8 @@ +All commands now support `package[@]`, `--version` is deprecated + +`dub` commands had some disparity in their version handling. +Most commands accepting a package name (e.g. `dub fetch` or `dub run`) supported +either `package[@version-spec]`, or supported only `package` and accepted an +option `--version=`. +The latter form has now been deprecated and all commands now accept `package[@]`. +Note that the absence of `@` still means "latest version" (except for `remove`). diff --git a/dub.sdl b/dub.sdl index 3f17241..91894bc 100644 --- a/dub.sdl +++ b/dub.sdl @@ -22,13 +22,13 @@ } configuration "library-nonet" { - dependency "vibe-d:http" version=">=0.7.30 <=0.9.0" optional=true + dependency "vibe-d:http" version=">=0.7.30 <0.10.0" optional=true targetType "library" excludedSourceFiles "source/app.d" } configuration "dynamic-library-nonet" { - dependency "vibe-d:http" version=">=0.7.30 <=0.9.0" optional=true + dependency "vibe-d:http" version=">=0.7.30 <0.10.0" optional=true targetType "dynamicLibrary" excludedSourceFiles "source/app.d" } diff --git a/dub.selections.json b/dub.selections.json index 3f215bf..e00205d 100644 --- a/dub.selections.json +++ b/dub.selections.json @@ -1,19 +1,19 @@ { "fileVersion": 1, "versions": { - "botan": "1.12.10", + "botan": "1.12.18", "botan-math": "1.0.3", - "diet-ng": "1.6.0", - "eventcore": "0.8.48", - "libasync": "0.8.4", + "diet-ng": "1.7.3", + "eventcore": "0.9.9", + "libasync": "0.8.6", "libev": "5.0.0+4.04", "libevent": "2.0.2+2.0.16", - "memutils": "0.4.13", + "memutils": "1.0.4", "mir-linux-kernel": "1.0.1", "openssl": "1.1.6+1.0.1g", "stdx-allocator": "2.77.5", - "taggedalgebraic": "0.11.8", - "vibe-core": "1.8.1", - "vibe-d": "0.8.6" + "taggedalgebraic": "0.11.17", + "vibe-core": "1.10.1", + "vibe-d": "0.9.2" } } diff --git a/scripts/ci/setup-ldc-windows.sh b/scripts/ci/setup-ldc-windows.sh index c5a2533..e95881e 100644 --- a/scripts/ci/setup-ldc-windows.sh +++ b/scripts/ci/setup-ldc-windows.sh @@ -4,7 +4,7 @@ # Make sure this version matches the version of LDC2 used in .travis.yml, # otherwise the compiler and the lib used might mismatch. -LDC_VERSION="1.20.0" +LDC_VERSION="1.22.0" ARCH=${ARCH:-32} VERSION=$(git describe --abbrev=0 --tags) OS=windows diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 666b79d..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; @@ -986,6 +988,13 @@ ]); } + protected void setupVersionPackage(Dub dub, string str_package_info, string default_build_type = "debug") + { + PackageAndVersion package_info = splitPackageName(str_package_info); + Version ver = package_info.version_.length ? Version(package_info.version_) : Version.unknown; + setupPackage(dub, package_info.name, default_build_type, ver); + } + protected void setupPackage(Dub dub, string package_name, string default_build_type = "debug", Version ver = Version.unknown) { if (!m_compilerName.length) m_compilerName = dub.defaultCompiler; @@ -1055,7 +1064,10 @@ auto pack = ver.isUnknown ? dub.packageManager.getLatestPackage(package_name) : dub.packageManager.getPackage(package_name, ver); - enforce(pack, "Failed to find a package named '"~package_name~"' locally."); + + enforce(pack, format!"Failed to find a package named '%s%s' locally."(package_name, + ver.isUnknown ? "" : "@" ~ ver.toString() + )); logInfo("Building package %s in %s", pack.name, pack.path.toNativeString()); dub.loadPackage(pack); return true; @@ -1077,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:", @@ -1115,19 +1127,17 @@ override int execute(Dub dub, string[] free_args, string[] app_args) { - PackageAndVersion package_info; + string str_package_info; if (!m_generator.length) { enforceUsage(free_args.length >= 1 && free_args.length <= 2, "Expected one or two arguments."); m_generator = free_args[0]; - if (free_args.length >= 2) package_info = splitPackageName(free_args[1]); + if (free_args.length >= 2) str_package_info = free_args[1]; } else { enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); - if (free_args.length >= 1) package_info = splitPackageName(free_args[0]); + if (free_args.length >= 1) str_package_info = free_args[0]; } - string package_name = package_info.name; - Version package_version = package_info.version_.length == 0 ? Version.unknown : Version(package_info.version_); - setupPackage(dub, package_name, "debug", package_version); + setupVersionPackage(dub, str_package_info, "debug"); if (m_printBuilds) { // FIXME: use actual package data logInfo("Available build types:"); @@ -1176,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)" @@ -1279,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)" @@ -1314,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.`, @@ -1363,11 +1373,11 @@ override int execute(Dub dub, string[] free_args, string[] app_args) { - string package_name; + string str_package_info; enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); - if (free_args.length >= 1) package_name = free_args[0]; + if (free_args.length >= 1) str_package_info = free_args[0]; - setupPackage(dub, package_name, "unittest", Version.unknown); + setupVersionPackage(dub, str_package_info, "unittest"); GeneratorSettings settings; settings.platform = m_buildPlatform; @@ -1403,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.` @@ -1454,9 +1464,9 @@ override int execute(Dub dub, string[] free_args, string[] app_args) { - string package_name; + string str_package_info; enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); - if (free_args.length >= 1) package_name = free_args[0]; + if (free_args.length >= 1) str_package_info = free_args[0]; string[] args; if (!m_syntaxCheck && !m_styleCheck && !m_report && app_args.length == 0) { m_styleCheck = true; } @@ -1470,7 +1480,7 @@ foreach (import_path; m_importPaths) args ~= ["-I", import_path]; if (m_config) args ~= ["--config", m_config]; - setupPackage(dub, package_name); + setupVersionPackage(dub, str_package_info); dub.lintProject(args ~ app_args); return 0; } @@ -1488,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 " ~ @@ -1567,10 +1577,10 @@ setLogLevel(max(ll, LogLevel.warn)); scope (exit) setLogLevel(ll); - string package_name; + string str_package_info; enforceUsage(free_args.length <= 1, "Expected one or zero arguments."); - if (free_args.length >= 1) package_name = free_args[0]; - setupPackage(dub, package_name); + if (free_args.length >= 1) str_package_info = free_args[0]; + setupVersionPackage(dub, str_package_info); m_defaultConfig = dub.project.getDefaultConfiguration(m_buildPlatform); @@ -1747,7 +1757,7 @@ enforceUsage(free_args.length <= 1, "Unexpected arguments."); enforceUsage(app_args.length == 0, "Unexpected application arguments."); enforceUsage(!m_verify, "--verify is not yet implemented."); - dub.loadPackage(); + enforce(loadCwdPackage(dub, true), "Failed to load package."); logInfo("Upgrading project in %s", dub.projectPath.toNativeString()); auto options = UpgradeOptions.upgrade|UpgradeOptions.select; if (m_missingOnly) options &= ~UpgradeOptions.upgrade; @@ -1769,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" @@ -1783,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.", @@ -1818,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 { @@ -1862,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." @@ -1910,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; } } @@ -2239,6 +2260,7 @@ string m_programRegex; string m_testPackage; bool m_combined; + bool m_noRedirect; } this() @safe pure nothrow @@ -2266,6 +2288,7 @@ args.getopt("program-regex", &m_programRegex, ["A regular expression used to match against the program output"]); args.getopt("test-package", &m_testPackage, ["Perform a test run - usually only used internally"]); args.getopt("combined", &m_combined, ["Builds multiple packages with one compiler run"]); + args.getopt("no-redirect", &m_noRedirect, ["Don't redirect stdout/stderr streams of the test command"]); super.prepare(args); // speed up loading when in test mode @@ -2382,7 +2405,7 @@ logInfo("Executing dustmite..."); auto testcmd = appender!string(); - testcmd.formattedWrite("%s dustmite --vquiet --test-package=%s --build=%s --config=%s", + testcmd.formattedWrite("%s dustmite --test-package=%s --build=%s --config=%s", thisExePath, prj.name, m_buildType, m_buildConfig); if (m_compilerName.length) testcmd.formattedWrite(" \"--compiler=%s\"", m_compilerName); @@ -2394,9 +2417,17 @@ if (m_programStatusCode != int.min) testcmd.formattedWrite(" --program-status=%s", m_programStatusCode); if (m_programRegex.length) testcmd.formattedWrite(" \"--program-regex=%s\"", m_programRegex); if (m_combined) testcmd ~= " --combined"; + + // --vquiet swallows dustmite's output ... + if (!m_noRedirect) testcmd ~= " --vquiet"; + // TODO: pass *all* original parameters logDiagnostic("Running dustmite: %s", testcmd); - auto dmpid = spawnProcess(["dustmite", path.toNativeString(), testcmd.data]); + + string[] extraArgs; + if (m_noRedirect) extraArgs ~= "--no-redirect"; + const cmd = "dustmite" ~ extraArgs ~ [path.toNativeString(), testcmd.data]; + auto dmpid = spawnProcess(cmd); return dmpid.wait(); } return 0; @@ -2578,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; @@ -2718,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/source/dub/compilers/compiler.d b/source/dub/compilers/compiler.d index 0f4fb32..2eb8a9a 100644 --- a/source/dub/compilers/compiler.d +++ b/source/dub/compilers/compiler.d @@ -72,7 +72,7 @@ /// Replaces high level fields with low level fields and converts /// dmd flags to compiler-specific flags - void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting supported_fields = BuildSetting.all) const; + void prepareBuildSettings(ref BuildSettings settings, const scope ref BuildPlatform platform, BuildSetting supported_fields = BuildSetting.all) const; /// Removes any dflags that match one of the BuildOptions values and populates the BuildSettings.options field. void extractBuildOptions(ref BuildSettings settings) const; @@ -156,12 +156,6 @@ // cmdline option does not lead to the same string being found among // `build_platform.architecture`, as it's brittle and doesn't work with triples. if (build_platform.compiler != "ldc") { - // Hack: see #1059 - // When compiling with --arch=x86_mscoff build_platform.architecture is equal to ["x86"] and canFind below is false. - // This hack prevents unnesessary warning 'Failed to apply the selected architecture x86_mscoff. Got ["x86"]'. - // And also makes "x86_mscoff" available as a platform specifier in the package recipe - if (arch_override == "x86_mscoff") - build_platform.architecture ~= arch_override; if (arch_override.length && !build_platform.architecture.canFind(arch_override)) { logWarn(`Failed to apply the selected architecture %s. Got %s.`, arch_override, build_platform.architecture); diff --git a/source/dub/compilers/dmd.d b/source/dub/compilers/dmd.d index 70df37e..6f55ee0 100644 --- a/source/dub/compilers/dmd.d +++ b/source/dub/compilers/dmd.d @@ -120,6 +120,7 @@ } break; case "x86": arch_flags = ["-m32"]; break; + case "x86_omf": arch_flags = ["-m32"]; break; case "x86_64": arch_flags = ["-m64"]; break; case "x86_mscoff": arch_flags = ["-m32mscoff"]; break; } @@ -131,8 +132,56 @@ arch_override ); } + version (Windows) version (DigitalMars) unittest + { + BuildSettings settings; + auto compiler = new DMDCompiler; + auto bp = compiler.determinePlatform(settings, "dmd", "x86"); + assert(bp.platform.canFind("windows")); + assert(bp.architecture.canFind("x86")); + assert(bp.architecture.canFind("x86_omf")); + assert(!bp.architecture.canFind("x86_mscoff")); + settings = BuildSettings.init; + bp = compiler.determinePlatform(settings, "dmd", "x86_omf"); + assert(bp.platform.canFind("windows")); + assert(bp.architecture.canFind("x86")); + assert(bp.architecture.canFind("x86_omf")); + assert(!bp.architecture.canFind("x86_mscoff")); + settings = BuildSettings.init; + bp = compiler.determinePlatform(settings, "dmd", "x86_mscoff"); + assert(bp.platform.canFind("windows")); + assert(bp.architecture.canFind("x86")); + assert(!bp.architecture.canFind("x86_omf")); + assert(bp.architecture.canFind("x86_mscoff")); + settings = BuildSettings.init; + bp = compiler.determinePlatform(settings, "dmd", "x86_64"); + assert(bp.platform.canFind("windows")); + assert(bp.architecture.canFind("x86_64")); + assert(!bp.architecture.canFind("x86")); + assert(!bp.architecture.canFind("x86_omf")); + assert(!bp.architecture.canFind("x86_mscoff")); + settings = BuildSettings.init; + bp = compiler.determinePlatform(settings, "dmd", ""); + if (!isWow64.isNull && !isWow64.get) assert(bp.architecture.canFind("x86")); + if (!isWow64.isNull && !isWow64.get) assert(bp.architecture.canFind("x86_mscoff")); + if (!isWow64.isNull && !isWow64.get) assert(!bp.architecture.canFind("x86_omf")); + if (!isWow64.isNull && isWow64.get) assert(bp.architecture.canFind("x86_64")); + } - void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const + version (LDC) unittest { + BuildSettings settings; + auto compiler = new DMDCompiler; + auto bp = compiler.determinePlatform(settings, "ldmd2", "x86"); + assert(bp.architecture.canFind("x86")); + assert(!bp.architecture.canFind("x86_omf")); + bp = compiler.determinePlatform(settings, "ldmd2", ""); + version (X86) assert(bp.architecture.canFind("x86")); + version (X86_64) assert(bp.architecture.canFind("x86_64")); + assert(!bp.architecture.canFind("x86_omf")); + } + + void prepareBuildSettings(ref BuildSettings settings, const scope ref BuildPlatform platform, + BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); diff --git a/source/dub/compilers/gdc.d b/source/dub/compilers/gdc.d index bb0c27b..cec2dbc 100644 --- a/source/dub/compilers/gdc.d +++ b/source/dub/compilers/gdc.d @@ -85,7 +85,7 @@ ); } - void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const + void prepareBuildSettings(ref BuildSettings settings, const scope ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); diff --git a/source/dub/compilers/ldc.d b/source/dub/compilers/ldc.d index f62e964..8273e97 100644 --- a/source/dub/compilers/ldc.d +++ b/source/dub/compilers/ldc.d @@ -101,7 +101,7 @@ ); } - void prepareBuildSettings(ref BuildSettings settings, in ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const + void prepareBuildSettings(ref BuildSettings settings, const scope ref BuildPlatform platform, BuildSetting fields = BuildSetting.all) const { enforceBuildRequirements(settings); diff --git a/source/dub/compilers/utils.d b/source/dub/compilers/utils.d index 12c55f3..171f487 100644 --- a/source/dub/compilers/utils.d +++ b/source/dub/compilers/utils.d @@ -40,7 +40,7 @@ Linker files include static/dynamic libraries, resource files, object files and DLL definition files. */ -bool isLinkerFile(in ref BuildPlatform platform, string f) +bool isLinkerFile(const scope ref BuildPlatform platform, string f) { import std.path; switch (extension(f)) { @@ -79,7 +79,7 @@ This function tries to invoke "pkg-config" if possible and falls back to direct flag translation if that fails. */ -void resolveLibs(ref BuildSettings settings, in ref BuildPlatform platform) +void resolveLibs(ref BuildSettings settings, const scope ref BuildPlatform platform) { import std.string : format; import std.array : array; diff --git a/source/dub/dependency.d b/source/dub/dependency.d index f16edcc..c9b1515 100644 --- a/source/dub/dependency.d +++ b/source/dub/dependency.d @@ -34,7 +34,6 @@ Dependency spec; } - /** Represents a dependency specification. @@ -56,6 +55,7 @@ NativePath m_path; bool m_optional = false; bool m_default = false; + Repository m_repository; } /// A Dependency, which matches every valid version. @@ -93,11 +93,31 @@ m_path = path; } + /** Constructs a new dependency specification that matches a specific + Git reference. + */ + this(Repository repository, string spec) { + this.versionSpec = spec; + this.repository = repository; + } + /// If set, overrides any version based dependency selection. @property void path(NativePath value) { m_path = value; } /// ditto @property NativePath path() const { return m_path; } + /// If set, overrides any version based dependency selection. + @property void repository(Repository value) + { + m_repository = value; + } + + /// ditto + @property Repository repository() const + { + return m_repository; + } + /// Determines if the dependency is required or optional. @property bool optional() const { return m_optional; } /// ditto @@ -111,6 +131,9 @@ /// Returns true $(I iff) the version range only matches a specific version. @property bool isExactVersion() const { return m_versA == m_versB; } + /// Determines whether it is a Git dependency. + @property bool isSCM() const { return !repository.empty; } + /// Returns the exact version matched by the version range. @property Version version_() const { enforce(m_versA == m_versB, "Dependency "~this.versionSpec~" is no exact version."); @@ -167,7 +190,7 @@ ves = ves[1..$].expandVersion; m_versA = Version(ves); m_versB = Version(bumpIncompatibleVersion(ves) ~ "-0"); - } else if (ves[0] == Version.branchPrefix) { + } else if (ves[0] == Version.branchPrefix || ves.isGitHash) { m_inclusiveA = true; m_inclusiveB = true; m_versA = m_versB = Version(ves); @@ -218,7 +241,6 @@ string r; if (this == invalid) return "invalid"; - if (m_versA == m_versB && m_inclusiveA && m_inclusiveB) { // Special "==" case if (m_versA == Version.masterBranch) return "~master"; @@ -272,7 +294,12 @@ */ string toString()() const { - auto ret = versionSpec; + string ret; + + if (!repository.empty) { + ret ~= repository.toString~"#"; + } + ret ~= versionSpec; if (optional) { if (default_) ret ~= " (optional, default)"; else ret ~= " (optional)"; @@ -296,12 +323,13 @@ Json toJson() const @trusted { // NOTE Path and Json is @system in vibe.d 0.7.x and in the compatibility layer Json json; - if( path.empty && !optional ){ + if( path.empty && repository.empty && !optional ){ json = Json(this.versionSpec); } else { json = Json.emptyObject; json["version"] = this.versionSpec; if (!path.empty) json["path"] = path.toString(); + if (!repository.empty) json["repository"] = repository.toString; if (optional) json["optional"] = true; if (default_) json["default"] = true; } @@ -316,6 +344,15 @@ assert(d.toJson() == Json("1.0.0"), "Failed: " ~ d.toJson().toPrettyString()); } + @trusted unittest { + Dependency dependency = Dependency(Repository("git+http://localhost"), "1.0.0"); + Json expected = Json([ + "repository": Json("git+http://localhost"), + "version": Json("1.0.0") + ]); + assert(dependency.toJson() == expected, "Failed: " ~ dependency.toJson().toPrettyString()); + } + /** Constructs a new `Dependency` from its JSON representation. See `toJson` for a description of the JSON format. @@ -330,6 +367,12 @@ dep = Dependency.any; dep.path = NativePath(verspec["path"].get!string); + } else if (auto repository = "repository" in verspec) { + enforce("version" in verspec, "No version field specified!"); + enforce(repository.length > 0, "No repository field specified!"); + + dep = Dependency(Repository(repository.get!string), + verspec["version"].get!string); } else { enforce("version" in verspec, "No version field specified!"); auto ver = verspec["version"].get!string; @@ -411,6 +454,7 @@ A specification is valid if it can match at least one version. */ bool valid() const { + if (this.isSCM) return true; return m_versA <= m_versB && doCmp(m_inclusiveA && m_inclusiveB, m_versA, m_versB); } @@ -440,6 +484,7 @@ /// ditto bool matches(ref const(Version) v) const { if (this.matchesAny) return true; + if (this.isSCM) return true; //logDebug(" try match: %s with: %s", v, this); // Master only matches master if(m_versA.isBranch) { @@ -463,6 +508,13 @@ */ Dependency merge(ref const(Dependency) o) const { + if (this.isSCM) { + if (!o.isSCM) return this; + if (this.m_versA == o.m_versA) return this; + return invalid; + } + if (o.isSCM) return o; + if (this.matchesAny) return o; if (o.matchesAny) return this; if (m_versA.isBranch != o.m_versA.isBranch) return invalid; @@ -677,6 +729,80 @@ assert(Dependency("^1.2").versionSpec == "~>1.2"); // equivalent; prefer ~> } +/** + Represents an SCM repository. +*/ +struct Repository +{ + private string m_remote; + + private Kind m_kind; + + enum Kind + { + git, + } + + /** + Params: + remote = Repository remote. + */ + this(string remote) + { + if (remote.startsWith("git+")) + { + m_remote = remote["git+".length .. $]; + m_kind = Kind.git; + } + else + { + throw new Exception("Unsupported repository type"); + } + } + + string toString() nothrow pure @safe + { + if (empty) return null; + string kindRepresentation; + + final switch (kind) + { + case Kind.git: + kindRepresentation = "git"; + } + return kindRepresentation~"+"~remote; + } + + /** + Returns: + Repository URL or path. + */ + @property string remote() @nogc nothrow pure @safe + in { assert(m_remote !is null); } + body + { + return m_remote; + } + + /** + Returns: + Repository type. + */ + @property Kind kind() @nogc nothrow pure @safe + { + return m_kind; + } + + /** + Returns: + Whether the repository was initialized with an URL or path. + */ + @property bool empty() const @nogc nothrow pure @safe + { + return m_remote.empty; + } +} + /** Represents a version in semantic version format, or a branch identifier. @@ -705,7 +831,7 @@ this(string vers) { enforce(vers.length > 1, "Version strings must not be empty."); - if (vers[0] != branchPrefix && vers.ptr !is UNKNOWN_VERS.ptr) + if (vers[0] != branchPrefix && !vers.isGitHash && vers.ptr !is UNKNOWN_VERS.ptr) enforce(vers.isValidVersion(), "Invalid SemVer format: " ~ vers); m_version = vers; } @@ -719,6 +845,9 @@ bool opEquals(const Version oth) const { return opCmp(oth) == 0; } + /// Tests if this represents a hash instead of a version. + @property bool isSCM() const { return m_version.isGitHash; } + /// Tests if this represents a branch instead of a version. @property bool isBranch() const { return m_version.length > 0 && m_version[0] == branchPrefix; } @@ -730,7 +859,7 @@ Note that branches are always considered pre-release versions. */ @property bool isPreRelease() const { - if (isBranch) return true; + if (isBranch || isSCM) return true; return isPreReleaseVersion(m_version); } @@ -749,6 +878,13 @@ if (isUnknown || other.isUnknown) { throw new Exception("Can't compare unknown versions! (this: %s, other: %s)".format(this, other)); } + + if (isSCM || other.isSCM) { + if (!isSCM) return -1; + if (!other.isSCM) return 1; + return m_version == other.m_version ? 0 : 1; + } + if (isBranch || other.isBranch) { if(m_version == other.m_version) return 0; if (!isBranch) return 1; @@ -790,6 +926,7 @@ assert(a == b, "a == b with a:'1.0.0', b:'1.0.0' failed"); b = Version("2.0.0"); assert(a != b, "a != b with a:'1.0.0', b:'2.0.0' failed"); + a = Version.masterBranch; b = Version("~BRANCH"); assert(a != b, "a != b with a:MASTER, b:'~branch' failed"); @@ -829,4 +966,22 @@ assertThrown(a == b, "Failed: UNKNOWN == UNKNOWN"); assert(Version("1.0.0+a") == Version("1.0.0+b")); + + assert(Version("73535568b79a0b124bc1653002637a830ce0fcb8").isSCM); +} + +/// Determines whether the given string is a Git hash. +bool isGitHash(string hash) @nogc nothrow pure @safe +{ + import std.ascii : isHexDigit; + import std.utf : byCodeUnit; + + return hash.length >= 7 && hash.length <= 40 && hash.byCodeUnit.all!isHexDigit; +} + +@nogc nothrow pure @safe unittest { + assert(isGitHash("73535568b79a0b124bc1653002637a830ce0fcb8")); + assert(!isGitHash("735")); + assert(!isGitHash("73535568b79a0b124bc1-53002637a830ce0fcb8")); + assert(!isGitHash("73535568b79a0b124bg1")); } diff --git a/source/dub/dependencyresolver.d b/source/dub/dependencyresolver.d index 85e97de..eb4462c 100644 --- a/source/dub/dependencyresolver.d +++ b/source/dub/dependencyresolver.d @@ -45,8 +45,8 @@ ret ^= typeid(CONFIGS).getHash(&configs); return ret; } - bool opEqual(in ref TreeNodes other) const { return pack == other.pack && configs == other.configs; } - int opCmp(in ref TreeNodes other) const { + bool opEqual(const scope ref TreeNodes other) const { return pack == other.pack && configs == other.configs; } + int opCmp(const scope ref TreeNodes other) const { if (pack != other.pack) return pack < other.pack ? -1 : 1; if (configs != other.configs) return configs < other.configs ? -1 : 1; return 0; @@ -66,8 +66,8 @@ ret ^= typeid(CONFIG).getHash(&config); return ret; } - bool opEqual(in ref TreeNode other) const { return pack == other.pack && config == other.config; } - int opCmp(in ref TreeNode other) const { + bool opEqual(const scope ref TreeNode other) const { return pack == other.pack && config == other.config; } + int opCmp(const scope ref TreeNode other) const { if (pack != other.pack) return pack < other.pack ? -1 : 1; if (config != other.config) return config < other.config ? -1 : 1; return 0; @@ -286,7 +286,7 @@ string failedNode; - this(TreeNode parent, TreeNodes dep, in ref ResolveContext context, string file = __FILE__, size_t line = __LINE__) + this(TreeNode parent, TreeNodes dep, const scope ref ResolveContext context, string file = __FILE__, size_t line = __LINE__) { auto m = format("Unresolvable dependencies to package %s:", dep.pack.basePackageName); super(m, file, line); diff --git a/source/dub/dub.d b/source/dub/dub.d index 1fee7b9..521538b 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -481,6 +481,9 @@ if (!path.absolute) path = this.rootPath ~ path; try if (m_packageManager.getOrLoadPackage(path)) continue; catch (Exception e) { logDebug("Failed to load path based selection: %s", e.toString().sanitize); } + } else if (!dep.repository.empty) { + if (m_packageManager.loadSCMPackage(getBasePackageName(p), dep)) + continue; } else { if (m_packageManager.getPackage(p, dep.version_)) continue; foreach (ps; m_packageSuppliers) { @@ -511,7 +514,7 @@ string rootbasename = getBasePackageName(m_project.rootPackage.name); foreach (p, ver; versions) { - if (!ver.path.empty) continue; + if (!ver.path.empty || !ver.repository.empty) continue; auto basename = getBasePackageName(p); if (basename == rootbasename) continue; @@ -523,7 +526,7 @@ continue; } auto sver = m_project.selections.getSelectedVersion(basename); - if (!sver.path.empty) continue; + if (!sver.path.empty || !sver.repository.empty) continue; if (ver.version_ <= sver.version_) continue; logInfo("Package %s would be upgraded from %s to %s.", basename, sver, ver); @@ -543,6 +546,8 @@ logDebug("Failed to load path based selection: %s", e.toString().sanitize); continue; } + } else if (!ver.repository.empty) { + pack = m_packageManager.loadSCMPackage(p, ver); } else { pack = m_packageManager.getBestPackage(p, ver); if (pack && m_packageManager.isManagedPackage(pack) @@ -559,8 +564,11 @@ fetchOpts |= (options & UpgradeOptions.preRelease) != 0 ? FetchOptions.usePrerelease : FetchOptions.none; if (!pack) fetch(p, ver, defaultPlacementLocation, fetchOpts, "getting selected version"); if ((options & UpgradeOptions.select) && p != m_project.rootPackage.name) { - if (ver.path.empty) m_project.selections.selectVersion(p, ver.version_); - else { + if (!ver.repository.empty) { + m_project.selections.selectVersionWithRepository(p, ver.repository, ver.versionSpec); + } else if (ver.path.empty) { + m_project.selections.selectVersion(p, ver.version_); + } else { NativePath relpath = ver.path; if (relpath.absolute) relpath = relpath.relativeTo(m_project.rootPackage.path); m_project.selections.selectVersion(p, relpath); @@ -701,7 +709,6 @@ import core.runtime; import std.exception; Runtime.moduleUnitTester = () => true; - //runUnitTests!app(new JsonTestResultWriter("results.json")); enforce(runUnitTests!allModules(new ConsoleTestResultWriter), "Unit tests failed."); } } @@ -1018,17 +1025,9 @@ void remove(string package_id, string version_, PlacementLocation location) { remove(package_id, location, (in packages) { - if (version_ == RemoveVersionWildcard) + if (version_ == RemoveVersionWildcard || version_.empty) return packages.length; - if (version_.empty && packages.length > 1) { - logError("Cannot remove package '" ~ package_id ~ "', there are multiple possibilities at location\n" - ~ "'" ~ to!string(location) ~ "'."); - logError("Available versions:"); - foreach(pack; packages) - logError(" %s", pack.version_); - throw new Exception("Please specify a individual version using --version=... or use the" - ~ " wildcard --version=" ~ RemoveVersionWildcard ~ " to remove all versions."); - } + foreach (i, p; packages) { if (p.version_ == Version(version_)) return i; @@ -1553,7 +1552,10 @@ protected override Dependency[] getSpecificConfigs(string pack, TreeNodes nodes) { - if (!nodes.configs.path.empty && getPackage(pack, nodes.configs)) return [nodes.configs]; + if (!nodes.configs.path.empty || !nodes.configs.repository.empty) { + if (getPackage(pack, nodes.configs)) return [nodes.configs]; + else return null; + } else return null; } @@ -1588,11 +1590,19 @@ absdeppath.endsWithSlash = true; auto subpack = m_dub.m_packageManager.getSubPackage(basepack, getSubPackageName(d.name), true); if (subpack) { - auto desireddeppath = d.name == dbasename ? basepack.path : subpack.path; + auto desireddeppath = basepack.path; desireddeppath.endsWithSlash = true; - enforce(d.spec.path.empty || absdeppath == desireddeppath, - format("Dependency from %s to root package references wrong path: %s vs. %s", - node.pack, absdeppath.toNativeString(), desireddeppath.toNativeString())); + + auto altdeppath = d.name == dbasename ? basepack.path : subpack.path; + altdeppath.endsWithSlash = true; + + if (absdeppath != desireddeppath) + logWarn("Warning: Sub package %s, referenced by %s %s must be referenced using the path to its base package", + subpack.name, pack.name, pack.version_); + + enforce(d.spec.path.empty || absdeppath == desireddeppath || absdeppath == altdeppath, + format("Dependency from %s to %s uses wrong path: %s vs. %s", + node.pack, subpack.name, absdeppath.toNativeString(), desireddeppath.toNativeString())); } ret ~= TreeNodes(d.name, node.config); continue; @@ -1673,7 +1683,10 @@ if (basename == m_rootPackage.basePackage.name) return m_rootPackage.basePackage; - if (!dep.path.empty) { + if (!dep.repository.empty) { + auto ret = m_dub.packageManager.loadSCMPackage(name, dep); + return ret !is null && dep.matches(ret.version_) ? ret : null; + } else if (!dep.path.empty) { try { auto ret = m_dub.packageManager.getOrLoadPackage(dep.path); if (dep.matches(ret.version_)) return ret; diff --git a/source/dub/generators/build.d b/source/dub/generators/build.d index 5f54d4a..75250f4 100644 --- a/source/dub/generators/build.d +++ b/source/dub/generators/build.d @@ -27,7 +27,7 @@ import std.string; import std.encoding : sanitize; -string getObjSuffix(in ref BuildPlatform platform) +string getObjSuffix(const scope ref BuildPlatform platform) { return platform.platform.canFind("windows") ? ".obj" : ".o"; } @@ -412,7 +412,7 @@ /// Calls with path that resolve to the same file on the filesystem will return the same, /// unless they include different symbolic links (which are not resolved). - static string pathToObjName(in ref BuildPlatform platform, string path) + static string pathToObjName(const scope ref BuildPlatform platform, string path) { import std.digest.crc : crc32Of; import std.path : buildNormalizedPath, dirSeparator, relativePath, stripDrive; @@ -593,7 +593,7 @@ return prj.path ~ "source/app.d"; } -private NativePath getTargetPath(in ref BuildSettings bs, in ref GeneratorSettings settings) +private NativePath getTargetPath(const scope ref BuildSettings bs, const scope ref GeneratorSettings settings) { return NativePath(bs.targetPath) ~ settings.compiler.getTargetFileName(bs, settings.platform); } diff --git a/source/dub/generators/generator.d b/source/dub/generators/generator.d index 97d2985..3c5d6d7 100644 --- a/source/dub/generators/generator.d +++ b/source/dub/generators/generator.d @@ -308,7 +308,7 @@ visited.clear(); // 1. downwards inherits versions, debugVersions, and inheritable build settings - static void configureDependencies(in ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0) + static void configureDependencies(const scope ref TargetInfo ti, TargetInfo[string] targets, size_t level = 0) { // do not use `visited` here as dependencies must inherit // configurations from *all* of their parents @@ -527,14 +527,14 @@ ti.pack.metadataCache = cache; } - private static void mergeFromDependent(in ref BuildSettings parent, ref BuildSettings child) + private static void mergeFromDependent(const scope ref BuildSettings parent, ref BuildSettings child) { child.addVersions(parent.versions); child.addDebugVersions(parent.debugVersions); child.addOptions(BuildOptions(parent.options & inheritedBuildOptions)); } - private static void mergeFromDependency(in ref BuildSettings child, ref BuildSettings parent, in ref BuildPlatform platform) + private static void mergeFromDependency(const scope ref BuildSettings child, ref BuildSettings parent, const scope ref BuildPlatform platform) { import dub.compilers.utils : isLinkerFile; diff --git a/source/dub/init.d b/source/dub/init.d index d29b679..a1fb3d9 100644 --- a/source/dub/init.d +++ b/source/dub/init.d @@ -113,7 +113,7 @@ private void initVibeDPackage(NativePath root_path, ref PackageRecipe p, scope void delegate() pre_write_callback) { if ("vibe-d" !in p.buildSettings.dependencies) - p.buildSettings.dependencies["vibe-d"] = Dependency("~>0.8.2"); + p.buildSettings.dependencies["vibe-d"] = Dependency("~>0.9"); p.description = "A simple vibe.d server application."; pre_write_callback(); diff --git a/source/dub/internal/git.d b/source/dub/internal/git.d index 50be963..d1e52d6 100644 --- a/source/dub/internal/git.d +++ b/source/dub/internal/git.d @@ -101,3 +101,41 @@ return null; } + +/** Clones a repository into a new directory. + + Params: + remote = The (possibly remote) repository to clone from + reference = The branch to check out after cloning + destination = Repository destination directory + + Returns: + Whether the cloning succeeded. +*/ +bool cloneRepository(string remote, string reference, string destination) +{ + import std.process : Pid, spawnProcess, wait; + + Pid command; + + if (!exists(destination)) { + string[] args = ["git", "clone", "--no-checkout"]; + if (getLogLevel > LogLevel.diagnostic) args ~= "-q"; + + command = spawnProcess(args~[remote, destination]); + if (wait(command) != 0) { + return false; + } + } + + string[] args = ["git", "-C", destination, "checkout", "--detach"]; + if (getLogLevel > LogLevel.diagnostic) args ~= "-q"; + command = spawnProcess(args~[reference]); + + if (wait(command) != 0) { + rmdirRecurse(destination); + return false; + } + + return true; +} diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index a4a23f2..be15f15 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -254,6 +254,62 @@ return pack; } + /** For a given SCM repository, returns the corresponding package. + + An SCM repository is provided as its remote URL, the repository is cloned + and in the dependency speicfied commit is checked out. + + If the target directory already exists, just returns the package + without cloning. + + Params: + name = Package name + dependency = Dependency that contains the repository URL and a specific commit + + Returns: + The package loaded from the given SCM repository or null if the + package couldn't be loaded. + */ + Package loadSCMPackage(string name, Dependency dependency) + in { assert(!dependency.repository.empty); } + body { + Package pack; + + with (dependency.repository) final switch (kind) + { + case Kind.git: + pack = loadGitPackage(name, dependency.versionSpec, dependency.repository.remote); + } + if (pack !is null) { + addPackages(m_temporaryPackages, pack); + } + return pack; + } + + private Package loadGitPackage(string name, string versionSpec, string remote) + { + import dub.internal.git : cloneRepository; + + if (!versionSpec.startsWith("~") && !versionSpec.isGitHash) { + return null; + } + + string gitReference = versionSpec.chompPrefix("~"); + const destination = m_repositories[LocalPackageType.user].packagePath ~ + NativePath(name ~ "-" ~ gitReference) ~ (name~"/"); + + foreach (p; getPackageIterator(name)) { + if (p.path == destination) { + return p; + } + } + + if (!cloneRepository(remote, gitReference, destination.toNativeString())) { + return null; + } + + return Package.load(destination); + } /** Searches for the latest version of a package matching the given dependency. */ diff --git a/source/dub/platform.d b/source/dub/platform.d index d908438..39e5557 100644 --- a/source/dub/platform.d +++ b/source/dub/platform.d @@ -54,6 +54,14 @@ enum string archCheck = q{ string[] ret; version(X86) ret ~= "x86"; + // Hack: see #1535 + // Makes "x86_omf" available as a platform specifier in the package recipe + version(X86) version(CRuntime_DigitalMars) ret ~= "x86_omf"; + // Hack: see #1059 + // When compiling with --arch=x86_mscoff build_platform.architecture is equal to ["x86"] and canFind below is false. + // This hack prevents unnesessary warning 'Failed to apply the selected architecture x86_mscoff. Got ["x86"]'. + // And also makes "x86_mscoff" available as a platform specifier in the package recipe + version(X86) version(CRuntime_Microsoft) ret ~= "x86_mscoff"; version(X86_64) ret ~= "x86_64"; version(ARM) ret ~= "arm"; version(AArch64) ret ~= "aarch64"; diff --git a/source/dub/project.d b/source/dub/project.d index f02f47e..edfd20b 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -256,7 +256,7 @@ enforce(!m_rootPackage.name.canFind(' '), "Aborting due to the package name containing spaces."); foreach (d; m_rootPackage.getAllDependencies()) - if (d.spec.isExactVersion && d.spec.version_.isBranch) { + if (d.spec.isExactVersion && d.spec.version_.isBranch && d.spec.repository.empty) { logWarn("WARNING: A deprecated branch based version specification is used " ~ "for the dependency %s. Please use numbered versions instead. Also " ~ "note that you can still use the %s file to override a certain " @@ -341,6 +341,10 @@ // need to be satisfied bool is_desired = !vspec.optional || m_selections.hasSelectedVersion(basename) || (vspec.default_ && m_selections.bare); + Package resolveSubPackage(Package p, in bool silentFail) { + return subname.length ? m_packageManager.getSubPackage(p, subname, silentFail) : p; + } + if (dep.name == m_rootPackage.basePackage.name) { vspec = Dependency(m_rootPackage.version_); p = m_rootPackage.basePackage; @@ -354,24 +358,32 @@ } } else if (m_selections.hasSelectedVersion(basename)) { vspec = m_selections.getSelectedVersion(basename); - if (vspec.path.empty) p = m_packageManager.getBestPackage(dep.name, vspec); - else { + if (!vspec.path.empty) { auto path = vspec.path; if (!path.absolute) path = m_rootPackage.path ~ path; p = m_packageManager.getOrLoadPackage(path, NativePath.init, true); - if (subname.length) p = m_packageManager.getSubPackage(p, subname, true); + p = resolveSubPackage(p, true); + } else if (!vspec.repository.empty) { + p = m_packageManager.loadSCMPackage(basename, vspec); + p = resolveSubPackage(p, true); + } else { + p = m_packageManager.getBestPackage(dep.name, vspec); } } else if (m_dependencies.canFind!(d => getBasePackageName(d.name) == basename)) { auto idx = m_dependencies.countUntil!(d => getBasePackageName(d.name) == basename); auto bp = m_dependencies[idx].basePackage; vspec = Dependency(bp.path); - if (subname.length) p = m_packageManager.getSubPackage(bp, subname, false); - else p = bp; + p = resolveSubPackage(bp, false); } else { logDiagnostic("%sVersion selection for dependency %s (%s) of %s is missing.", indent, basename, dep.name, pack.name); } + if (!p && !vspec.repository.empty) { + p = m_packageManager.loadSCMPackage(basename, vspec); + resolveSubPackage(p, false); + } + if (!p && !vspec.path.empty) { NativePath path = vspec.path; if (!path.absolute) path = pack.path ~ path; @@ -381,7 +393,7 @@ logWarn("%sSub package %s must be referenced using the path to it's parent package.", indent, dep.name); p = p.parentPackage; } - if (subname.length) p = m_packageManager.getSubPackage(p, subname, false); + p = resolveSubPackage(p, false); enforce(p.name == dep.name, format("Path based dependency %s is referenced with a wrong name: %s vs. %s", path.toNativeString(), dep.name, p.name)); @@ -1542,6 +1554,18 @@ m_dirty = true; } + /// Selects a certain Git reference for a specific package. + void selectVersionWithRepository(string package_id, Repository repository, string spec) + { + const dependency = Dependency(repository, spec); + if (auto ps = package_id in m_selections) { + if (ps.dep == dependency) + return; + } + m_selections[package_id] = Selected(dependency); + m_dirty = true; + } + /// Removes the selection for a particular package. void deselectVersion(string package_id) { @@ -1604,7 +1628,12 @@ static Json dependencyToJson(Dependency d) { - if (d.path.empty) return Json(d.version_.toString()); + if (!d.repository.empty) { + return serializeToJson([ + "version": d.version_.toString(), + "repository": d.repository.toString, + ]); + } else if (d.path.empty) return Json(d.version_.toString()); else return serializeToJson(["path": d.path.toString()]); } @@ -1612,9 +1641,12 @@ { if (j.type == Json.Type.string) return Dependency(Version(j.get!string)); - else if (j.type == Json.Type.object) + else if (j.type == Json.Type.object && "path" in j) return Dependency(NativePath(j["path"].get!string)); - else throw new Exception(format("Unexpected type for dependency: %s", j.type)); + else if (j.type == Json.Type.object && "repository" in j) + return Dependency(Repository(j["repository"].get!string), + enforce("version" in j, "Expected \"version\" field in repository version object").get!string); + else throw new Exception(format("Unexpected type for dependency: %s", j)); } Json serialize() diff --git a/source/dub/recipe/io.d b/source/dub/recipe/io.d index c66072e..994b3da 100644 --- a/source/dub/recipe/io.d +++ b/source/dub/recipe/io.d @@ -128,7 +128,7 @@ Note that the file extension must be either "json" or "sdl". */ -void writePackageRecipe(string filename, in ref PackageRecipe recipe) +void writePackageRecipe(string filename, const scope ref PackageRecipe recipe) { import dub.internal.vibecompat.core.file : openFile, FileMode; auto f = openFile(filename, FileMode.createTrunc); @@ -137,7 +137,7 @@ } /// ditto -void writePackageRecipe(NativePath filename, in ref PackageRecipe recipe) +void writePackageRecipe(NativePath filename, const scope ref PackageRecipe recipe) { writePackageRecipe(filename.toNativeString, recipe); } @@ -147,7 +147,7 @@ The extension of the supplied `filename` must be either "json" or "sdl". The output format is chosen accordingly. */ -void serializePackageRecipe(R)(ref R dst, in ref PackageRecipe recipe, string filename) +void serializePackageRecipe(R)(ref R dst, const scope ref PackageRecipe recipe, string filename) { import std.algorithm : endsWith; import dub.internal.vibecompat.data.json : writeJsonString; @@ -160,4 +160,3 @@ toSDL(recipe).toSDLDocument(dst); else assert(false, "writePackageRecipe called with filename with unknown extension: "~filename); } - diff --git a/source/dub/recipe/json.d b/source/dub/recipe/json.d index 791d485..54486c7 100644 --- a/source/dub/recipe/json.d +++ b/source/dub/recipe/json.d @@ -73,7 +73,7 @@ recipe.parseSubPackages(fullname, ps.opt!(Json[])); } -Json toJson(in ref PackageRecipe recipe) +Json toJson(const scope ref PackageRecipe recipe) { auto ret = recipe.buildSettings.toJson(); ret["name"] = recipe.name; @@ -152,7 +152,7 @@ config.buildSettings.parseJson(json, package_name); } -private Json toJson(in ref ConfigurationInfo config) +private Json toJson(const scope ref ConfigurationInfo config) { auto ret = config.buildSettings.toJson(); ret["name"] = config.name; @@ -245,7 +245,7 @@ } } -private Json toJson(in ref BuildSettingsTemplate bs) +private Json toJson(const scope ref BuildSettingsTemplate bs) { auto ret = Json.emptyObject; if( bs.dependencies !is null ){ @@ -302,7 +302,7 @@ tr.addRequirement(name, value.get!string); } -private Json toJson(in ref ToolchainRequirements tr) +private Json toJson(const scope ref ToolchainRequirements tr) { auto ret = Json.emptyObject; if (tr.dub != Dependency.any) ret["dub"] = serializeToJson(tr.dub); diff --git a/source/dub/recipe/packagerecipe.d b/source/dub/recipe/packagerecipe.d index a879991..e03fa92 100644 --- a/source/dub/recipe/packagerecipe.d +++ b/source/dub/recipe/packagerecipe.d @@ -341,7 +341,7 @@ } } -package(dub) void checkPlatform(in ref ToolchainRequirements tr, BuildPlatform platform, string package_name) +package(dub) void checkPlatform(const scope ref ToolchainRequirements tr, BuildPlatform platform, string package_name) { import dub.compilers.utils : dmdLikeVersionToSemverLike; import std.algorithm.iteration : map; diff --git a/source/dub/recipe/sdl.d b/source/dub/recipe/sdl.d index 7f3ad45..cc6ab55 100644 --- a/source/dub/recipe/sdl.d +++ b/source/dub/recipe/sdl.d @@ -88,7 +88,7 @@ } } -Tag toSDL(in ref PackageRecipe recipe) +Tag toSDL(const scope ref PackageRecipe recipe) { Tag ret = new Tag; void add(T)(string field, T value) { ret.add(new Tag(null, field, [Value(value)])); } @@ -187,6 +187,11 @@ logDiagnostic("Ignoring version specification (%s) for path based dependency %s", attrs["version"][0].value.get!string, attrs["path"][0].value.get!string); dep.versionSpec = "*"; dep.path = NativePath(attrs["path"][0].value.get!string); + } else if ("repository" in attrs) { + enforceSDL("version" in attrs, "Missing version specification.", t); + + dep.repository = Repository(attrs["repository"][0].value.get!string); + dep.versionSpec = attrs["version"][0].value.get!string; } else { enforceSDL("version" in attrs, "Missing version specification.", t); dep.versionSpec = attrs["version"][0].value.get!string; @@ -212,7 +217,7 @@ } } -private Tag toSDL(in ref ConfigurationInfo config) +private Tag toSDL(const scope ref ConfigurationInfo config) { auto ret = new Tag(null, "configuration", [Value(config.name)]); if (config.platforms.length) ret.add(new Tag(null, "platforms", config.platforms[].map!(p => Value(p)).array)); @@ -220,7 +225,7 @@ return ret; } -private Tag[] toSDL(in ref BuildSettingsTemplate bs) +private Tag[] toSDL(const scope ref BuildSettingsTemplate bs) { Tag[] ret; void add(string name, string value, string namespace = null) { ret ~= new Tag(namespace, name, [Value(value)]); } @@ -239,6 +244,7 @@ foreach (pack, d; bs.dependencies) { Attribute[] attribs; + if (!d.repository.empty) attribs ~= new Attribute(null, "repository", Value(d.repository.toString())); if (!d.path.empty) attribs ~= new Attribute(null, "path", Value(d.path.toString())); else attribs ~= new Attribute(null, "version", Value(d.versionSpec)); if (d.optional) attribs ~= new Attribute(null, "optional", Value(true)); @@ -586,3 +592,28 @@ parseSDL(rec, sdl, null, "testfile"); assert("" in rec.buildSettings.sourcePaths); } + +unittest { + auto sdl = +`name "test" +dependency "package" repository="git+https://some.url" version="12345678" +`; + PackageRecipe rec; + parseSDL(rec, sdl, null, "testfile"); + auto dependency = rec.buildSettings.dependencies["package"]; + assert(!dependency.repository.empty); + assert(dependency.versionSpec == "12345678"); +} + +unittest { + PackageRecipe p; + p.name = "test"; + + auto repository = Repository("git+https://some.url"); + p.buildSettings.dependencies["package"] = Dependency(repository, "12345678"); + auto sdl = toSDL(p).toSDLDocument(); + assert(sdl == +`name "test" +dependency "package" repository="git+https://some.url" version="12345678" +`); +} diff --git a/test/.gitignore b/test/.gitignore index ff95cca..e8ce8bd 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -12,5 +12,8 @@ path-subpackage-ref/test subpackage-ref/test subpackage-common-with-sourcefile-globbing/mypackage* +version-spec/**/CMakeLists.txt +version-spec/**/foo.cmake +version-spec/**/foo /test_registry diff --git a/test/4-describe-data-2-dmd.sh b/test/4-describe-data-2-dmd.sh index 8d7d0ae..bf3c1da 100755 --- a/test/4-describe-data-2-dmd.sh +++ b/test/4-describe-data-2-dmd.sh @@ -29,7 +29,7 @@ --data=import-files \ --data=options \ > "$temp_file"; then - die 'Printing project data failed!' + die $LINENO 'Printing project data failed!' fi # Create the expected output path file to compare against. @@ -79,6 +79,6 @@ echo "" >> "$expected_file" if ! diff "$expected_file" "$temp_file"; then - die 'The project data did not match the expected output!' + die $LINENO 'The project data did not match the expected output!' fi diff --git a/test/4-describe-data-3-zero-delim.sh b/test/4-describe-data-3-zero-delim.sh index a6924ca..0a628bd 100755 --- a/test/4-describe-data-3-zero-delim.sh +++ b/test/4-describe-data-3-zero-delim.sh @@ -40,7 +40,7 @@ --data=requirements \ --data=options \ > "$temp_file_normal"; then - die 'Printing list-style project data failed!' + die $LINENO 'Printing list-style project data failed!' fi if ! $DUB describe --compiler=$DC --data-0 --data-list \ @@ -68,26 +68,26 @@ --data=requirements \ --data=options \ | xargs -0 printf "%s\n" > "$temp_file_zero_delim"; then - die 'Printing null-delimited list-style project data failed!' + die $LINENO 'Printing null-delimited list-style project data failed!' fi if ! diff -b -B "$temp_file_normal" "$temp_file_zero_delim"; then - die 'The null-delimited list-style project data did not match the expected output!' + die $LINENO 'The null-delimited list-style project data did not match the expected output!' fi # Test --import-paths if ! $DUB describe --compiler=$DC --import-paths \ > "$temp_file_normal"; then - die 'Printing --import-paths failed!' + die $LINENO 'Printing --import-paths failed!' fi if ! $DUB describe --compiler=$DC --data-0 --import-paths \ | xargs -0 printf "%s\n" > "$temp_file_zero_delim"; then - die 'Printing null-delimited --import-paths failed!' + die $LINENO 'Printing null-delimited --import-paths failed!' fi if ! diff -b -B "$temp_file_normal" "$temp_file_zero_delim"; then - die 'The null-delimited --import-paths data did not match the expected output!' + die $LINENO 'The null-delimited --import-paths data did not match the expected output!' fi # DMD-only beyond this point @@ -99,29 +99,29 @@ # Test dmd-style --data=versions if ! $DUB describe --compiler=$DC --data=versions \ > "$temp_file_normal"; then - die 'Printing dmd-style --data=versions failed!' + die $LINENO 'Printing dmd-style --data=versions failed!' fi if ! $DUB describe --compiler=$DC --data-0 --data=versions \ | xargs -0 printf "%s " > "$temp_file_zero_delim"; then - die 'Printing null-delimited dmd-style --data=versions failed!' + die $LINENO 'Printing null-delimited dmd-style --data=versions failed!' fi if ! diff -b -B "$temp_file_normal" "$temp_file_zero_delim"; then - die 'The null-delimited dmd-style --data=versions did not match the expected output!' + die $LINENO 'The null-delimited dmd-style --data=versions did not match the expected output!' fi # Test dmd-style --data=source-files if ! $DUB describe --compiler=$DC --data=source-files \ > "$temp_file_normal"; then - die 'Printing dmd-style --data=source-files failed!' + die $LINENO 'Printing dmd-style --data=source-files failed!' fi if ! $DUB describe --compiler=$DC --data-0 --data=source-files \ | xargs -0 printf "'%s' " > "$temp_file_zero_delim"; then - die 'Printing null-delimited dmd-style --data=source-files failed!' + die $LINENO 'Printing null-delimited dmd-style --data=source-files failed!' fi if ! diff -b -B "$temp_file_normal" "$temp_file_zero_delim"; then - die 'The null-delimited dmd-style --data=source-files did not match the expected output!' + die $LINENO 'The null-delimited dmd-style --data=source-files did not match the expected output!' fi diff --git a/test/4-describe-import-paths.sh b/test/4-describe-import-paths.sh index 375bc40..201a633 100755 --- a/test/4-describe-import-paths.sh +++ b/test/4-describe-import-paths.sh @@ -13,7 +13,7 @@ trap cleanup EXIT if ! $DUB describe --compiler=$DC --import-paths > "$temp_file"; then - die 'Printing import paths failed!' + die $LINENO 'Printing import paths failed!' fi # Create the expected output path file to compare against. @@ -23,6 +23,6 @@ echo "$CURR_DIR/describe-dependency-3/dep3-source/" >> "$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!' + die $LINENO 'The import paths did not match the expected output!' fi diff --git a/test/4-describe-json.sh b/test/4-describe-json.sh index 21f5105..e22bb71 100755 --- a/test/4-describe-json.sh +++ b/test/4-describe-json.sh @@ -13,6 +13,6 @@ trap cleanup EXIT if ! $DUB describe --compiler=$DC > "$temp_file"; then - die 'Printing describe JSON failed!' + die $LINENO 'Printing describe JSON failed!' fi diff --git a/test/4-describe-string-import-paths.sh b/test/4-describe-string-import-paths.sh index c1106a6..89545d5 100755 --- a/test/4-describe-string-import-paths.sh +++ b/test/4-describe-string-import-paths.sh @@ -13,7 +13,7 @@ trap cleanup EXIT if ! $DUB describe --compiler=$DC --string-import-paths > "$temp_file"; then - die 'Printing string import paths failed!' + die $LINENO 'Printing string import paths failed!' fi # Create the expected output path file to compare against. @@ -22,6 +22,6 @@ echo "$CURR_DIR/describe-dependency-3/dep3-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!' + die $LINENO 'The string import paths did not match the expected output!' fi diff --git a/test/dustmite-no-redirect-test/.no_build b/test/dustmite-no-redirect-test/.no_build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/dustmite-no-redirect-test/.no_build diff --git a/test/dustmite-no-redirect-test/project/dub.json b/test/dustmite-no-redirect-test/project/dub.json new file mode 100644 index 0000000..32fa835 --- /dev/null +++ b/test/dustmite-no-redirect-test/project/dub.json @@ -0,0 +1,3 @@ +{ + "name": "dustmite-no-redirect-test" +} diff --git a/test/dustmite-no-redirect-test/project/source/app.d b/test/dustmite-no-redirect-test/project/source/app.d new file mode 100644 index 0000000..3ba959a --- /dev/null +++ b/test/dustmite-no-redirect-test/project/source/app.d @@ -0,0 +1,6 @@ +extern(C) int printf(const scope char*, ...); + +void main() +{ + printf("This text should be shown!\n"); +} diff --git a/test/dustmite-no-redirect.sh b/test/dustmite-no-redirect.sh new file mode 100755 index 0000000..30c6b9c --- /dev/null +++ b/test/dustmite-no-redirect.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if ! command -v dustmite &> /dev/null +then + echo "Skipping test because dustmite is not installed!" + exit 0 +fi + +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +DM_TEST="$CURR_DIR/dustmite-no-redirect-test/project" +DM_TMP="$DM_TEST-dusting" +EXPECTED="This text should be shown!" +LOG="$DM_TEST.log" + +rm -rf $DM_TMP $DM_TMP.* + +$DUB --root=$DM_TEST dustmite --no-redirect --program-status=1 $DM_TMP &> $LOG || true + +if ! grep -q "$EXPECTED" "$LOG" +then + cat $LOG + die $LINENO "Diff between expected and actual output" +fi + +rm -rf $DM_TMP $DM_TMP.* $LOG diff --git a/test/fetchzip.sh b/test/fetchzip.sh index 15b906e..d5917d4 100755 --- a/test/fetchzip.sh +++ b/test/fetchzip.sh @@ -5,55 +5,55 @@ PORT=$(getRandomPort) -dub remove gitcompatibledubpackage --non-interactive --version=* 2>/dev/null || true +${DUB} remove gitcompatibledubpackage --non-interactive 2>/dev/null || true -"$DUB" build --single "$DIR"/test_registry.d +${DUB} build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1336-registry" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download gitcompatibledubpackage (1.0.4)" -timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.4 --skip-registry=all --registry=http://localhost:$PORT +timeout 1s ${DUB} fetch gitcompatibledubpackage@1.0.4 --skip-registry=all --registry=http://localhost:$PORT if [ $? -eq 124 ]; then - die 'Fetching from responsive registry should not time-out.' + die $LINENO 'Fetching from responsive registry should not time-out.' fi -dub remove gitcompatibledubpackage --non-interactive --version=1.0.4 +${DUB} remove gitcompatibledubpackage@1.0.4 echo "Downloads should be retried when the zip is corrupted - gitcompatibledubpackage (1.0.3)" -zipOut=$(! timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.3 --skip-registry=all --registry=http://localhost:$PORT 2>&1) +zipOut=$(! timeout 1s ${DUB} fetch gitcompatibledubpackage@1.0.3 --skip-registry=all --registry=http://localhost:$PORT 2>&1) rc=$? if ! zipCount=$(grep -Fc 'Failed to extract zip archive' <<<"$zipOut") || [ "$zipCount" -lt 3 ] ; then echo '========== +Output was ==========' >&2 echo "$zipOut" >&2 echo '========== -Output was ==========' >&2 - die 'DUB should have tried to download the zip archive multiple times.' + die $LINENO 'DUB should have tried to download the zip archive multiple times.' elif [ $rc -eq 124 ]; then - die 'DUB timed out unexpectedly.' + die $LINENO 'DUB timed out unexpectedly.' fi -if dub remove gitcompatibledubpackage --non-interactive --version=* 2>/dev/null; then - die 'DUB should not have installed a broken package.' +if ${DUB} remove gitcompatibledubpackage --non-interactive 2>/dev/null; then + die $LINENO 'DUB should not have installed a broken package.' fi echo "HTTP status errors on downloads should be retried - gitcompatibledubpackage (1.0.2)" -retryOut=$(! timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.2 --skip-registry=all --registry=http://localhost:$PORT --vverbose 2>&1) +retryOut=$(! timeout 1s ${DUB} fetch gitcompatibledubpackage@1.0.2 --skip-registry=all --registry=http://localhost:$PORT --vverbose 2>&1) rc=$? if ! retryCount=$(echo "$retryOut" | grep -Fc 'Bad Gateway') || [ "$retryCount" -lt 3 ] ; then echo '========== +Output was ==========' >&2 echo "$retryOut" >&2 echo '========== -Output was ==========' >&2 - die "DUB should have retried download on server error multiple times, but only tried $retryCount times." + die $LINENO "DUB should have retried download on server error multiple times, but only tried $retryCount times." elif [ $rc -eq 124 ]; then - die 'DUB timed out unexpectedly.' + die $LINENO 'DUB timed out unexpectedly.' fi -if dub remove gitcompatibledubpackage --non-interactive --version=* 2>/dev/null; then - die 'DUB should not have installed a package.' +if ${DUB} remove gitcompatibledubpackage --non-interactive 2>/dev/null; then + die $LINENO 'DUB should not have installed a package.' fi echo "HTTP status errors on downloads should retry with fallback mirror - gitcompatibledubpackage (1.0.2)" -timeout 1s "$DUB" fetch gitcompatibledubpackage --version=1.0.2 --skip-registry=all --registry="http://localhost:$PORT http://localhost:$PORT/fallback" +timeout 1s "$DUB" fetch gitcompatibledubpackage@1.0.2 --skip-registry=all --registry="http://localhost:$PORT http://localhost:$PORT/fallback" if [ $? -eq 124 ]; then - die 'Fetching from responsive registry should not time-out.' + die $LINENO 'Fetching from responsive registry should not time-out.' fi -dub remove gitcompatibledubpackage --non-interactive --version=1.0.2 +${DUB} remove gitcompatibledubpackage@1.0.2 diff --git a/test/git-dependency/dub.json b/test/git-dependency/dub.json new file mode 100644 index 0000000..ace7c64 --- /dev/null +++ b/test/git-dependency/dub.json @@ -0,0 +1,9 @@ +{ + "name": "git-dependency", + "dependencies": { + "gitcompatibledubpackage": { + "repository": "git+https://github.com/dlang-community/gitcompatibledubpackage.git", + "version": "ccb31bf6a655437176ec02e04c2305a8c7c90d67" + } + } +} diff --git a/test/git-dependency/src/app.d b/test/git-dependency/src/app.d new file mode 100644 index 0000000..29751b2 --- /dev/null +++ b/test/git-dependency/src/app.d @@ -0,0 +1,6 @@ +import gitcompatibledubpackage.subdir.file; + +void main() +{ + assert(!hasTheWorldExploded()); +} diff --git a/test/help.sh b/test/help.sh index 89cd08c..8d56f79 100755 --- a/test/help.sh +++ b/test/help.sh @@ -2,26 +2,24 @@ . $(dirname "${BASH_SOURCE[0]}")/common.sh -DUB=dub - ### It shows the general help message if ! { ${DUB} help | grep "Manages the DUB project in the current directory."; } then - die 'DUB did not print the default help message, with the `help` command.' + die $LINENO 'DUB did not print the default help message, with the `help` command.' fi if ! { ${DUB} -h | grep "Manages the DUB project in the current directory."; } then - die 'DUB did not print the default help message, with the `-h` argument.' + die $LINENO 'DUB did not print the default help message, with the `-h` argument.' fi if ! { ${DUB} --help | grep "Manages the DUB project in the current directory."; } then - die 'DUB did not print the default help message, with the `--help` argument.' + die $LINENO 'DUB did not print the default help message, with the `--help` argument.' fi ### It shows the build command help if ! { ${DUB} build -h | grep "Builds a package"; } then - die 'DUB did not print the build help message, with the `-h` argument.' + die $LINENO 'DUB did not print the build help message, with the `-h` argument.' fi if ! { ${DUB} build --help | grep "Builds a package"; } then - die 'DUB did not print the build help message, with the `--help` argument.' + die $LINENO 'DUB did not print the build help message, with the `--help` argument.' fi diff --git a/test/interactive-remove.sh b/test/interactive-remove.sh index 387323d..fd65ab8 100755 --- a/test/interactive-remove.sh +++ b/test/interactive-remove.sh @@ -7,32 +7,34 @@ # Ideally, we should not have this run by default / run it in a container. # In the meantime, in order to make it pass on developer's machines, # we need to nuke every `dub` version in the user cache... -$DUB remove dub -n --version=* || true +$DUB remove dub -n || true -$DUB fetch dub --version=1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] -$DUB fetch dub --version=1.10.0 && [ -d $HOME/.dub/packages/dub-1.10.0/dub ] -if $DUB remove dub --non-interactive 2>/dev/null; then - die $LINENO 'Non-interactive remove should fail' -fi +$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 ] + echo 1 | $DUB remove dub | tr -d '\n' | grep --ignore-case 'select.*1\.9\.0.*1\.10\.0.*' if [ -d $HOME/.dub/packages/dub-1.9.0/dub ]; then die $LINENO 'Failed to remove dub-1.9.0' fi -$DUB fetch dub --version=1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] + +$DUB fetch dub@1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] # EOF aborts remove echo -xn '' | $DUB remove dub if [ ! -d $HOME/.dub/packages/dub-1.9.0/dub ] || [ ! -d $HOME/.dub/packages/dub-1.10.0/dub ]; then die $LINENO 'Aborted dub still removed a package' fi + # validates input echo -e 'abc\n4\n-1\n3' | $DUB remove dub 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 all version of dub' fi -$DUB fetch dub --version=1.9.0 && [ -d $HOME/.dub/packages/dub-1.9.0/dub ] + +$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 ] -# is non-interactive with --version= -$DUB remove dub --version=\* +# is non-interactive with `--version=` +$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 non-interactively remove specified versions' fi diff --git a/test/issue1037-better-dependency-messages.sh b/test/issue1037-better-dependency-messages.sh index 4c5c87a..8847382 100755 --- a/test/issue1037-better-dependency-messages.sh +++ b/test/issue1037-better-dependency-messages.sh @@ -19,7 +19,7 @@ $DUB upgrade 2>$temp_file && exit 1 # dub upgrade should fail if ! diff "$temp_file2" "$temp_file"; then - die 'output not containing conflict information' + die $LINENO 'output not containing conflict information' fi exit 0 diff --git a/test/issue1180-local-cache-broken.sh b/test/issue1180-local-cache-broken.sh index 0a83177..41a8588 100755 --- a/test/issue1180-local-cache-broken.sh +++ b/test/issue1180-local-cache-broken.sh @@ -5,7 +5,7 @@ PORT=$(getRandomPort) -"$DUB" remove maven-dubpackage --root="$DIR/issue1180-local-cache-broken" --non-interactive --version=* 2>/dev/null || true +"$DUB" remove maven-dubpackage --root="$DIR/issue1180-local-cache-broken" --non-interactive 2>/dev/null || true "$DUB" build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1416-maven-repo-pkg-supplier" --port=$PORT & @@ -16,6 +16,6 @@ echo "Trying to download maven-dubpackage (1.0.5)" "$DUB" upgrade --root="$DIR/issue1180-local-cache-broken" --cache=local --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages -if ! "$DUB" remove maven-dubpackage --root="$DIR/issue1180-local-cache-broken" --non-interactive --version=1.0.5 2>/dev/null; then - die 'DUB did not install package from maven registry.' +if ! "$DUB" remove maven-dubpackage@1.0.5 --root="$DIR/issue1180-local-cache-broken" --non-interactive 2>/dev/null; then + die $LINENO 'DUB did not install package from maven registry.' fi diff --git a/test/issue1372-ignore-files-in-hidden-dirs.sh b/test/issue1372-ignore-files-in-hidden-dirs.sh index 1ecede2..f4560e9 100755 --- a/test/issue1372-ignore-files-in-hidden-dirs.sh +++ b/test/issue1372-ignore-files-in-hidden-dirs.sh @@ -12,7 +12,7 @@ echo "Compile and ignore hidden directories" ${DUB} build --root ${BASEDIR} --config=normal --force OUTPUT=`${BASEDIR}/issue1372` -if [[ "$OUTPUT" != "no hidden file compiled" ]]; then die "Normal compilation failed"; fi +if [[ "$OUTPUT" != "no hidden file compiled" ]]; then die $LINENO "Normal compilation failed"; fi rm -rf ${BASEDIR}/.dub rm -rf ${BASEDIR}/issue1372 @@ -22,7 +22,7 @@ ${DUB} build --root ${BASEDIR} --config=hiddenfile --force OUTPUT=`${BASEDIR}/issue1372` -if [[ "$OUTPUT" != "hidden file compiled" ]]; then die "Hidden file compilation failed"; fi +if [[ "$OUTPUT" != "hidden file compiled" ]]; then die $LINENO "Hidden file compilation failed"; fi rm -rf ${BASEDIR}/.dub rm -rf ${BASEDIR}/issue1372 @@ -31,7 +31,7 @@ ${DUB} build --root ${BASEDIR} --config=hiddendir --force OUTPUT=`${BASEDIR}/issue1372` -if [[ "$OUTPUT" != "hidden dir compiled" ]]; then die "Hidden directory compilation failed"; fi +if [[ "$OUTPUT" != "hidden dir compiled" ]]; then die $LINENO "Hidden directory compilation failed"; fi rm -rf ${BASEDIR}/.dub rm -rf ${BASEDIR}/issue1372 diff --git a/test/issue1401-filesystem-supplier.sh b/test/issue1401-filesystem-supplier.sh index 1367fc6..18d1fcd 100755 --- a/test/issue1401-filesystem-supplier.sh +++ b/test/issue1401-filesystem-supplier.sh @@ -3,26 +3,26 @@ . "$DIR"/common.sh -dub remove fs-json-dubpackage --non-interactive --version=* 2>/dev/null || true -dub remove fs-sdl-dubpackage --non-interactive --version=* 2>/dev/null || true +${DUB} remove fs-json-dubpackage --non-interactive 2>/dev/null || true +${DUB} remove fs-sdl-dubpackage --non-interactive 2>/dev/null || true echo "Trying to get fs-sdl-dubpackage (1.0.5)" -"$DUB" fetch fs-sdl-dubpackage --version=1.0.5 --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier +${DUB} fetch fs-sdl-dubpackage --version=1.0.5 --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier -if ! dub remove fs-sdl-dubpackage --non-interactive --version=1.0.5 2>/dev/null; then - die 'DUB did not install package from file system.' +if ! ${DUB} remove fs-sdl-dubpackage@1.0.5 2>/dev/null; then + die $LINENO 'DUB did not install package from file system.' fi echo "Trying to get fs-sdl-dubpackage (latest)" -"$DUB" fetch fs-sdl-dubpackage --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier +${DUB} fetch fs-sdl-dubpackage --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier -if ! dub remove fs-sdl-dubpackage --non-interactive --version=1.0.6 2>/dev/null; then - die 'DUB did not install latest package from file system.' +if ! ${DUB} remove fs-sdl-dubpackage@1.0.6 2>/dev/null; then + die $LINENO 'DUB did not install latest package from file system.' fi echo "Trying to get fs-json-dubpackage (1.0.7)" -"$DUB" fetch fs-json-dubpackage --version=1.0.7 --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier +${DUB} fetch fs-json-dubpackage@1.0.7 --skip-registry=all --registry=file://"$DIR"/issue1401-file-system-pkg-supplier -if ! dub remove fs-json-dubpackage --non-interactive --version=1.0.7 2>/dev/null; then - die 'DUB did not install package from file system.' +if ! ${DUB} remove fs-json-dubpackage@1.0.7 2>/dev/null; then + die $LINENO 'DUB did not install package from file system.' fi diff --git a/test/issue1416-maven-repo-pkg-supplier.sh b/test/issue1416-maven-repo-pkg-supplier.sh index 3aca25b..4b65f52 100755 --- a/test/issue1416-maven-repo-pkg-supplier.sh +++ b/test/issue1416-maven-repo-pkg-supplier.sh @@ -5,27 +5,27 @@ PORT=$(getRandomPort) -dub remove maven-dubpackage --non-interactive --version=* 2>/dev/null || true +${DUB} remove maven-dubpackage --non-interactive 2>/dev/null || true -"$DUB" build --single "$DIR"/test_registry.d +${DUB} build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1416-maven-repo-pkg-supplier" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download maven-dubpackage (1.0.5)" -"$DUB" fetch maven-dubpackage --version=1.0.5 --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages +${DUB} fetch maven-dubpackage@1.0.5 --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages -if ! dub remove maven-dubpackage --non-interactive --version=1.0.5 2>/dev/null; then - die 'DUB did not install package from maven registry.' +if ! ${DUB} remove maven-dubpackage@1.0.5 2>/dev/null; then + die $LINENO 'DUB did not install package from maven registry.' fi echo "Trying to download maven-dubpackage (latest)" -"$DUB" fetch maven-dubpackage --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages +${DUB} fetch maven-dubpackage --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages -if ! dub remove maven-dubpackage --non-interactive --version=1.0.6 2>/dev/null; then - die 'DUB fetch did not install latest package from maven registry.' +if ! ${DUB} remove maven-dubpackage@1.0.6 2>/dev/null; then + die $LINENO 'DUB fetch did not install latest package from maven registry.' fi echo "Trying to search (exact) maven-dubpackage" -"$DUB" search maven-dubpackage --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages | grep -c "maven-dubpackage (1.0.6)" +${DUB} search maven-dubpackage --skip-registry=all --registry=mvn+http://localhost:$PORT/maven/release/dubpackages | grep -c "maven-dubpackage (1.0.6)" diff --git a/test/issue1447-build-settings-vars.sh b/test/issue1447-build-settings-vars.sh index 5f60e06..b2500e5 100755 --- a/test/issue1447-build-settings-vars.sh +++ b/test/issue1447-build-settings-vars.sh @@ -18,4 +18,4 @@ rm -rf ${CURR_DIR}/issue1447-build-settings-vars/.dub rm -rf ${CURR_DIR}/issue1447-build-settings-vars/test -if [[ "$OUTPUT" != "$ARCH" ]]; then die "Build settings ARCH var incorrect"; fi +if [[ "$OUTPUT" != "$ARCH" ]]; then die $LINENO "Build settings ARCH var incorrect"; fi diff --git a/test/issue1524-maven-upgrade-dependency-tree.sh b/test/issue1524-maven-upgrade-dependency-tree.sh index 24f5f65..05dd22f 100755 --- a/test/issue1524-maven-upgrade-dependency-tree.sh +++ b/test/issue1524-maven-upgrade-dependency-tree.sh @@ -5,23 +5,23 @@ PORT=$(getRandomPort) -dub remove maven-dubpackage-a --non-interactive --version=* 2>/dev/null || true -dub remove maven-dubpackage-b --non-interactive --version=* 2>/dev/null || true +${DUB} remove maven-dubpackage-a --non-interactive 2>/dev/null || true +${DUB} remove maven-dubpackage-b --non-interactive 2>/dev/null || true -"$DUB" build --single "$DIR"/test_registry.d +${DUB} build --single "$DIR"/test_registry.d "$DIR"/test_registry --folder="$DIR/issue1524-maven-upgrade-dependency-tree" --port=$PORT & PID=$! sleep 1 trap 'kill $PID 2>/dev/null || true' exit echo "Trying to download maven-dubpackage-a (1.0.5) with dependency to maven-dubpackage-b (1.0.6)" -"$DUB" upgrade --root "$DIR/issue1524-maven-upgrade-dependency-tree" --skip-registry=standard --registry=mvn+http://localhost:$PORT/maven/release/dubpackages +${DUB} upgrade --root "$DIR/issue1524-maven-upgrade-dependency-tree" --skip-registry=standard --registry=mvn+http://localhost:$PORT/maven/release/dubpackages -if ! dub remove maven-dubpackage-a --non-interactive --version=1.0.5 2>/dev/null; then - die 'DUB did not install package "maven-dubpackage-a" from maven registry.' +if ! ${DUB} remove maven-dubpackage-a@1.0.5 2>/dev/null; then + die $LINENO 'DUB did not install package "maven-dubpackage-a" from maven registry.' fi -if ! dub remove maven-dubpackage-b --non-interactive --version=1.0.6 2>/dev/null; then - die 'DUB did not install package "maven-dubpackage-b" from maven registry.' +if ! ${DUB} remove maven-dubpackage-b@1.0.6 2>/dev/null; then + die $LINENO 'DUB did not install package "maven-dubpackage-b" from maven registry.' fi diff --git a/test/issue1531-toolchain-requirements.sh b/test/issue1531-toolchain-requirements.sh index c384198..00eb8ee 100755 --- a/test/issue1531-toolchain-requirements.sh +++ b/test/issue1531-toolchain-requirements.sh @@ -3,7 +3,7 @@ . $(dirname "${BASH_SOURCE[0]}")/common.sh -cat << EOF | $DUB - || die "Did not pass without toolchainRequirements" +cat << EOF | $DUB - || die $LINENO "Did not pass without toolchainRequirements" /+ dub.sdl: +/ void main() {} @@ -11,7 +11,7 @@ # pass test dub requirement given as $1 function test_dub_req_pass { - cat << EOF | $DUB - || die "Did not pass requirement dub=\"$1\"" + cat << EOF | $DUB - || die $LINENO "Did not pass requirement dub=\"$1\"" /+ dub.sdl: toolchainRequirements dub="$1" +/ @@ -21,7 +21,7 @@ # fail test dub requirement given as $1 function test_dub_req_fail { - ! cat << EOF | $DUB - || die "Did not pass requirement dub=\"$1\"" + ! cat << EOF | $DUB - || die $LINENO "Did not pass requirement dub=\"$1\"" /+ dub.sdl: toolchainRequirements dub="$1" +/ @@ -44,7 +44,7 @@ VER_REG='\) (([[:digit:]]+)(\.[[:digit:]]+\.[[:digit:]]+[A-Za-z0-9.+-]*))' DC_NAME=gdc else - die "Did not recognize compiler" + die $LINENO "Did not recognize compiler" fi if [[ $($DC --version) =~ $VER_REG ]]; then DC_VER=${BASH_REMATCH[1]} @@ -54,7 +54,7 @@ echo $DC version is $DC_VER else $DC --version - die "Could not extract compiler version" + die $LINENO "Could not extract compiler version" fi # create test app directory @@ -76,13 +76,13 @@ # pass test compiler requirement given as $1 function test_cl_req_pass { write_cl_req $1 - $DUB --compiler=$DC --root=$TMPDIR || die "Did not pass with $DC_NAME=\"$1\"" + $DUB --compiler=$DC --root=$TMPDIR || die $LINENO "Did not pass with $DC_NAME=\"$1\"" } # fail test compiler requirement given as $1 function test_cl_req_fail { write_cl_req $1 - ! $DUB --compiler=$DC --root=$TMPDIR || die "Did not fail with $DC_NAME=\"$1\"" + ! $DUB --compiler=$DC --root=$TMPDIR || die $LINENO "Did not fail with $DC_NAME=\"$1\"" } diff --git a/test/issue1556-fetch-and-build.sh b/test/issue1556-fetch-and-build.sh index 9e2fec4..6bef98d 100755 --- a/test/issue1556-fetch-and-build.sh +++ b/test/issue1556-fetch-and-build.sh @@ -3,8 +3,8 @@ . "$DIR"/common.sh -dub remove main-package --non-interactive --version=* 2>/dev/null || true -dub remove dependency-package --non-interactive --version=* 2>/dev/null || true +dub remove main-package --non-interactive 2>/dev/null || true +dub remove dependency-package --non-interactive 2>/dev/null || true echo "Trying to fetch fs-sdl-dubpackage" diff --git a/test/issue1567-fetch-sub-package.sh b/test/issue1567-fetch-sub-package.sh index 98ec125..62c0678 100755 --- a/test/issue1567-fetch-sub-package.sh +++ b/test/issue1567-fetch-sub-package.sh @@ -4,9 +4,9 @@ packname="fetch-sub-package-dubpackage" sub_packagename="my-sub-package" -$DUB remove $packname --non-interactive --version=* 2>/dev/null || true -$DUB fetch "$packname:$sub_packagename" --skip-registry=all --registry=file://"$DIR"/issue1567-fetch-sub-package +${DUB} remove $packname --non-interactive 2>/dev/null || true +${DUB} fetch "$packname:$sub_packagename" --skip-registry=all --registry=file://"$DIR"/issue1567-fetch-sub-package -if ! dub remove $packname --non-interactive --version=1.0.1 2>/dev/null; then - die 'DUB did not install package $packname:$sub_packagename.' -fi \ No newline at end of file +if ! ${DUB} remove $packname@1.0.1 2>/dev/null; then + die $LINENO 'DUB did not install package $packname:$sub_packagename.' +fi diff --git a/test/issue1651-custom-dub-init-type.sh b/test/issue1651-custom-dub-init-type.sh index 5c48313..0efafa9 100755 --- a/test/issue1651-custom-dub-init-type.sh +++ b/test/issue1651-custom-dub-init-type.sh @@ -3,7 +3,7 @@ DIR=$(dirname "${BASH_SOURCE[0]}") packname="custom-dub-init-type-sample" -$DUB remove custom-dub-init-dubpackage --non-interactive --version=* 2>/dev/null || true +$DUB remove custom-dub-init-dubpackage --non-interactive 2>/dev/null || true $DUB init -n $packname --format sdl -t custom-dub-init-dubpackage --skip-registry=all --registry=file://"$DIR"/issue1651-custom-dub-init-type -- --foo=bar function cleanup { @@ -22,4 +22,4 @@ die $LINENO 'Custom init type.' fi cd .. -cleanup \ No newline at end of file +cleanup diff --git a/test/issue616-describe-vs-generate-commands.sh b/test/issue616-describe-vs-generate-commands.sh index 698ef63..c8127e5 100755 --- a/test/issue616-describe-vs-generate-commands.sh +++ b/test/issue616-describe-vs-generate-commands.sh @@ -13,7 +13,7 @@ if ! $DUB describe --compiler=$DC --data-list --data=target-name \ > "$temp_file" 2>&1; then - die 'Printing project data failed!' + die $LINENO 'Printing project data failed!' fi # Create the expected output file to compare stdout against. @@ -25,5 +25,5 @@ echo "issue616-describe-vs-generate-commands" >> "$expected_file" if ! diff "$expected_file" "$temp_file"; then - die 'The stdout output did not match the expected output!' + die $LINENO 'The stdout output did not match the expected output!' fi diff --git a/test/issue990-download-optional-selected.sh b/test/issue990-download-optional-selected.sh index f46e4ca..36fd4ad 100755 --- a/test/issue990-download-optional-selected.sh +++ b/test/issue990-download-optional-selected.sh @@ -3,5 +3,5 @@ . $(dirname "${BASH_SOURCE[0]}")/common.sh cd ${CURR_DIR}/issue990-download-optional-selected ${DUB} clean -${DUB} remove gitcompatibledubpackage -n --version=* 2>/dev/null || true +${DUB} remove gitcompatibledubpackage -n 2>/dev/null || true ${DUB} run diff --git a/test/pr1549-dub-exe-var.sh b/test/pr1549-dub-exe-var.sh index 7ad9f55..52d4155 100755 --- a/test/pr1549-dub-exe-var.sh +++ b/test/pr1549-dub-exe-var.sh @@ -8,4 +8,4 @@ ${DUB} build --root ${PR1549} OUTPUT=$(${PR1549}/test-application) -if [[ "$OUTPUT" != "modified code" ]]; then die "\$DUB build variable was (likely) not evaluated correctly"; fi +if [[ "$OUTPUT" != "modified code" ]]; then die $LINENO "\$DUB build variable was (likely) not evaluated correctly"; fi diff --git a/test/run-unittest.sh b/test/run-unittest.sh index b0f29a5..943f8ef 100755 --- a/test/run-unittest.sh +++ b/test/run-unittest.sh @@ -25,7 +25,7 @@ export -f die if [ -z ${DUB:-} ]; then - die 'Variable $DUB must be defined to run the tests.' + die $LINENO 'Variable $DUB must be defined to run the tests.' fi if [ -z ${DC:-} ]; then diff --git a/test/test_registry.d b/test/test_registry.d index 7b6f67f..f50f38b 100755 --- a/test/test_registry.d +++ b/test/test_registry.d @@ -1,6 +1,6 @@ #!/usr/bin/env dub /+dub.sdl: -dependency "vibe-d" version="~>0.8.5" +dependency "vibe-d" version="~>0.9" versions "VibeNoSSL" +/ diff --git a/test/timeout.sh b/test/timeout.sh index 31209b1..4e7f7db 100755 --- a/test/timeout.sh +++ b/test/timeout.sh @@ -7,18 +7,18 @@ log ' Testing unconnectable registry' if timeout 1s $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then - die 'Fetching from unconnectable registry should fail.' + die $LINENO 'Fetching from unconnectable registry should fail.' elif [ $? -eq 124 ]; then - die 'Fetching from unconnectable registry should fail immediately.' + die $LINENO 'Fetching from unconnectable registry should fail immediately.' fi log ' Testing non-responding registry' cat | nc -l $PORT >/dev/null & PID=$! if timeout 10s $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then - die 'Fetching from non-responding registry should fail.' + die $LINENO 'Fetching from non-responding registry should fail.' elif [ $? -eq 124 ]; then - die 'Fetching from non-responding registry should time-out within 8s.' + die $LINENO 'Fetching from non-responding registry should time-out within 8s.' fi kill $PID 2>/dev/null || true @@ -37,8 +37,8 @@ } | nc -l $PORT >/dev/null & PID=$! if timeout 10s time $DUB fetch dub --skip-registry=all --registry=http://localhost:$PORT; then - die 'Fetching from too slow registry should fail.' + die $LINENO 'Fetching from too slow registry should fail.' elif [ $? -eq 124 ]; then - die 'Fetching from too slow registry should time-out within 8s.' + die $LINENO 'Fetching from too slow registry should time-out within 8s.' fi kill $PID 2>/dev/null || true diff --git a/test/version-spec.sh b/test/version-spec.sh new file mode 100755 index 0000000..76b54b8 --- /dev/null +++ b/test/version-spec.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +$DUB add-local "$CURR_DIR/version-spec/newfoo" +$DUB add-local "$CURR_DIR/version-spec/oldfoo" + +[[ $($DUB describe foo | grep path | head -n 1) == *"/newfoo/"* ]] +[[ $($DUB describe foo@1.0.0 | grep path | head -n 1) == *"/newfoo/"* ]] +[[ $($DUB describe foo@0.1.0 | grep path | head -n 1) == *"/oldfoo/"* ]] + +[[ $($DUB test foo | head -n 1) == *"/newfoo/" ]] +[[ $($DUB test foo@1.0.0 | head -n 1) == *"/newfoo/" ]] +[[ $($DUB test foo@0.1.0 | head -n 1) == *"/oldfoo/" ]] + +[[ $($DUB lint foo | tail -n 1) == *"/newfoo/" ]] +[[ $($DUB lint foo@1.0.0 | tail -n 1) == *"/newfoo/" ]] +[[ $($DUB lint foo@0.1.0 | tail -n 1) == *"/oldfoo/" ]] + +[[ $($DUB generate cmake foo | head -n 1) == *"/newfoo/" ]] +[[ $($DUB generate cmake foo@1.0.0 | head -n 1) == *"/newfoo/" ]] +[[ $($DUB generate cmake foo@0.1.0 | head -n 1) == *"/oldfoo/" ]] + +[[ $($DUB build -n foo | head -n 1) == *"/newfoo/" ]] +[[ $($DUB build -n foo@1.0.0 | head -n 1) == *"/newfoo/" ]] +[[ $($DUB build -n foo@0.1.0 | head -n 1) == *"/oldfoo/" ]] + +[[ $($DUB run -n foo | tail -n 1) == 'new-foo' ]] +[[ $($DUB run -n foo@1.0.0 | tail -n 1) == 'new-foo' ]] +[[ $($DUB run -n foo@0.1.0 | tail -n 1) == 'old-foo' ]] + +$DUB remove-local "$CURR_DIR/version-spec/newfoo" +$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/.no_build b/test/version-spec/.no_build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/version-spec/.no_build diff --git a/test/version-spec/.no_run b/test/version-spec/.no_run new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/version-spec/.no_run diff --git a/test/version-spec/.no_test b/test/version-spec/.no_test new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/version-spec/.no_test diff --git a/test/version-spec/newfoo/dub.sdl b/test/version-spec/newfoo/dub.sdl new file mode 100644 index 0000000..f1d06a6 --- /dev/null +++ b/test/version-spec/newfoo/dub.sdl @@ -0,0 +1,3 @@ +name "foo" +version "1.0.0" +targetType "executable" diff --git a/test/version-spec/newfoo/source/app.d b/test/version-spec/newfoo/source/app.d new file mode 100644 index 0000000..314f1dd --- /dev/null +++ b/test/version-spec/newfoo/source/app.d @@ -0,0 +1,2 @@ +import std.stdio; +void main() { writeln("new-foo"); } diff --git a/test/version-spec/oldfoo/dub.sdl b/test/version-spec/oldfoo/dub.sdl new file mode 100644 index 0000000..bb3a51c --- /dev/null +++ b/test/version-spec/oldfoo/dub.sdl @@ -0,0 +1,3 @@ +name "foo" +version "0.1.0" +targetType "executable" diff --git a/test/version-spec/oldfoo/source/app.d b/test/version-spec/oldfoo/source/app.d new file mode 100644 index 0000000..c4a6993 --- /dev/null +++ b/test/version-spec/oldfoo/source/app.d @@ -0,0 +1,2 @@ +import std.stdio; +void main() { writeln("old-foo"); }