diff --git a/changelog/subpackage_upgrade.dd b/changelog/subpackage_upgrade.dd new file mode 100644 index 0000000..c9a28ce --- /dev/null +++ b/changelog/subpackage_upgrade.dd @@ -0,0 +1,5 @@ +Upgrading all sub packages at once + +A new "-s" switch allows to "dub upgrade" all sub packages together with the +base package. This aims to provide a better workflow for fully reproducible +builds and tests. diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 246f8e5..946a6e4 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -1758,6 +1758,7 @@ class UpgradeCommand : Command { private { bool m_prerelease = false; + bool m_includeSubPackages = false; bool m_forceRemove = false; bool m_missingOnly = false; bool m_verify = false; @@ -1783,6 +1784,9 @@ args.getopt("prerelease", &m_prerelease, [ "Uses the latest pre-release version, even if release versions are available" ]); + args.getopt("s|sub-packages", &m_includeSubPackages, [ + "Also upgrades dependencies of all directory based sub packages" + ]); args.getopt("verify", &m_verify, [ "Updates the project and performs a build. If successful, rewrites the selected versions file ." ]); @@ -1809,6 +1813,41 @@ if (m_prerelease) options |= UpgradeOptions.preRelease; if (m_dryRun) options |= UpgradeOptions.dryRun; dub.upgrade(options, free_args); + + auto spacks = dub.project.rootPackage + .subPackages + .filter!(sp => sp.path.length); + + if (m_includeSubPackages) { + bool any_error = false; + + // Go through each path based sub package, load it as a new instance + // and perform an upgrade as if the upgrade had been run from within + // the sub package folder. Note that we have to use separate Dub + // instances, because the upgrade always works on the root package + // of a project, which in this case are the individual sub packages. + foreach (sp; spacks) { + try { + auto fullpath = (dub.projectPath ~ sp.path).toNativeString(); + logInfo("Upgrading sub package in %s", fullpath); + auto sdub = new Dub(fullpath, dub.packageSuppliers, SkipPackageSuppliers.all); + sdub.defaultPlacementLocation = dub.defaultPlacementLocation; + sdub.loadPackage(); + sdub.upgrade(options, free_args); + } catch (Exception e) { + logError("Failed to update sub package at %s: %s", + sp.path, e.msg); + any_error = true; + } + } + + if (any_error) return 1; + } else if (!spacks.empty) { + foreach (sp; spacks) + logInfo("Not upgrading sub package in %s", sp.path); + logInfo("\nNote: specify -s to also upgrade sub packages."); + } + return 0; } } diff --git a/source/dub/dub.d b/source/dub/dub.d index 833aa65..c6bc832 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -343,6 +343,8 @@ @property inout(Project) project() inout { return m_project; } + @property inout(PackageSupplier)[] packageSuppliers() inout { return m_packageSuppliers; } + /** Returns the default compiler binary to use for building D code. If set, the "defaultCompiler" field of the DUB user or system diff --git a/test/test-upgrade-subpackages.sh b/test/test-upgrade-subpackages.sh new file mode 100755 index 0000000..860e686 --- /dev/null +++ b/test/test-upgrade-subpackages.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +. $(dirname ${BASH_SOURCE[0]})/common.sh + +PACK_PATH="$CURR_DIR"/path-subpackage-ref + +# make sure that there are no left-over selections files +rm -f $PACK_PATH/dub.selections.json $PACK_PATH/subpack/dub.selections.json + +# first upgrade only the root package +if ! ${DUB} upgrade --root $PACK_PATH; then + die $LINENO 'The upgrade command failed.' +fi +if [ ! -f $PACK_PATH/dub.selections.json ] || [ -f $PACK_PATH/subpack/dub.selections.json ]; then + die $LINENO 'The upgrade command did not generate the right set of dub.selections.json files.' +fi + +rm -f $PACK_PATH/dub.selections.json + +# now upgrade with all sub packages +if ! ${DUB} upgrade -s --root $PACK_PATH; then + die $LINENO 'The upgrade command failed with -s.' +fi +if [ ! -f $PACK_PATH/dub.selections.json ] || [ ! -f $PACK_PATH/subpack/dub.selections.json ]; then + die $LINENO 'The upgrade command did not generate all dub.selections.json files.' +fi + +# clean up +rm -f $PACK_PATH/dub.selections.json $PACK_PATH/subpack/dub.selections.json diff --git a/test/timeout.sh b/test/timeout.sh index 4e7f7db..eb8d3c4 100755 --- a/test/timeout.sh +++ b/test/timeout.sh @@ -31,7 +31,7 @@ \r {}') for i in $(seq 0 $((${#res} - 1))); do - echo -n "${res:$i:1}" + echo -n "${res:$i:1}" || true sleep 1 done } | nc -l $PORT >/dev/null &