diff --git a/changelog/customCachePaths.dd b/changelog/customCachePaths.dd new file mode 100644 index 0000000..d9030d2 --- /dev/null +++ b/changelog/customCachePaths.dd @@ -0,0 +1,6 @@ +DUB supports "customCachePaths" for providing read-only package paths + +With this release DUB allows defining additional paths that contain packages in subfolders with the pattern "(name)-(version)/(name)/" by defining a "customCachePaths" field in `/etc/dub/settings.json` or `~/.dub/settings.json.` + +"customCachePaths" can be used to provide prebuilt DUB libraries (e.g. for distribution package maintainers). + diff --git a/source/dub/dub.d b/source/dub/dub.d index 42618dd..5ed9f06 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -189,6 +189,11 @@ m_packageSuppliers = ps; m_packageManager = new PackageManager(m_dirs.localRepository, m_dirs.systemSettings); + + auto ccps = m_config.customCachePaths; + if (ccps.length) + m_packageManager.customCachePaths = ccps; + updatePackageSearchPath(); } @@ -252,12 +257,12 @@ m_defaultArchitecture = m_config.defaultArchitecture; } - version(Windows) + version(Windows) private void migrateRepositoryFromRoaming(NativePath roamingDir, NativePath localDir) { immutable roamingDirPath = roamingDir.toNativeString(); if (!existsDirectory(roamingDir)) return; - + immutable localDirPath = localDir.toNativeString(); logInfo("Detected a package cache in " ~ roamingDirPath ~ ". This will be migrated to " ~ localDirPath ~ ". Please wait..."); if (!existsDirectory(localDir)) @@ -265,7 +270,7 @@ mkdirRecurse(localDirPath); } - runCommand("xcopy /s /e /y " ~ roamingDirPath ~ " " ~ localDirPath ~ " > NUL"); + runCommand("xcopy /s /e /y " ~ roamingDirPath ~ " " ~ localDirPath ~ " > NUL"); rmdirRecurse(roamingDirPath); } @@ -1653,6 +1658,21 @@ return ret; } + @property NativePath[] customCachePaths() + { + import std.algorithm.iteration : map; + import std.array : array; + + NativePath[] ret; + if (auto pv = "customCachePaths" in m_data) + ret = (*pv).deserializeJson!(string[]) + .map!(s => NativePath(s)) + .array; + if (m_parentConfig) + ret ~= m_parentConfig.customCachePaths; + return ret; + } + @property string defaultCompiler() const { if (auto pv = "defaultCompiler" in m_data) diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index c210b2b..13134b5 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -30,7 +30,7 @@ /// packages. class PackageManager { private { - Repository[LocalPackageType] m_repositories; + Repository[] m_repositories; NativePath[] m_searchPath; Package[] m_packages; Package[] m_temporaryPackages; @@ -39,8 +39,9 @@ this(NativePath user_path, NativePath system_path, bool refresh_packages = true) { - m_repositories[LocalPackageType.user] = Repository(user_path); - m_repositories[LocalPackageType.system] = Repository(system_path); + m_repositories.length = LocalPackageType.max+1; + m_repositories[LocalPackageType.user] = Repository(user_path ~ "packages/"); + m_repositories[LocalPackageType.system] = Repository(system_path ~ "packages/"); if (refresh_packages) refresh(true); } @@ -71,14 +72,33 @@ auto ret = appender!(NativePath[])(); ret.put(cast(NativePath[])m_searchPath); // work around Phobos 17251 if (!m_disableDefaultSearchPaths) { - ret.put(cast(NativePath[])m_repositories[LocalPackageType.user].searchPath); - ret.put(cast(NativePath)m_repositories[LocalPackageType.user].packagePath); - ret.put(cast(NativePath[])m_repositories[LocalPackageType.system].searchPath); - ret.put(cast(NativePath)m_repositories[LocalPackageType.system].packagePath); + foreach (ref repo; m_repositories) { + ret.put(cast(NativePath[])repo.searchPath); + ret.put(cast(NativePath)repo.packagePath); + } } return ret.data; } + /** Sets additional (read-only) package cache paths to search for packages. + + Cache paths have the same structure as the default cache paths, such as + ".dub/packages/". + + Note that previously set custom paths will be removed when setting this + property. + */ + @property void customCachePaths(NativePath[] custom_cache_paths) + { + import std.algorithm.iteration : map; + import std.array : array; + + m_repositories.length = LocalPackageType.max+1; + m_repositories ~= custom_cache_paths.map!(p => Repository(p)).array; + + refresh(false); + } + /** Looks up a specific package. @@ -100,8 +120,8 @@ Package getPackage(string name, Version ver, bool enable_overrides = true) { if (enable_overrides) { - foreach (tp; [LocalPackageType.user, LocalPackageType.system]) - foreach (ovr; m_repositories[tp].overrides) + foreach (ref repo; m_repositories) + foreach (ovr; repo.overrides) if (ovr.package_ == name && ovr.version_.matches(ver)) { Package pack; if (!ovr.targetPath.empty) pack = getOrLoadPackage(ovr.targetPath); @@ -266,8 +286,8 @@ if (auto ret = del(tp)) return ret; // first search local packages - foreach (tp; LocalPackageType.min .. LocalPackageType.max+1) - foreach (p; m_repositories[cast(LocalPackageType)tp].localPackages) + foreach (ref repo; m_repositories) + foreach (p; repo.localPackages) if (auto ret = del(p)) return ret; // and then all packages gathered from the search path @@ -803,7 +823,6 @@ private struct Repository { - NativePath path; NativePath packagePath; NativePath[] searchPath; Package[] localPackages; @@ -811,7 +830,6 @@ this(NativePath path) { - this.path = path; - this.packagePath = path ~"packages/"; + this.packagePath = path; } } diff --git a/test/issue838-custom-cache-paths.sh b/test/issue838-custom-cache-paths.sh new file mode 100755 index 0000000..da8e84a --- /dev/null +++ b/test/issue838-custom-cache-paths.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +. $(dirname "${BASH_SOURCE[0]}")/common.sh + +CONFIG_FILE=$CURR_DIR/../etc/dub/settings.json + +mkdir $CURR_DIR/../etc && mkdir $CURR_DIR/../etc/dub || true +echo "{\"customCachePaths\": [\"$CURR_DIR/issue838-custom-cache-paths/cache\"]}" > $CONFIG_FILE + +trap "rm $CONFIG_FILE" EXIT + +if ! { $DUB build --root "$CURR_DIR/issue838-custom-cache-paths" --skip-registry=all; }; then + die $LINENO 'Failed to build package with custom cache path for dependencies.' +fi diff --git a/test/issue838-custom-cache-paths/.no_build b/test/issue838-custom-cache-paths/.no_build new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/issue838-custom-cache-paths/.no_build diff --git a/test/issue838-custom-cache-paths/cache/foo-1.0.0/foo/dub.sdl b/test/issue838-custom-cache-paths/cache/foo-1.0.0/foo/dub.sdl new file mode 100644 index 0000000..650050d --- /dev/null +++ b/test/issue838-custom-cache-paths/cache/foo-1.0.0/foo/dub.sdl @@ -0,0 +1,3 @@ +name "foo" +version "1.0.0" +targetType "sourceLibrary" diff --git a/test/issue838-custom-cache-paths/dub.sdl b/test/issue838-custom-cache-paths/dub.sdl new file mode 100644 index 0000000..f4135fc --- /dev/null +++ b/test/issue838-custom-cache-paths/dub.sdl @@ -0,0 +1,2 @@ +name "test" +dependency "foo" version="1.0.0" diff --git a/test/issue838-custom-cache-paths/source/app.d b/test/issue838-custom-cache-paths/source/app.d new file mode 100644 index 0000000..9198103 --- /dev/null +++ b/test/issue838-custom-cache-paths/source/app.d @@ -0,0 +1,3 @@ +void main() +{ +}