- /**
- A package supplier, able to get some packages to the local FS.
-
- Copyright: © 2012-2013 Matthias Dondorff
- License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
- Authors: Matthias Dondorff
- */
- module dub.packagesupplier;
-
- import dub.dependency;
- import dub.internal.utils;
- import dub.internal.vibecompat.core.log;
- import dub.internal.vibecompat.core.file;
- import dub.internal.vibecompat.data.json;
- import dub.internal.vibecompat.inet.url;
-
- import std.file;
- import std.exception;
- import std.zip;
- import std.conv;
-
- /// Supplies packages, this is done by supplying the latest possible version
- /// which is available.
- interface PackageSupplier {
- /// path: absolute path to store the package (usually in a zip format)
- void retrievePackage(Path path, string packageId, Dependency dep);
-
- /// returns the metadata for the package
- Json getPackageDescription(string packageId, Dependency dep);
-
- /// Returns a hunman readable representation of the supplier
- string toString();
- }
-
- class FileSystemPackageSupplier : PackageSupplier {
- private {
- Path m_path;
- }
-
- this(Path root) { m_path = root; }
-
- override string toString() { return "file repository at "~m_path.toNativeString(); }
-
- void retrievePackage(Path path, string packageId, Dependency dep)
- {
- enforce(path.absolute);
- logInfo("Storing package '"~packageId~"', version requirements: %s", dep);
- auto filename = bestPackageFile(packageId, dep);
- enforce(existsFile(filename));
- copyFile(filename, path);
- }
-
- Json getPackageDescription(string packageId, Dependency dep)
- {
- auto filename = bestPackageFile(packageId, dep);
- return jsonFromZip(filename, "package.json");
- }
-
- private Path bestPackageFile(string packageId, Dependency dep)
- const {
- Version bestVersion = Version.RELEASE;
- foreach (DirEntry d; dirEntries(m_path.toNativeString(), packageId~"*", SpanMode.shallow)) {
- Path p = Path(d.name);
- logDebug("Entry: %s", p);
- enforce(to!string(p.head)[$-4..$] == ".zip");
- string vers = to!string(p.head)[packageId.length+1..$-4];
- logDebug("Version string: "~vers);
- Version v = Version(vers);
- if (v > bestVersion && dep.matches(v)) {
- bestVersion = v;
- }
- }
-
- auto fileName = m_path ~ (packageId ~ "_" ~ to!string(bestVersion) ~ ".zip");
-
- if (bestVersion == Version.RELEASE || !existsFile(fileName))
- throw new Exception("No matching package found");
-
- logDiagnostic("Found best matching package: '%s'", fileName);
- return fileName;
- }
- }
-
-
- /// Client PackageSupplier using the registry available via registerVpmRegistry
- class RegistryPackageSupplier : PackageSupplier {
- private {
- Url m_registryUrl;
- Json[string] m_allMetadata;
- }
-
- this(Url registry)
- {
- m_registryUrl = registry;
- }
-
- override string toString() { return "registry at "~m_registryUrl.toString(); }
-
- void retrievePackage(Path path, string packageId, Dependency dep)
- {
- Json best = getBestPackage(packageId, dep);
- auto url = m_registryUrl ~ Path(PackagesPath~"/"~packageId~"/"~best["version"].get!string~".zip");
- logDiagnostic("Found download URL: '%s'", url);
- download(url, path);
- }
-
- Json getPackageDescription(string packageId, Dependency dep)
- {
- return getBestPackage(packageId, dep);
- }
-
- private Json getMetadata(string packageId)
- {
- if (auto json = packageId in m_allMetadata)
- return *json;
-
- auto url = m_registryUrl ~ Path(PackagesPath ~ "/" ~ packageId ~ ".json");
-
- logDebug("Downloading metadata for %s", packageId);
- logDebug("Getting from %s", url);
-
- auto jsonData = cast(string)download(url);
- Json json = parseJson(jsonData);
- m_allMetadata[packageId] = json;
- return json;
- }
-
- private Json getBestPackage(string packageId, Dependency dep)
- {
- Json md = getMetadata(packageId);
- Json best = null;
- foreach (json; md["versions"]) {
- auto cur = Version(cast(string)json["version"]);
- if (dep.matches(cur) && (best == null || Version(cast(string)best["version"]) < cur))
- best = json;
- }
- enforce(best != null, "No package candidate found for "~packageId~" "~dep.toString());
- return best;
- }
- }
-
- private enum PackagesPath = "packages";