Add support for DUBPATH and "add-path" + change the default installation location to the DUB user path. Fixes #64.
This change allows to specify a number of directories in addition to the system and user DUB package directories to search for local packages.

Full list of changes:

 - Add support for the DUBPATH environment variable (a (semi-)colon separated list of paths)
 - Add support for "dub add-path" and "dub remove-path" to add static search paths
 - The branch of local packages with no "version" field in their package.json is now inferred using "git rev-parse"
 - The structure of the user/system package directories is changed from "packages/<packname>/<packver>" to "packages/<packname>-<packver>"
 - There is no project local package directory (".dub/packages") anymore - packages are instead installed to the user package directory by default
 - Upgrading and uninstallation is partially broken in this commit - will be fixed later
1 parent 84b37f1 commit 3560f92307d95d91da8b743567af6de54ca046b9
@Sönke Ludwig Sönke Ludwig authored on 4 Jun 2013
Showing 5 changed files
View
32
source/app.d
case "upgrade":
dub.loadPackageFromCwd();
logInfo("Upgrading project in %s", dub.projectPath.toNativeString());
logDebug("dub initialized");
dub.update(UpdateOptions.Reinstall | (annotate ? UpdateOptions.JustAnnotate : UpdateOptions.None));
dub.update(UpdateOptions.Upgrade | (annotate ? UpdateOptions.JustAnnotate : UpdateOptions.None));
return 0;
case "install":
enforce(args.length >= 2, "Missing package name.");
auto location = InstallLocation.userWide;
case "remove-local":
enforce(args.length >= 2, "Missing path to package.");
dub.removeLocalPackage(args[1], install_system);
break;
case "list-locals":
case "list-system":
case "list-user":
auto toList = cmd == "list-locals"? InstallLocation.local
: cmd == "list-system"? InstallLocation.systemWide
: InstallLocation.userWide;
logInfo(cmd == "list-locals"? "Locals:" : cmd == "list-system"? "System:" : "User:");
foreach( p; dub.packageManager.getPackageIterator() )
if( p.installLocation == toList)
logInfo(" %s %s: %s", p.name, p.ver, p.path.toNativeString());
case "add-path":
enforce(args.length >= 2, "Missing search path.");
dub.addSearchPath(args[1], install_system);
break;
case "remove-path":
enforce(args.length >= 2, "Missing search path.");
dub.removeSearchPath(args[1], install_system);
break;
case "list-installed":
logInfo("Installed packages:");
foreach (p; dub.packageManager.getPackageIterator())
logInfo(" %s %s: %s", p.name, p.ver, p.path.toNativeString());
logInfo("");
break;
case "run":
case "build":
uninstall <name> Uninstalls a package. See 'dub help uninstall'.
add-local <dir> <version>
Adds a local package directory (e.g. a git repository)
remove-local <dir> Removes a local package directory
list-locals Prints a list of all locals
list-system Prints a list of all system wide installed packages.
list-user Prints a list of all user installed packages.
list-installed Prints a list of all installed packages
generate <name> Generates project files using the specified generator:
visuald, mono-d, build, rdmd
describe Prints a JSON description of the project and its
dependencies
View
92
source/dub/dub.d
/// The Dub class helps in getting the applications
/// dependencies up and running. An instance manages one application.
class Dub {
private {
PackageManager m_packageManager;
PackageSupplier[] m_packageSuppliers;
Path m_cwd, m_tempPath;
Path m_root;
PackageSupplier[] m_packageSuppliers;
Path m_userDubPath, m_systemDubPath;
Json m_systemConfig, m_userConfig;
PackageManager m_packageManager;
Path m_projectPath;
Project m_project;
}
 
/// Initiales the package manager for the vibe application
m_userConfig = jsonFromFile(m_userDubPath ~ "settings.json", true);
m_systemConfig = jsonFromFile(m_systemDubPath ~ "settings.json", true);
 
m_packageSuppliers = ps;
m_packageManager = new PackageManager(m_systemDubPath ~ "packages/", m_userDubPath ~ "packages/");
m_packageManager = new PackageManager(m_userDubPath, m_systemDubPath);
updatePackageSearchPath();
}
 
/// Returns the name listed in the package.json of the current
/// application.
@property string projectName() const { return m_project.name; }
 
@property Path projectPath() const { return m_root; }
@property Path projectPath() const { return m_projectPath; }
 
@property string[] configurations() const { return m_project.configurations; }
 
@property inout(PackageManager) packageManager() inout { return m_packageManager; }
}
 
void loadPackage(Path path)
{
m_root = path;
m_packageManager.projectPackagePath = m_root ~ ".dub/packages/";
m_project = new Project(m_packageManager, m_root);
m_projectPath = path;
updatePackageSearchPath();
m_project = new Project(m_packageManager, m_projectPath);
}
 
string getDefaultConfiguration(BuildPlatform platform) const { return m_project.getDefaultConfiguration(platform); }
 
}
enforce(pinfo.type != Json.Type.Undefined, "No package "~packageId~" was found matching the dependency "~dep.toString());
string ver = pinfo["version"].get!string;
 
if( auto pack = m_packageManager.getPackage(packageId, ver, location) ){
Path install_path;
final switch (location) {
case InstallLocation.local: install_path = m_cwd; break;
case InstallLocation.projectLocal: install_path = m_project.mainPackage.path ~ ".dub/packages/"; break;
case InstallLocation.userWide: install_path = m_userDubPath ~ "packages/"; break;
case InstallLocation.systemWide: install_path = m_systemDubPath ~ "packages/"; break;
}
 
if( auto pack = m_packageManager.getPackage(packageId, ver, install_path) ){
logInfo("Package %s %s (%s) is already installed with the latest version, skipping upgrade.",
packageId, ver, location);
packageId, ver, install_path);
return pack;
}
 
logInfo("Downloading %s %s...", packageId, ver);
 
logDebug("Acquiring package zip file");
auto dload = m_root ~ ".dub/temp/downloads";
auto dload = m_projectPath ~ ".dub/temp/downloads";
auto tempfname = packageId ~ "-" ~ (ver.startsWith('~') ? ver[1 .. $] : ver) ~ ".zip";
auto tempFile = m_tempPath ~ tempfname;
string sTempFile = tempFile.toNativeString();
if(exists(sTempFile)) remove(sTempFile);
supplier.retrievePackage(tempFile, packageId, dep); // Q: continue on fail?
scope(exit) remove(sTempFile);
 
logInfo("Installing %s %s...", packageId, ver);
return m_packageManager.install(tempFile, pinfo, location);
auto clean_package_version = ver[ver.startsWith("~") ? 1 : 0 .. $];
Path dstpath = install_path ~ (packageId ~ "-" ~ clean_package_version);
 
return m_packageManager.install(tempFile, pinfo, dstpath);
}
 
/// Uninstalls a given package from the list of installed modules.
/// @removeFromApplication: if true, this will also remove an entry in the
/// exception, if there are multiple versions installed.
/// Note: as wildcard string only "*" is supported.
/// @param location_
void uninstall(string package_id, string version_, InstallLocation location_) {
enforce(!package_id.empty);
/+enforce(!package_id.empty);
Package[] packages;
const bool wildcardOrEmpty = version_ == UninstallVersionWildcard || version_.empty;
if(location_ == InstallLocation.local) {
// Try folder named like the package_id in the cwd.
uninstall(pack);
logInfo("Uninstalled %s, version %s.", package_id, pack.vers);
}
catch logError("Failed to uninstall %s, version %s. Continuing with other packages (if any).", package_id, pack.vers);
}
}+/
}
 
void addLocalPackage(string path, string ver, bool system)
{
auto abs_path = Path(path);
if( !abs_path.absolute ) abs_path = m_cwd ~ abs_path;
m_packageManager.addLocalPackage(abs_path, Version(ver), system ? LocalPackageType.system : LocalPackageType.user);
m_packageManager.addLocalPackage(makeAbsolute(path), Version(ver), system ? LocalPackageType.system : LocalPackageType.user);
}
 
void removeLocalPackage(string path, bool system)
{
auto abs_path = Path(path);
if( !abs_path.absolute ) abs_path = m_cwd ~ abs_path;
m_packageManager.removeLocalPackage(abs_path, system ? LocalPackageType.system : LocalPackageType.user);
m_packageManager.removeLocalPackage(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user);
}
 
void addSearchPath(string path, bool system)
{
m_packageManager.addSearchPath(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user);
}
 
void removeSearchPath(string path, bool system)
{
m_packageManager.removeSearchPath(makeAbsolute(path), system ? LocalPackageType.system : LocalPackageType.user);
}
 
void createEmptyPackage(Path path)
{
version(Windows) commands ~= "xcopy /S /D "~dub_path~"public\\* docs\\";
else commands ~= "cp -r "~dub_path~"public/* docs/";
runCommands(commands);
}
 
private void updatePackageSearchPath()
{
auto p = environment.get("DUBPATH");
Path[] paths;
version(Windows) if (p.length) paths ~= p.split(":").map!(p => Path(p))().array();
else if (p.length) paths ~= p.split(";").map!(p => Path(p))().array();
m_packageManager.searchPath = paths;
}
 
private Path makeAbsolute(Path p) const { return p.absolute ? p : m_cwd ~ p; }
private Path makeAbsolute(string p) const { return makeAbsolute(Path(p)); }
}
View
source/dub/package_.d
View
source/dub/packagemanager.d
View
source/dub/project.d