diff --git a/src/nix/profile.cc b/src/nix/profile.cc index fc669d5ed..d39a24d36 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -101,6 +101,15 @@ struct ProfileElement } }; +std::string getNameFromElement(const ProfileElement & element) +{ + std::optional result = std::nullopt; + if (element.source) { + result = getNameFromURL(parseURL(element.source->to_string())); + } + return result.value_or(element.identifier()); +} + struct ProfileManifest { using ProfileElementName = std::string; @@ -189,12 +198,8 @@ struct ProfileManifest void addElement(ProfileElement element) { - auto name = - element.source - ? getNameFromURL(parseURL(element.source->to_string())) - : std::nullopt; - auto name2 = name ? *name : element.identifier(); - addElement(name2, std::move(element)); + auto name = getNameFromElement(element); + addElement(name, std::move(element)); } nlohmann::json toJSON(Store & store) const @@ -390,7 +395,26 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile element.updateStorePaths(getEvalStore(), store, res); - manifest.addElement(std::move(element)); + auto elementName = getNameFromElement(element); + + // Check if the element already exists. + auto existingPair = manifest.elements.find(elementName); + if (existingPair != manifest.elements.end()) { + auto existingElement = existingPair->second; + auto existingSource = existingElement.source; + auto elementSource = element.source; + if (existingSource + && elementSource + && existingElement.priority == element.priority + && existingSource->originalRef == elementSource->originalRef + && existingSource->attrPath == elementSource->attrPath + ) { + warn("'%s' is already installed", elementName); + continue; + } + } + + manifest.addElement(elementName, std::move(element)); } try { diff --git a/tests/functional/nix-profile.sh b/tests/functional/nix-profile.sh index 88b713d53..ee93251e9 100644 --- a/tests/functional/nix-profile.sh +++ b/tests/functional/nix-profile.sh @@ -64,6 +64,9 @@ nix profile install $flake1Dir [[ $($TEST_HOME/.local/state/nix/profile/bin/hello) = "Hello World" ]] unset NIX_CONFIG +# Test conflicting package install. +nix profile install $flake1Dir 2>&1 | grep "warning: 'flake1' is already installed" + # Test upgrading a package. printf NixOS > $flake1Dir/who printf 2.0 > $flake1Dir/version