Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions changelog/dub-run.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
`dub run` will now automatically fetch a package if it's not found locally

Starting with this release, `dub run <mypackage>` makes sure that the package is available locally.
This means that now a `dub fetch <mypackage>` is no longer required and all a user of a library needs to run your dub package is `dub run`:

$(CONSOLE
> dub run gitcompatibledubpackage
gitcompatibledubpackage wasn't found locally, but it's available online:
---
Description: Example of a DUB package also usable as git submodule. For DUB test suite.
Version: 1.0.4
---
Do you want to fetch gitcompatibledubpackage? [Y/n]:
)

An optional `--yes` (`-y`) flag is provided for non-interactive use:

$(CONSOLE
> dub run --yes gitcompatibledubpackage
gitcompatibledubpackage wasn't found locally, but it's available online:
---
Description: Example of a DUB package also usable as git submodule. For DUB test suite.
Version: 1.0.4
---
Fetching gitcompatibledubpackage 1.0.4...
Building package gitcompatibledubpackage in /home/seb/.dub/packages/gitcompatibledubpackage-1.0.4/gitcompatibledubpackage/
Performing "debug" build using dmd for x86_64.
gitcompatibledubpackage 1.0.4: building configuration "exe"...
Linking...
Running ../../.dub/packages/gitcompatibledubpackage-1.0.4/gitcompatibledubpackage/gitcompatibledubpackage
Hello DUB
)

If one wants to run a specific version of a package, it can be passed to `dub run` too:

$(CONSOLE
> dub run gitcompatibledubpackage@1.0.3
Fetching gitcompatibledubpackage 1.0.3...
Building package gitcompatibledubpackage in /home/seb/.dub/packages/gitcompatibledubpackage-1.0.3/gitcompatibledubpackage/
Performing "debug" build using dmd for x86_64.
gitcompatibledubpackage 1.0.3: building configuration "exe"...
Linking...
Running ../../.dub/packages/gitcompatibledubpackage-1.0.3/gitcompatibledubpackage/gitcompatibledubpackage
Hello DUB
)
61 changes: 60 additions & 1 deletion source/dub/commandline.d
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ class InitCommand : Command {
free_args = free_args[1 .. $];
}

string input(string caption, string default_value)
static string input(string caption, string default_value)
{
writef("%s [%s]: ", caption, default_value);
auto inp = readln();
Expand Down Expand Up @@ -829,6 +829,7 @@ class GenerateCommand : PackageBuildCommand {
}

class BuildCommand : GenerateCommand {
bool m_yes; // automatic yes to prompts;
this()
{
this.name = "build";
Expand All @@ -848,12 +849,70 @@ class BuildCommand : GenerateCommand {
args.getopt("f|force", &m_force, [
"Forces a recompilation even if the target is up to date"
]);
args.getopt("y|yes", &m_yes, [
`Automatic yes to prompts. Assume "yes" as answer to all prompts and run non-interactively.`
]);
super.prepare(args);
m_generator = "build";
}

override int execute(Dub dub, string[] free_args, string[] app_args)
{
// single package files don't need to be downloaded, they are on the disk.
if (free_args.length < 1 || m_single)
return super.execute(dub, free_args, app_args);

const package_parts = splitPackageName(free_args[0]);
const package_name = package_parts.name;

static bool input(string caption, bool default_value = true) {
writef("%s [%s]: ", caption, default_value ? "Y/n" : "y/N");
auto inp = readln();
string userInput = "y";
if (inp.length > 1)
userInput = inp[0 .. $ - 1].toLower;

switch (userInput) {
case "no", "n", "0":
return false;
case "yes", "y", "1":
default:
return true;
}
}

Dependency dep;

if (package_parts.version_.length > 0) {
// the user provided a version manually
free_args[0] = package_name;
dep = Dependency(package_parts.version_);
} else {
const pack = dub.packageManager.getFirstPackage(package_name);
if (pack)
return super.execute(dub, free_args, app_args);

// search for the package and filter versions for exact matches
auto search = dub.searchPackages(package_name)
.map!(tup => tup[1].find!(p => p.name == package_name))
.filter!(ps => !ps.empty);
if (search.empty)
return 2;

const p = search.front.front;
logInfo("%s wasn't found locally, but it's available online:", package_name);
logInfo("---");
logInfo("Description: %s", p.description);
logInfo("Version: %s", p.version_);
logInfo("---");

const answer = m_yes ? true : input("Do you want to fetch %s?".format(package_name));
if (!answer)
return 0;
dep = Dependency(p.version_);
}

dub.fetch(package_name, dep, dub.defaultPlacementLocation, FetchOptions.none);
return super.execute(dub, free_args, app_args);
}
}
Expand Down
32 changes: 32 additions & 0 deletions test/issue877-auto-fetch-package-on-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash

set -eu -o pipefail
set -x
$DUB remove --version="*" gitcompatibledubpackage || true

# check whether the interactive run mode works
echo "y" | $DUB run gitcompatibledubpackage | grep "Hello DUB"
$DUB remove gitcompatibledubpackage

! (echo "n" | $DUB run gitcompatibledubpackage | grep "Hello DUB")
! $DUB remove gitcompatibledubpackage

# check -y
$DUB run --yes gitcompatibledubpackage | grep "Hello DUB"
$DUB remove gitcompatibledubpackage

# check --yes
$DUB run -y gitcompatibledubpackage | grep "Hello DUB"
$DUB remove gitcompatibledubpackage

# check supplying versions directly
dub_log="$($DUB run gitcompatibledubpackage@1.0.3)"
echo "$dub_log" | grep "Hello DUB"
echo "$dub_log" | grep "Fetching.*1.0.3"
$DUB remove gitcompatibledubpackage

# check supplying an invalid version
(! $DUB run gitcompatibledubpackage@0.42.43) 2>&1 | \
grep 'No package gitcompatibledubpackage was found matching the dependency 0[.]42[.]43'

! $DUB remove gitcompatibledubpackage