From 8d39470ed5a33741c985f86d06c89842bdc77652 Mon Sep 17 00:00:00 2001 From: "richard (rikki) andrew cattermole" Date: Mon, 20 Nov 2023 22:05:02 +1300 Subject: [PATCH] Fix issue #2190 - windows: dub won't run if TEMP is unset or empty --- source/dub/commandline.d | 25 ++++++++++++--- test/issue2190-unset-TEMP.script.d | 51 ++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 test/issue2190-unset-TEMP.script.d diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 5bb5db064..d3367cb62 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -371,6 +371,8 @@ unittest { */ int runDubCommandLine(string[] args) { + import std.file : tempDir; + static string[] toSinglePackageArgs (string args0, string file, string[] trailing) { return [args0, "run", "-q", "--temp-build", "--single", file, "--"] ~ trailing; @@ -382,11 +384,24 @@ int runDubCommandLine(string[] args) logDiagnostic("DUB version %s", getDUBVersion()); - version(Windows){ - // rdmd uses $TEMP to compute a temporary path. since cygwin substitutes backslashes - // with slashes, this causes OPTLINK to fail (it thinks path segments are options) - // we substitute the other way around here to fix this. - environment["TEMP"] = environment["TEMP"].replace("/", "\\"); + { + version(Windows) { + // Guarantee that this environment variable is set + // this is specifically needed because of the Windows fix that follows this statement. + // While it probably isn't needed for all targets, it does simplify things a bit. + // Question is can it be more generic? Probably not due to $TMP + if ("TEMP" !in environment) + environment["TEMP"] = tempDir(); + + // rdmd uses $TEMP to compute a temporary path. since cygwin substitutes backslashes + // with slashes, this causes OPTLINK to fail (it thinks path segments are options) + // we substitute the other way around here to fix this. + + // In case the environment variable TEMP is empty (it should never be), we'll swap out + // opIndex in favor of get with the fallback. + + environment["TEMP"] = environment.get("TEMP", null).replace("/", "\\"); + } } auto handler = CommandLineHandler(getCommands()); diff --git a/test/issue2190-unset-TEMP.script.d b/test/issue2190-unset-TEMP.script.d new file mode 100644 index 000000000..398695346 --- /dev/null +++ b/test/issue2190-unset-TEMP.script.d @@ -0,0 +1,51 @@ +/+ dub.json: { + "name": "issue2190_unset_TEMP" +} +/ + +module issue2190_unset_TEMP.script; + +int main() +{ + import std.stdio; + import std.algorithm; + import std.path; + import std.process; + + const dir = __FILE_FULL_PATH__.dirName(); + + // doesn't matter, just pick something + const file = buildPath(dir, "single-file-sdl-default-name.d"); + + const dub = environment.get("DUB", buildPath(dirName(dir), "bin", "dub.exe")); + + int exitCode; + + void runTest(scope const string[] cmd) + { + const result = execute(cmd); + + if (result.status || result.output.canFind("Failed")) + { + writefln("\n> %-(%s %)", cmd); + writeln("==========================================================="); + writeln(result.output); + writeln("==========================================================="); + writeln("Last command failed with exit code ", result.status, '\n'); + exitCode = 1; + } + } + + environment.remove("TEMP"); + + // only guaranteed to be there on Windows + // See: runDubCommandLine in commandline + version(Windows) + { + runTest([ + dub, "build", + "--single", file, + ]); + } + + return exitCode; +}