aboutsummaryrefslogtreecommitdiff
path: root/src/nix/profile.cc
diff options
context:
space:
mode:
authorThéophane Hufschmitt <theophane.hufschmitt@tweag.io>2023-05-16 11:37:45 +0200
committerThéophane Hufschmitt <theophane.hufschmitt@tweag.io>2023-05-16 11:41:58 +0200
commite997512523d8c5d22005b6cd5e22271284273ee6 (patch)
tree9ba54525ef0f799a1259deb2c1c75ea2ea7234c9 /src/nix/profile.cc
parent3d144e778e4193c948fa6e0a23f9f3de194bc62f (diff)
Fix the printing of the installables on `nix profile install` conflict
- If the element comes from a flake, print the full flakeref (with the fragment part) and not just the reference to the flake itself - If the element doesn't come from a flake, print its store path(s) This is a bit too verbose, but has the advantages of being correct (and not crashing), so it's strictly better than the previous situation Fix https://github.com/NixOS/nix/issues/8284
Diffstat (limited to 'src/nix/profile.cc')
-rw-r--r--src/nix/profile.cc33
1 files changed, 26 insertions, 7 deletions
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index ce3b6fbbc..7cea616d2 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -31,6 +31,11 @@ struct ProfileElementSource
std::tuple(originalRef.to_string(), attrPath, outputs) <
std::tuple(other.originalRef.to_string(), other.attrPath, other.outputs);
}
+
+ std::string to_string() const
+ {
+ return fmt("%s#%s%s", originalRef, attrPath, outputs.to_string());
+ }
};
const int defaultPriority = 5;
@@ -45,13 +50,27 @@ struct ProfileElement
std::string identifier() const
{
if (source)
- return fmt("%s#%s%s", source->originalRef, source->attrPath, source->outputs.to_string());
+ return source->to_string();
StringSet names;
for (auto & path : storePaths)
names.insert(DrvName(path.name()).name);
return concatStringsSep(", ", names);
}
+ /**
+ * Return a string representing an installable corresponding to the current
+ * element, either a flakeref or a plain store path
+ */
+ std::set<std::string> toInstallables(Store & store)
+ {
+ if (source)
+ return {source->to_string()};
+ StringSet rawPaths;
+ for (auto & path : storePaths)
+ rawPaths.insert(store.printStorePath(path));
+ return rawPaths;
+ }
+
std::string versions() const
{
StringSet versions;
@@ -363,10 +382,10 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
auto profileElement = *it;
for (auto & storePath : profileElement.storePaths) {
if (conflictError.fileA.starts_with(store->printStorePath(storePath))) {
- return std::pair(conflictError.fileA, profileElement.source->originalRef);
+ return std::pair(conflictError.fileA, profileElement.toInstallables(*store));
}
if (conflictError.fileB.starts_with(store->printStorePath(storePath))) {
- return std::pair(conflictError.fileB, profileElement.source->originalRef);
+ return std::pair(conflictError.fileB, profileElement.toInstallables(*store));
}
}
}
@@ -375,9 +394,9 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
// There are 2 conflicting files. We need to find out which one is from the already installed package and
// which one is the package that is the new package that is being installed.
// The first matching package is the one that was already installed (original).
- auto [originalConflictingFilePath, originalConflictingRef] = findRefByFilePath(manifest.elements.begin(), manifest.elements.end());
+ auto [originalConflictingFilePath, originalConflictingRefs] = findRefByFilePath(manifest.elements.begin(), manifest.elements.end());
// The last matching package is the one that was going to be installed (new).
- auto [newConflictingFilePath, newConflictingRef] = findRefByFilePath(manifest.elements.rbegin(), manifest.elements.rend());
+ auto [newConflictingFilePath, newConflictingRefs] = findRefByFilePath(manifest.elements.rbegin(), manifest.elements.rend());
throw Error(
"An existing package already provides the following file:\n"
@@ -403,8 +422,8 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
" nix profile install %4% --priority %7%\n",
originalConflictingFilePath,
newConflictingFilePath,
- originalConflictingRef.to_string(),
- newConflictingRef.to_string(),
+ concatStringsSep(" ", originalConflictingRefs),
+ concatStringsSep(" ", newConflictingRefs),
conflictError.priority,
conflictError.priority - 1,
conflictError.priority + 1