diff --git a/source/dub/dub.d b/source/dub/dub.d index 0436193..bfa5980 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -65,6 +65,7 @@ /// The URL to the official package registry. enum defaultRegistryURL = "http://code.dlang.org/"; +enum fallbackRegistryURL = "https://code-mirror.dlang.io/"; /** Returns a default list of package suppliers. @@ -76,7 +77,12 @@ PackageSupplier[] defaultPackageSuppliers() { logDiagnostic("Using dub registry url '%s'", defaultRegistryURL); - return [new RegistryPackageSupplier(URL(defaultRegistryURL))]; + return [ + new FallbackPackageSupplier( + new RegistryPackageSupplier(URL(defaultRegistryURL)), + new RegistryPackageSupplier(URL(fallbackRegistryURL)) + ) + ]; } diff --git a/source/dub/packagesupplier.d b/source/dub/packagesupplier.d index cf12f3c..030bcf2 100644 --- a/source/dub/packagesupplier.d +++ b/source/dub/packagesupplier.d @@ -21,6 +21,7 @@ import std.exception; import std.file; import std.string : format; +import std.typecons : AutoImplement; import std.zip; // TODO: Could drop the "best package" behavior and let retrievePackage/ @@ -266,4 +267,41 @@ } } +package abstract class AbstractFallbackPackageSupplier : PackageSupplier +{ + protected PackageSupplier m_default, m_fallback; + + this(PackageSupplier default_, PackageSupplier fallback) + { + m_default = default_; + m_fallback = fallback; + } + + override @property string description() + { + return format("%s (fallback %s)", m_default.description, m_fallback.description); + } + + // Workaround https://issues.dlang.org/show_bug.cgi?id=2525 + abstract override Version[] getVersions(string package_id); + abstract override void fetchPackage(Path path, string package_id, Dependency dep, bool pre_release); + abstract override Json fetchPackageRecipe(string package_id, Dependency dep, bool pre_release); + abstract override SearchResult[] searchPackages(string query); +} + +/** + Combines two package suppliers and uses the second as fallback to handle failures. + + Assumes that both registries serve the same packages (--mirror). +*/ +package alias FallbackPackageSupplier = AutoImplement!(AbstractFallbackPackageSupplier, fallback); + +private template fallback(T, alias func) +{ + enum fallback = q{ + scope (failure) return m_fallback.%1$s(args); + return m_default.%1$s(args); + }.format(__traits(identifier, func)); +} + private enum PackagesPath = "packages";