diff --git a/source/app.d b/source/app.d index 77d8c7b..f7d77ee 100644 --- a/source/app.d +++ b/source/app.d @@ -127,7 +127,7 @@ return 0; case "upgrade": dub.loadPackageFromCwd(); - logInfo("Upgrading project in '%s'", dub.projectPath); + logInfo("Upgrading project in %s", dub.projectPath.toNativeString); logDebug("dub initialized"); dub.update(UpdateOptions.Reinstall | (annotate ? UpdateOptions.JustAnnotate : UpdateOptions.None)); return 0; diff --git a/source/dub/dub.d b/source/dub/dub.d index fb8c7be..52e71ff 100644 --- a/source/dub/dub.d +++ b/source/dub/dub.d @@ -117,8 +117,8 @@ logInfo("The following changes could be performed:"); bool conflictedOrFailed = false; foreach(Action a; actions) { - logInfo(capitalize( to!string( a.action ) ) ~ ": " ~ a.packageId ~ ", version %s", a.vers); - if( a.action == Action.ActionId.Conflict || a.action == Action.ActionId.Failure ) { + logInfo(capitalize(to!string(a.type)) ~ ": " ~ a.packageId ~ ", version %s", a.vers); + if( a.type == Action.Type.conflict || a.type == Action.Type.failure ) { logInfo("Issued by: "); conflictedOrFailed = true; foreach(string pkg, d; a.issuer) @@ -132,18 +132,18 @@ // Uninstall first // ?? - // foreach(Action a ; filter!((Action a) => a.action == Action.ActionId.Uninstall)(actions)) + // foreach(Action a ; filter!((Action a) => a.type == Action.Type.Uninstall)(actions)) // uninstall(a.packageId); - // foreach(Action a; filter!((Action a) => a.action == Action.ActionId.InstallUpdate)(actions)) + // foreach(Action a; filter!((Action a) => a.type == Action.Type.InstallUpdate)(actions)) // install(a.packageId, a.vers); foreach(Action a; actions) - if(a.action == Action.ActionId.Uninstall){ + if(a.type == Action.Type.uninstall){ assert(a.pack !is null, "No package specified for uninstall."); uninstall(a.pack); } foreach(Action a; actions) - if(a.action == Action.ActionId.InstallUpdate) - install(a.packageId, a.vers); + if(a.type == Action.Type.install) + install(a.packageId, a.vers, a.location); m_app.reinit(); Action[] newActions = m_app.determineActions(m_packageSupplier, 0); diff --git a/source/dub/packagemanager.d b/source/dub/packagemanager.d index b73a1eb..cba794f 100644 --- a/source/dub/packagemanager.d +++ b/source/dub/packagemanager.d @@ -157,6 +157,16 @@ Package install(Path zip_file_path, Json package_info, InstallLocation location) { + foreach(ep; getPackageIterator()){ + if( ep.installLocation == location && ep.name == package_info.name.get!string + && ep.vers == package_info["version"].get!string() ) + { + logInfo("Skipping installation of already existing %s package %s %s.", + location, ep.name, ep.vers); + return ep; + } + } + auto package_name = package_info.name.get!string(); auto package_version = package_info["version"].get!string(); @@ -168,8 +178,9 @@ case InstallLocation.SystemWide: destination = m_systemPackagePath ~ (package_name ~ "/" ~ package_version); break; } - if( existsFile(destination) ) + if( existsFile(destination) ){ throw new Exception(format("%s %s needs to be uninstalled prior installation.", package_name, package_version)); + } // open zip file ZipArchive archive; diff --git a/source/dub/project.d b/source/dub/project.d index d980e21..52d61df 100644 --- a/source/dub/project.d +++ b/source/dub/project.d @@ -202,7 +202,7 @@ logError("The dependency graph could not be filled."); Action[] actions; foreach( string pkg, rdp; graph.missing()) - actions ~= Action(Action.ActionId.Failure, pkg, rdp.dependency, rdp.packages); + actions ~= Action.failure(pkg, rdp.dependency, rdp.packages); return actions; } @@ -211,7 +211,7 @@ logDebug("Conflicts found"); Action[] actions; foreach( string pkg, dbp; conflicts) - actions ~= Action(Action.ActionId.Conflict, pkg, dbp.dependency, dbp.packages); + actions ~= Action.conflict(pkg, dbp.dependency, dbp.packages); return actions; } @@ -241,15 +241,16 @@ 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(Action.ActionId.InstallUpdate, pkg, d.dependency, d.packages); + actions ~= Action.install(pkg, InstallLocation.ProjectLocal, 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 ) - uninstalls ~= Action(Action.ActionId.Uninstall, *p, em); - actions ~= Action(Action.ActionId.InstallUpdate, pkg, d.dependency, d.packages); + 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()); } @@ -261,10 +262,12 @@ } // Add uninstall actions - foreach( string pkg, p; unused ) { - logDebug("Superfluous package found: '"~pkg~"', version '"~p.vers~"'"); + foreach( pname, pkg; unused ){ + if( pkg.installLocation != InstallLocation.ProjectLocal ) + continue; + logDebug("Superfluous package found: '"~pname~"', version '"~pkg.vers~"'"); Dependency[string] em; - uninstalls ~= Action( Action.ActionId.Uninstall, pkg, new Dependency("==", p.vers), em); + uninstalls ~= Action.uninstall(pkg, em); } // Ugly "uninstall" comes first @@ -421,40 +424,62 @@ /// Actions to be performed by the dub struct Action { - enum ActionId { - InstallUpdate, - Uninstall, - Conflict, - Failure + enum Type { + install, + uninstall, + conflict, + failure } immutable { - ActionId action; + Type type; string packageId; + InstallLocation location; Dependency vers; } const Package pack; const Dependency[string] issuer; - this(ActionId id, string pkg, in Dependency d, Dependency[string] issue) + static Action install(string pkg, InstallLocation location, in Dependency dep, Dependency[string] context) { - action = id; - packageId = pkg; - vers = new immutable(Dependency)(d); - issuer = issue; + return Action(Type.install, pkg, location, dep, context); } - this(ActionId id, Package pkg, Dependency[string] issue) + static Action uninstall(Package pkg, Dependency[string] context) + { + return Action(Type.uninstall, pkg, context); + } + + static Action conflict(string pkg, in Dependency dep, Dependency[string] context) + { + return Action(Type.conflict, pkg, InstallLocation.ProjectLocal, dep, context); + } + + static Action failure(string pkg, in Dependency dep, Dependency[string] context) + { + return Action(Type.failure, pkg, InstallLocation.ProjectLocal, dep, context); + } + + private this(Type id, string pkg, InstallLocation location, in Dependency d, Dependency[string] issue) + { + this.type = id; + this.packageId = pkg; + this.location = location; + this.vers = new immutable(Dependency)(d); + this.issuer = issue; + } + + private this(Type id, Package pkg, Dependency[string] issue) { pack = pkg; - action = id; + type = id; packageId = pkg.name; vers = new immutable(Dependency)("==", pkg.vers); issuer = issue; } string toString() const { - return to!string(action) ~ ": " ~ packageId ~ ", " ~ to!string(vers); + return to!string(type) ~ ": " ~ packageId ~ ", " ~ to!string(vers); } }