-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nix profile
: Allow referring to elements by human-readable name
#8678
Changes from all commits
257b768
9c0a09f
9d9d9ff
d77a39a
14508ad
942d635
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
synopsis: "`nix profile` now allows referring to elements by human-readable name" | ||
prs: 8678 | ||
--- | ||
|
||
[`nix profile`](@docroot@/command-ref/new-cli/nix3-profile.md) now uses names to refer to installed packages when running [`list`](@docroot@/command-ref/new-cli/nix3-profile-list.md), [`remove`](@docroot@/command-ref/new-cli/nix3-profile-remove.md) or [`upgrade`](@docroot@/command-ref/new-cli/nix3-profile-upgrade.md) as opposed to indices. Indices are deprecated and will be removed in a future version. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include "url-name.hh" | ||
#include <regex> | ||
#include <iostream> | ||
|
||
namespace nix { | ||
|
||
static const std::string attributeNamePattern("[a-z0-9_-]+"); | ||
static const std::regex lastAttributeRegex("(?:" + attributeNamePattern + "\\.)*(?!default)(" + attributeNamePattern +")(\\^.*)?"); | ||
static const std::string pathSegmentPattern("[a-zA-Z0-9_-]+"); | ||
static const std::regex lastPathSegmentRegex(".*/(" + pathSegmentPattern +")"); | ||
static const std::regex secondPathSegmentRegex("(?:" + pathSegmentPattern + ")/(" + pathSegmentPattern +")(?:/.*)?"); | ||
static const std::regex gitProviderRegex("github|gitlab|sourcehut"); | ||
static const std::regex gitSchemeRegex("git($|\\+.*)"); | ||
static const std::regex defaultOutputRegex(".*\\.default($|\\^.*)"); | ||
|
||
std::optional<std::string> getNameFromURL(const ParsedURL & url) | ||
{ | ||
std::smatch match; | ||
|
||
/* If there is a dir= argument, use its value */ | ||
if (url.query.count("dir") > 0) | ||
return url.query.at("dir"); | ||
|
||
/* If the fragment isn't a "default" and contains two attribute elements, use the last one */ | ||
if (std::regex_match(url.fragment, match, lastAttributeRegex)) | ||
return match.str(1); | ||
|
||
/* If this is a github/gitlab/sourcehut flake, use the repo name */ | ||
if (std::regex_match(url.scheme, gitProviderRegex) && std::regex_match(url.path, match, secondPathSegmentRegex)) | ||
return match.str(1); | ||
|
||
/* If it is a regular git flake, use the directory name */ | ||
if (std::regex_match(url.scheme, gitSchemeRegex) && std::regex_match(url.path, match, lastPathSegmentRegex)) | ||
return match.str(1); | ||
|
||
/* If everything failed but there is a non-default fragment, use it in full */ | ||
if (!url.fragment.empty() && !std::regex_match(url.fragment, defaultOutputRegex)) | ||
return url.fragment; | ||
|
||
/* If there is no fragment, take the last element of the path */ | ||
if (std::regex_match(url.path, match, lastPathSegmentRegex)) | ||
return match.str(1); | ||
|
||
/* If even that didn't work, the URL does not contain enough info to determine a useful name */ | ||
return {}; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#include "url.hh" | ||
#include "url-parts.hh" | ||
#include "util.hh" | ||
#include "split.hh" | ||
|
||
namespace nix { | ||
|
||
/** | ||
* Try to extract a reasonably unique and meaningful, human-readable | ||
* name of a flake output from a parsed URL. | ||
* When nullopt is returned, the callsite should use information available | ||
* to it outside of the URL to determine a useful name. | ||
* This is a heuristic approach intended for user interfaces. | ||
* @return nullopt if the extracted name is not useful to identify a | ||
* flake output, for example because it is empty or "default". | ||
* Otherwise returns the extracted name. | ||
*/ | ||
std::optional<std::string> getNameFromURL(const ParsedURL & url); | ||
|
||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,12 +6,14 @@ R""( | |
|
||
```console | ||
# nix profile list | ||
Name: gdb | ||
iFreilicht marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Index: 0 | ||
Flake attribute: legacyPackages.x86_64-linux.gdb | ||
Original flake URL: flake:nixpkgs | ||
Locked flake URL: github:NixOS/nixpkgs/7b38b03d76ab71bdc8dc325e3f6338d984cc35ca | ||
Store paths: /nix/store/indzcw5wvlhx6vwk7k4iq29q15chvr3d-gdb-11.1 | ||
|
||
Name: blender-bin | ||
Index: 1 | ||
Flake attribute: packages.x86_64-linux.default | ||
Original flake URL: flake:blender-bin | ||
|
@@ -26,18 +28,22 @@ R""( | |
# nix build github:edolstra/nix-warez/91f2ffee657bf834e4475865ae336e2379282d34?dir=blender#packages.x86_64-linux.default | ||
``` | ||
|
||
will build the package with index 1 shown above. | ||
will build the package `blender-bin` shown above. | ||
|
||
# Description | ||
|
||
This command shows what packages are currently installed in a | ||
profile. For each installed package, it shows the following | ||
information: | ||
|
||
* `Index`: An integer that can be used to unambiguously identify the | ||
* `Name`: A unique name used to unambiguously identify the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do we guarantee that names are unambiguous? A name like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unambiguous in the context of the current profile. They're generated when listing the profile contents. If a name like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isnt that susceptible to the same issues this outlines: #7961? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it makes sense to use some portion of the store hash as an alternative suffix? e.g. hello-3bjqzx, hello-6r9h8 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That could also be an option. Personally I'd like to avoid duplicate names eventually altogether by erroring upon install. I think these kinds of improvements/iterations should be a decision for a follow-up PR. The current implementation of this PR is simple and more or less in line with the current implementation on master (numbering the packages). I see this PR as the most minimal step we can make towards using names for profile entries. |
||
package in invocations of `nix profile remove` and `nix profile | ||
upgrade`. | ||
|
||
* `Index`: An integer that can be used to unambiguously identify the | ||
package in invocations of `nix profile remove` and `nix profile upgrade`. | ||
(*Deprecated, will be removed in a future version in favor of `Name`.*) | ||
|
||
* `Flake attribute`: The flake output attribute path that provides the | ||
package (e.g. `packages.x86_64-linux.hello`). | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iFreilicht I would appreciate if you could move this elsewhere.
libutil
should be just utilities and not define Nix-specific concepts like store paths or flake things. (In the "Domain-Driven Design" parlance, this is a "application layer" or "domain layer" concept, but libutil is supposed to be the "infrastructure layer".)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Could you maybe give me a hint where "elsewhere" could be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. I would put in
src/libexpr/flake/
for now. There are other flakes things in there that don't strictly relate to evaluation already.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, see #9655