diff --git a/source/app.d b/source/app.d index eaf2bf4..da23361 100644 --- a/source/app.d +++ b/source/app.d @@ -146,7 +146,7 @@ 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."); @@ -188,16 +188,18 @@ 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": @@ -322,9 +324,7 @@ add-local Adds a local package directory (e.g. a git repository) remove-local 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 Generates project files using the specified generator: visuald, mono-d, build, rdmd describe Prints a JSON description of the project and its diff --git a/source/dub/dub.d b/source/dub/dub.d index 0631d79..a207041 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -50,12 +50,12 @@ /// dependencies up and running. An instance manages one application. class Dub { private { - Path m_cwd, m_tempPath; - Path m_root; + PackageManager m_packageManager; PackageSupplier[] m_packageSuppliers; + Path m_cwd, m_tempPath; Path m_userDubPath, m_systemDubPath; Json m_systemConfig, m_userConfig; - PackageManager m_packageManager; + Path m_projectPath; Project m_project; } @@ -79,14 +79,15 @@ 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; } @@ -99,9 +100,9 @@ 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); } @@ -202,16 +203,24 @@ 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(); @@ -220,7 +229,10 @@ 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. @@ -247,7 +259,7 @@ /// 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) { @@ -290,21 +302,27 @@ 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) @@ -405,4 +423,16 @@ 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)); } } diff --git a/source/dub/package_.d b/source/dub/package_.d index ed9a4c1..83fdf06 100644 --- a/source/dub/package_.d +++ b/source/dub/package_.d @@ -50,19 +50,17 @@ static struct LocalPackageDef { string name; Version version_; Path path; } private { - InstallLocation m_location; Path m_path; PackageInfo m_info; } - this(InstallLocation location, Path root) + this(Path root) { - this(jsonFromFile(root ~ PackageJsonFilename), location, root); + this(jsonFromFile(root ~ PackageJsonFilename), root); } - this(Json packageInfo, InstallLocation location = InstallLocation.local, Path root = Path()) + this(Json packageInfo, Path root = Path()) { - m_location = location; m_path = root; // check for default string import folders @@ -90,6 +88,28 @@ { scope(failure) logError("Failed to parse package description in %s", root.toNativeString()); m_info.parseJson(packageInfo); + + // try to run git to determine the version of the package if no explicit version was given + if (m_info.version_.length == 0) { + import dub.internal.std.process; + try { + auto branch = execute(["git", "--git-dir="~(root~".git").toNativeString(), "rev-parse", "--abbrev-ref", "HEAD"]); + enforce(branch.status == 0, "git rev-parse failed: " ~ branch.output); + if (branch.output.strip() == "HEAD") { + //auto ver = execute("git",) + enforce(false, "oops"); + } else { + m_info.version_ = "~" ~ branch.output.strip(); + } + } catch (Exception e) { + logDebug("Failed to run git: %s", e.msg); + } + + if (m_info.version_.length == 0) { + logDebug("Failed to determine version of package %s at %s. Assuming ~master.", m_info.name, this.path.toNativeString()); + m_info.version_ = "~master"; + } else logDebug("Determined package version using GIT: %s %s", m_info.name, m_info.version_); + } } // generate default configurations if none are defined @@ -119,7 +139,6 @@ @property string vers() const { return m_info.version_; } @property Version ver() const { return Version(m_info.version_); } @property const(PackageInfo) info() const { return m_info; } - @property installLocation() const { return m_location; } @property Path path() const { return m_path; } @property Path packageInfoFile() const { return m_path ~ "package.json"; } @property const(Dependency[string]) dependencies() const { return m_info.dependencies; } diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index f20bea9..4305907 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -17,6 +17,7 @@ import dub.utils; import std.algorithm : countUntil, filter, sort, canFind; +import std.array; import std.conv; import std.digest.sha; import std.exception; @@ -28,8 +29,21 @@ enum JournalJsonFilename = "journal.json"; enum LocalPackagesFilename = "local-packages.json"; + +private struct Repository { + Path path; + Path packagePath; + Path[] searchPath; + Package[] localPackages; + + this(Path path) + { + this.path = path; + this.packagePath = path ~"packages/"; + } +} + enum LocalPackageType { - temporary, user, system } @@ -37,27 +51,32 @@ class PackageManager { private { - Path m_systemPackagePath; - Path m_userPackagePath; - Path m_projectPackagePath; - Package[][string] m_systemPackages; - Package[][string] m_userPackages; - Package[string] m_projectPackages; - Package[] m_localTemporaryPackages; - Package[] m_localUserPackages; - Package[] m_localSystemPackages; + Repository[LocalPackageType] m_repositories; + Path[] m_searchPath; + Package[][string] m_packages; + Package[] m_temporaryPackages; } - this(Path system_package_path, Path user_package_path, Path project_package_path = Path()) + this(Path user_path, Path system_path) { - m_systemPackagePath = system_package_path; - m_userPackagePath = user_package_path; - m_projectPackagePath = project_package_path; + m_repositories[LocalPackageType.user] = Repository(user_path); + m_repositories[LocalPackageType.system] = Repository(system_path); refresh(); } - @property Path projectPackagePath() const { return m_projectPackagePath; } - @property void projectPackagePath(Path path) { m_projectPackagePath = path; refresh(); } + @property void searchPath(Path[] paths) { m_searchPath = paths.dup; refresh(); } + @property const(Path)[] searchPath() const { return m_searchPath; } + + @property const(Path)[] completeSearchPath() + const { + auto ret = appender!(Path[])(); + ret.put(m_searchPath); + ret.put(m_repositories[LocalPackageType.user].searchPath); + ret.put(m_repositories[LocalPackageType.user].packagePath); + ret.put(m_repositories[LocalPackageType.system].searchPath); + ret.put(m_repositories[LocalPackageType.system].packagePath); + return ret.data; + } Package getPackage(string name, Version ver) { @@ -67,10 +86,22 @@ return null; } - Package getPackage(string name, string ver, InstallLocation location) + Package getPackage(string name, string ver, Path in_path) { - foreach(ep; getPackageIterator(name)){ - if( ep.installLocation == location && ep.vers == ver ) + return getPackage(name, Version(ver), in_path); + } + Package getPackage(string name, Version ver, Path in_path) + { + foreach( p; getPackageIterator(name) ) + if (p.ver == ver && p.path.startsWith(in_path)) + return p; + return null; + } + + Package getPackage(string name, string ver) + { + foreach (ep; getPackageIterator(name)) { + if (ep.vers == ver) return ep; } return null; @@ -94,32 +125,19 @@ { int iterator(int delegate(ref Package) del) { - // first search project local packages - foreach( p; m_localTemporaryPackages ) - if( auto ret = del(p) ) return ret; - foreach( p; m_projectPackages ) - if( auto ret = del(p) ) return ret; + foreach (tp; m_temporaryPackages) + if (auto ret = del(tp)) return ret; - // then local packages - foreach( p; m_localUserPackages ) - if( auto ret = del(p) ) return ret; + // first search local packages + foreach (tp; LocalPackageType.min .. LocalPackageType.max+1) + foreach (p; m_repositories[cast(LocalPackageType)tp].localPackages) + if (auto ret = del(p)) return ret; - // then local packages - foreach( p; m_localSystemPackages ) - if( auto ret = del(p) ) return ret; - - // then user installed packages - foreach( pl; m_userPackages ) + // and then all packages gathered from the search path + foreach( pl; m_packages ) foreach( v; pl ) if( auto ret = del(v) ) return ret; - - // finally system-wide installed packages - foreach( pl; m_systemPackages ) - foreach( v; pl ) - if( auto ret = del(v) ) - return ret; - return 0; } @@ -130,57 +148,23 @@ { int iterator(int delegate(ref Package) del) { - // first search project local packages - foreach( p; m_localTemporaryPackages ) - if( p.name == name ) - if( auto ret = del(p) ) return ret; - if( auto pp = name in m_projectPackages ) - if( auto ret = del(*pp) ) return ret; - - // then local packages - foreach( p; m_localUserPackages ) - if( p.name == name ) - if( auto ret = del(p) ) return ret; - - // then local packages - foreach( p; m_localSystemPackages ) - if( p.name == name ) - if( auto ret = del(p) ) return ret; - - // then user installed packages - if( auto pp = name in m_userPackages ) - foreach( v; *pp ) - if( auto ret = del(v) ) - return ret; - - // finally system-wide installed packages - if( auto pp = name in m_systemPackages ) - foreach( v; *pp ) - if( auto ret = del(v) ) - return ret; - + foreach (p; getPackageIterator()) + if (p.name == name) + if (auto ret = del(p)) return ret; return 0; } return &iterator; } - Package install(Path zip_file_path, Json package_info, InstallLocation location) + Package install(Path zip_file_path, Json package_info, /*InstallLocation location*/Path destination) { auto package_name = package_info.name.get!string(); auto package_version = package_info["version"].get!string(); auto clean_package_version = package_version[package_version.startsWith("~") ? 1 : 0 .. $]; logDebug("Installing package '%s' version '%s' to location '%s' from file '%s'", - package_name, package_version, to!string(location), zip_file_path.toNativeString()); - - Path destination; - final switch( location ){ - case InstallLocation.local: destination = Path(package_name); break; - case InstallLocation.projectLocal: enforce(!m_projectPackagePath.empty, "no project path set."); destination = m_projectPackagePath ~ package_name; break; - case InstallLocation.userWide: destination = m_userPackagePath ~ (package_name ~ "/" ~ clean_package_version); break; - case InstallLocation.systemWide: destination = m_systemPackagePath ~ (package_name ~ "/" ~ clean_package_version); break; - } + package_name, package_version, destination.toNativeString(), zip_file_path.toNativeString()); if( existsFile(destination) ){ throw new Exception(format("%s %s needs to be uninstalled prior installation.", package_name, package_version)); @@ -262,21 +246,16 @@ if( existsFile(destination~PackageJsonFilename) ) logInfo("%s has been installed with version %s", package_name, package_version); - auto pack = new Package(location, destination); + auto pack = new Package(destination); - final switch( location ){ - case InstallLocation.local: break; - case InstallLocation.projectLocal: m_projectPackages[package_name] = pack; break; - case InstallLocation.userWide: m_userPackages[package_name] ~= pack; break; - case InstallLocation.systemWide: m_systemPackages[package_name] ~= pack; break; - } + m_packages[package_name] ~= pack; return pack; } void uninstall(in Package pack) { - logTrace("Uninstall %s, version %s, path '%s'", pack.name, pack.vers, pack.path); + /+logTrace("Uninstall %s, version %s, path '%s'", pack.name, pack.vers, pack.path); enforce(!pack.path.empty, "Cannot uninstall package "~pack.name~" without a path."); // remove package from package list @@ -356,12 +335,12 @@ throw new Exception("Alien files found in '"~pack.path.toNativeString()~"', needs to be deleted manually."); rmdir(pack.path.toNativeString()); - logInfo("Uninstalled package: '"~pack.name~"'"); + logInfo("Uninstalled package: '"~pack.name~"'");+/ } Package addLocalPackage(in Path path, in Version ver, LocalPackageType type) { - Package[]* packs = getLocalPackageList(type); + Package[]* packs = &m_repositories[type].localPackages; auto info = jsonFromFile(path ~ PackageJsonFilename, false); string name; if( "name" !in info ) info["name"] = path.head.toString(); @@ -375,7 +354,7 @@ } } - auto pack = new Package(info, InstallLocation.local, path); + auto pack = new Package(info, path); *packs ~= pack; @@ -386,7 +365,7 @@ void removeLocalPackage(in Path path, LocalPackageType type) { - Package[]* packs = getLocalPackageList(type); + Package[]* packs = &m_repositories[type].localPackages; size_t[] to_remove; foreach( i, entry; *packs ) if( entry.path == path ) @@ -399,60 +378,38 @@ writeLocalPackageList(type); } + Package addTemporaryPackage(Path path, Version ver) + { + auto info = jsonFromFile(path ~ PackageJsonFilename, false); + string name; + if( "name" !in info ) info["name"] = path.head.toString(); + info["version"] = ver.toString(); + + auto pack = new Package(info, path); + m_temporaryPackages ~= pack; + return pack; + } + + void addSearchPath(Path path, LocalPackageType type) + { + m_repositories[type].searchPath ~= path; + writeLocalPackageList(type); + } + + void removeSearchPath(Path path, LocalPackageType type) + { + m_repositories[type].searchPath = m_repositories[type].searchPath.filter!(p => p != path)().array(); + writeLocalPackageList(type); + } + void refresh() { - // rescan the system and user package folder - void scanPackageFolder(Path path, ref Package[][string] packs, InstallLocation location) - { - packs = null; - if( path.existsDirectory() ){ - logDebug("iterating dir %s", path.toNativeString()); - try foreach( pdir; iterateDirectory(path) ){ - logDebug("iterating dir %s entry %s", path.toNativeString(), pdir.name); - if( !pdir.isDirectory ) continue; - Package[] vers; - auto pack_path = path ~ pdir.name; - foreach( vdir; iterateDirectory(pack_path) ){ - if( !vdir.isDirectory ) continue; - auto ver_path = pack_path ~ vdir.name; - if( !existsFile(ver_path ~ PackageJsonFilename) ) continue; - try { - auto p = new Package(location, ver_path); - vers ~= p; - } catch( Exception e ){ - logError("Failed to load package in %s: %s", ver_path, e.msg); - } - } - packs[pdir.name] = vers; - } - catch(Exception e) logDebug("Failed to enumerate %s packages: %s", location, e.toString()); - } - } - scanPackageFolder(m_systemPackagePath, m_systemPackages, InstallLocation.systemWide); - scanPackageFolder(m_userPackagePath, m_userPackages, InstallLocation.userWide); - - - // rescan the project package folder - m_projectPackages = null; - if( !m_projectPackagePath.empty && m_projectPackagePath.existsDirectory() ){ - logDebug("iterating dir %s", m_projectPackagePath.toNativeString()); - try foreach( pdir; m_projectPackagePath.iterateDirectory() ){ - if( !pdir.isDirectory ) continue; - auto pack_path = m_projectPackagePath ~ pdir.name; - if( !existsFile(pack_path ~ PackageJsonFilename) ) continue; - - try { - auto p = new Package(InstallLocation.projectLocal, pack_path); - m_projectPackages[pdir.name] = p; - } catch( Exception e ){ - logError("Failed to load package in %s: %s", pack_path, e.msg); - } - } - catch(Exception e) logDebug("Failed to enumerate project packages: %s", e.toString()); - } - // load locally defined packages - void scanLocalPackages(Path list_path, ref Package[] packs){ + void scanLocalPackages(LocalPackageType type) + { + Path list_path = m_repositories[type].packagePath; + Package[] packs; + Path[] paths; try { logDebug("Looking for local package map at %s", list_path.toNativeString()); if( !existsFile(list_path ~ LocalPackagesFilename) ) return; @@ -462,16 +419,20 @@ foreach( pentry; packlist ){ try { auto name = pentry.name.get!string(); - auto ver = pentry["version"].get!string(); auto path = Path(pentry.path.get!string()); - auto info = Json.EmptyObject; - if( existsFile(path ~ PackageJsonFilename) ) info = jsonFromFile(path ~ PackageJsonFilename); - if( "name" in info && info.name.get!string() != name ) - logWarn("Local package at %s has different name than %s (%s)", path.toNativeString(), name, info.name.get!string()); - info.name = name; - info["version"] = ver; - auto pp = new Package(info, InstallLocation.local, path); - packs ~= pp; + if (name == "*") { + paths ~= path; + } else { + auto ver = pentry["version"].get!string(); + auto info = Json.EmptyObject; + if( existsFile(path ~ PackageJsonFilename) ) info = jsonFromFile(path ~ PackageJsonFilename); + if( "name" in info && info.name.get!string() != name ) + logWarn("Local package at %s has different name than %s (%s)", path.toNativeString(), name, info.name.get!string()); + info.name = name; + info["version"] = ver; + auto pp = new Package(info, path); + packs ~= pp; + } } catch( Exception e ){ logWarn("Error adding local package: %s", e.msg); } @@ -479,9 +440,37 @@ } catch( Exception e ){ logDebug("Loading of local package list at %s failed: %s", list_path.toNativeString(), e.msg); } + m_repositories[type].localPackages = packs; + m_repositories[type].searchPath = paths; } - scanLocalPackages(m_systemPackagePath, m_localSystemPackages); - scanLocalPackages(m_userPackagePath, m_localUserPackages); + scanLocalPackages(LocalPackageType.system); + scanLocalPackages(LocalPackageType.user); + + // rescan the system and user package folder + void scanPackageFolder(Path path) + { + if( path.existsDirectory() ){ + logTrace("iterating dir %s", path.toNativeString()); + try foreach( pdir; iterateDirectory(path) ){ + logTrace("iterating dir %s entry %s", path.toNativeString(), pdir.name); + if( !pdir.isDirectory ) continue; + auto pack_path = path ~ pdir.name; + if( !existsFile(pack_path ~ PackageJsonFilename) ) continue; + Package p; + try { + p = new Package(pack_path); + m_packages[p.name] ~= p; + } catch( Exception e ){ + logError("Failed to load package in %s: %s", pack_path, e.msg); + } + } + catch(Exception e) logDebug("Failed to enumerate %s packages: %s", path.toNativeString(), e.toString()); + } + } + + m_packages = null; + foreach (p; this.completeSearchPath) + scanPackageFolder(p); } alias ubyte[] Hash; @@ -514,20 +503,17 @@ return hash[0..$]; } - private Package[]* getLocalPackageList(LocalPackageType type) - { - final switch(type){ - case LocalPackageType.user: return &m_localUserPackages; - case LocalPackageType.system: return &m_localSystemPackages; - case LocalPackageType.temporary: return &m_localTemporaryPackages; - } - } - private void writeLocalPackageList(LocalPackageType type) { - Package[]* packs = getLocalPackageList(type); Json[] newlist; - foreach( p; *packs ){ + foreach (p; m_repositories[type].searchPath) { + auto entry = Json.EmptyObject; + entry.name = "*"; + entry.path = p.toNativeString(); + newlist ~= entry; + } + + foreach (p; m_repositories[type].localPackages) { auto entry = Json.EmptyObject; entry["name"] = p.name; entry["version"] = p.ver.toString(); @@ -535,12 +521,7 @@ newlist ~= entry; } - Path path; - final switch(type){ - case LocalPackageType.user: path = m_userPackagePath; break; - case LocalPackageType.system: path = m_systemPackagePath; break; - case LocalPackageType.temporary: return; - } + Path path = m_repositories[type].packagePath; if( !existsDirectory(path) ) mkdirRecurse(path.toNativeString()); writeJsonFile(path ~ LocalPackagesFilename, Json(newlist)); } diff --git a/source/dub/project.d b/source/dub/project.d index c7c0b82..f500908 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -146,7 +146,7 @@ { scope(failure){ logDebug("Failed to initialize project. Assuming defaults."); - m_main = new Package(serializeToJson(["name": "unknown"]), InstallLocation.local, m_root); + m_main = new Package(serializeToJson(["name": "unknown"]), m_root); } m_dependencies = null; @@ -160,11 +160,11 @@ logWarn("There was no '"~PackageJsonFilename~"' found for the application in '%s'.", m_root.toNativeString()); auto json = Json.EmptyObject; json.name = "unknown"; - m_main = new Package(json, InstallLocation.local, m_root); + m_main = new Package(json, m_root); return; } - m_main = new Package(InstallLocation.local, m_root); + m_main = new Package(m_root); m_main.warnOnSpecialCompilerFlags(); if (m_main.name != m_main.name.toLower()) { logWarn("Package names should always be lower case, please change from '%s' to '%s'!", @@ -183,7 +183,7 @@ Path path = vspec.path; if( !path.absolute ) path = pack.path ~ path; logDebug("Adding local %s %s", path, vspec.version_); - p = m_packageManager.addLocalPackage(path, vspec.version_, LocalPackageType.temporary); + p = m_packageManager.addTemporaryPackage(path, vspec.version_); } else { p = m_packageManager.getBestPackage(name, vspec); } @@ -262,7 +262,8 @@ /// Actions which can be performed to update the application. - Action[] determineActions(PackageSupplier[] packageSuppliers, int option) { + Action[] determineActions(PackageSupplier[] packageSuppliers, int option) + { scope(exit) writeDubJson(); if(!m_main) { @@ -301,51 +302,23 @@ installed[p.name] = p; } - // To see, which could be uninstalled - Package[string] unused = installed.dup; - unused.remove(m_main.name); // Check against installed and add install actions Action[] actions; - Action[] uninstalls; foreach( string pkg, d; graph.needed() ) { auto p = pkg in installed; // TODO: auto update to latest head revision if(!p || (!d.dependency.matches(p.vers) && !d.dependency.matches(Version.MASTER))) { - if(!p) logDebug("Application not complete, required package '"~pkg~"', which was not found."); - else logDebug("Application not complete, required package '"~pkg~"', invalid version. Required '%s', available '%s'.", d.dependency, p.vers); - actions ~= Action.install(pkg, InstallLocation.projectLocal, d.dependency, d.packages); + if(!p) logDebug("Triggering installation of required package '"~pkg~"', which is not installed."); + else logDebug("Triggering installation of required package '"~pkg~"', which doesn't match the required versionh. Required '%s', available '%s'.", d.dependency, p.vers); + actions ~= Action.install(pkg, InstallLocation.userWide, d.dependency, d.packages); } else { logDebug("Required package '"~pkg~"' found with version '"~p.vers~"'"); - if( option & UpdateOptions.Reinstall ) { - if( p.installLocation != InstallLocation.local ){ - Dependency[string] em; - // user and system packages are not uninstalled (could be needed by other projects) - if (p.installLocation == InstallLocation.projectLocal || p.ver.isBranch) - uninstalls ~= Action.uninstall(*p, em); - actions ~= Action.install(pkg, p.installLocation, d.dependency, d.packages); - } else { - logInfo("Skipping local package %s at %s", p.name, p.path.toNativeString()); - } - } - - if( (pkg in unused) !is null ) - unused.remove(pkg); + if( option & UpdateOptions.Upgrade ) + actions ~= Action.install(pkg, InstallLocation.userWide, d.dependency, d.packages); } } - // Add uninstall actions - foreach( pname, pkg; unused ){ - if( pkg.installLocation != InstallLocation.projectLocal ) - continue; - logDebug("Superfluous package found: '"~pname~"', version '"~pkg.vers~"'"); - Dependency[string] em; - uninstalls ~= Action.uninstall(pkg, em); - } - - // Ugly "uninstall" comes first - actions = uninstalls ~ actions; - return actions; } @@ -433,7 +406,8 @@ } } - private bool gatherMissingDependencies(PackageSupplier[] packageSuppliers, DependencyGraph graph) { + private bool gatherMissingDependencies(PackageSupplier[] packageSuppliers, DependencyGraph graph) + { RequestedDependency[string] missing = graph.missing(); RequestedDependency[string] oldMissing; while( missing.length > 0 ) { @@ -477,7 +451,7 @@ if( !p && reqDep.dependency.optional ) continue; // Try an already installed package first - if( p && p.installLocation != InstallLocation.local && needsUpToDateCheck(pkg) ){ + if( p && needsUpToDateCheck(pkg) ){ logInfo("Triggering update of package %s", pkg); p = null; } @@ -611,7 +585,7 @@ { None = 0, JustAnnotate = 1<<0, - Reinstall = 1<<1 + Upgrade = 1<<1 };