Newer
Older
dub_jkp / source / dub / packagesupplier.d
/**
	A package manager.

	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.packagesupplier;

import dub.utils;
import dub.dependency;

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

import vibe.core.log;
import vibe.core.file;
import vibe.data.json;
import vibe.inet.url;
import vibe.inet.urltransfer;

/// 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 storePackage(const Path path, const string packageId, const Dependency dep);
	
	/// returns the metadata for the package
	Json packageJson(const string packageId, const Dependency dep);
}

class FSPackageSupplier : PackageSupplier {
	private { Path m_path; }
	this(Path root) { m_path = root; }
	
	void storePackage(const Path path, const string packageId, const Dependency dep) {
		enforce(path.absolute);
		logInfo("Storing package '"~packageId~"', version requirements: %s", dep);
		auto filename = bestPackageFile(packageId, dep);
		enforce( exists(to!string(filename)) );
		copy(to!string(filename), to!string(path));
	}
	
	Json packageJson(const string packageId, const Dependency dep) {
		auto filename = bestPackageFile(packageId, dep);
		return jsonFromZip(to!string(filename), "package.json");
	}
	
	private Path bestPackageFile( const string packageId, const Dependency dep) const {
		Version bestVersion = Version(Version.RELEASE);
		foreach(DirEntry d; dirEntries(to!string(m_path), packageId~"*", SpanMode.shallow)) {
			Path p = Path(d.name);
			logTrace("Entry: %s", p);
			enforce(to!string(p.head)[$-4..$] == ".zip");
			string vers = to!string(p.head)[packageId.length+1..$-4];
			logTrace("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 || !exists(to!string(fileName)))
			throw new Exception("No matching package found");
		
		logDebug("Found best matching package: '%s'", fileName);
		return fileName;
	}
}