cleanup trailing slash/backslash behavior of expanded vars
- expand $VARS without trailing slash/backslash
  (for concatenation e.g. `${PACKAGE_PATH}/subpath`)
1 parent 1fdf47e commit afcbcf33ff190c5c2c328921fd7fcd983cca5091
@Martin Nowak Martin Nowak authored on 23 Feb 2018
Showing 2 changed files
View
9
changelog/env-var-replacement.dd 0 → 100644
Enviroment variable expansion was improved
 
Environment variable expansion now supports the braced `${MY_VAR}` expansion syntax: e.g. for `${PACKAGE_PATH}_suffix`.
 
Moreover, `$PACKAGE_PATH`, `$ROOT_PACKAGE_PATH`, and `$DEP_PACKAGE_PATH` no longer end
with a `/` or `\` to support clean concatenation, e.g. `${PACKAGE_PATH}/subpath`.
 
Learn more about the details at $(LINK2 https://github.com/dlang/dub/pull/1392, #1392).
View
56
source/dub/project.d
 
private string getVariable(Project, Package)(string name, in Project project, in Package pack, in GeneratorSettings gsettings)
{
import std.process : environment;
if (name == "PACKAGE_DIR") return pack.path.toNativeString();
if (name == "ROOT_PACKAGE_DIR") return project.rootPackage.path.toNativeString();
Path path;
if (name == "PACKAGE_DIR")
path = pack.path;
else if (name == "ROOT_PACKAGE_DIR")
path = project.rootPackage.path;
 
if (name.endsWith("_PACKAGE_DIR")) {
auto pname = name[0 .. $-12];
foreach (prj; project.getTopologicalPackageList())
if (prj.name.toUpper().replace("-", "_") == pname)
return prj.path.toNativeString();
{
path = prj.path;
break;
}
}
 
if (!path.empty)
{
// no trailing slash for clean path concatenation (see #1392)
path.endsWithSlash = false;
return path.toNativeString();
}
 
if (name == "ARCH") {
foreach (a; gsettings.platform.architecture)
this(string name)
{
this.name = name;
version (Posix)
path = NativePath("/pkgs/"~name~"/");
path = NativePath("/pkgs/"~name);
else version (Windows)
path = NativePath(`C:\pkgs\`~name~`\`);
path = NativePath(`C:\pkgs\`~name);
// see 4d4017c14c, #268, and #1392 for why this all package paths end on slash internally
path.endsWithSlash = true;
}
string name;
NativePath path;
}
};
auto pack = MockPackage("test");
GeneratorSettings gsettings;
enum isPath = true;
 
version (Posix) enum sep = "/";
else version (Windows) enum sep = `\`;
static Path woSlash(Path p) { p.endsWithSlash = false; return p; }
// basic vars
assert(processVars("Hello $PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~pack.path.toNativeString);
assert(processVars("Hello $ROOT_PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~proj.rootPackage.path.toNativeString);
assert(processVars("Hello $DEP1_PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~proj._dependencies[0].path.toNativeString);
// ${VAR} replacements, NOTE: PACKAGE_DIR et.al. end on /
assert(processVars("Hello ${PACKAGE_DIR}foobar", proj, pack, gsettings, !isPath) == "Hello "~(pack.path ~ "foobar").toNativeString);
assert(processVars("Hello $PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~woSlash(pack.path).toNativeString);
assert(processVars("Hello $ROOT_PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~woSlash(proj.rootPackage.path).toNativeString.chomp(sep));
assert(processVars("Hello $DEP1_PACKAGE_DIR", proj, pack, gsettings, !isPath) == "Hello "~woSlash(proj._dependencies[0].path).toNativeString);
// ${VAR} replacements
assert(processVars("Hello ${PACKAGE_DIR}"~sep~"foobar", proj, pack, gsettings, !isPath) == "Hello "~(pack.path ~ "foobar").toNativeString);
assert(processVars("Hello $PACKAGE_DIR"~sep~"foobar", proj, pack, gsettings, !isPath) == "Hello "~(pack.path ~ "foobar").toNativeString);
// test with isPath
assert(processVars("local", proj, pack, gsettings, isPath) == (pack.path ~ "local").toNativeString);
// test other env variables
import std.process : environment;