Newer
Older
dub_jkp / source / dub / registry.d
/**
	A package supplier using the registry server.

	Copyright: © 2012 Matthias Dondorff
	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
	Authors: Matthias Dondorff
*/
module dub.registry;

import dub.dependency;
import dub.packagesupplier;
import dub.utils;

import vibe.core.file;
import vibe.core.log;
import vibe.data.json;
import vibe.http.client;
import vibe.http.fileserver;
import vibe.http.router;
import vibe.inet.url;
import vibe.inet.urltransfer;

import std.conv;
import std.exception;
import std.file;

private const string PackagesPath = "packages";


/// Client PackageSupplier using the registry available via registerVpmRegistry
class RegistryPS : PackageSupplier {
	this(Url registry) { m_registryUrl = registry; }
	
	void storePackage(const Path path, const string packageId, const Dependency dep) {
		Json best = bestPackage(packageId, dep);
		logDebug("Found dllinkg: '%s'", best["url"]);
		download(cast(string) best["url"], to!string(path));
	}
	
	Json packageJson(const string packageId, const Dependency dep) {
		return bestPackage(packageId, dep);
	}
	
	private {
		Url m_registryUrl;
		Json[string] m_allMetadata;
	}
	
	private Json metadata(const string packageId) {
		if( auto json = packageId in m_allMetadata ) 
			return *json;
		
		logTrace("Downloading metadata for %s", packageId);
		logTrace("Connecting to %s", m_registryUrl.host);
		auto client = new HttpClient;
		bool ssl = m_registryUrl.schema == "https";
		ushort port = m_registryUrl.port != 0? m_registryUrl.port : ssl? 443 : 80;
		client.connect(m_registryUrl.host, port, ssl);
		auto res = client.request((req) {
				req.url = to!string(m_registryUrl.path ~ (PackagesPath ~ "/" ~ packageId ~ ".json"));
				logTrace("Requested '%s'", req.url);
			});
		
		if(res.statusCode == 404) {
			logError("Could not get metadata for %s", packageId);
			throw new Exception("Could not get metadata for " ~ packageId);
		}
		
		string jsonData = cast(string)res.bodyReader.readAll();
		Json json = parseJson(jsonData);
		m_allMetadata[packageId] = json;
		return json;
	}
	
	private Json bestPackage(const string packageId, const Dependency dep) {
		Json md = metadata(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);
		return best;
	}
}