diff --git a/doc/manual/change-authors.yml b/doc/manual/change-authors.yml index 5894ce821..28a20b25f 100644 --- a/doc/manual/change-authors.yml +++ b/doc/manual/change-authors.yml @@ -44,6 +44,11 @@ cole-h: display_name: Cole Helbling github: cole-h +delan: + display_name: delan + forgejo: delan + github: delan + edolstra: display_name: Eelco Dolstra github: edolstra diff --git a/doc/manual/rl-next/registry-add-shorthand-only.md b/doc/manual/rl-next/registry-add-shorthand-only.md new file mode 100644 index 000000000..72f972b0a --- /dev/null +++ b/doc/manual/rl-next/registry-add-shorthand-only.md @@ -0,0 +1,10 @@ +--- +synopsis: "`nix registry add` now requires a shorthand flakeref on the 'from' side" +cls: 1494 +credits: delan +category: Improvements +--- + +The 'from' argument must now be a shorthand flakeref like `nixpkgs` or `nixpkgs/nixos-20.03`, making it harder to accidentally swap the 'from' and 'to' arguments. + +Registry entries that map from other flake URLs can still be specified in registry.json, the `nix.registry` option in NixOS, or the `--override-flake` option in the CLI, but they are not guaranteed to work correctly. diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc index 1c90bfc43..a95df04ba 100644 --- a/src/libexpr/flake/flakeref.cc +++ b/src/libexpr/flake/flakeref.cc @@ -85,8 +85,8 @@ std::pair parseFlakeRefWithFragment( + "(?:#(" + queryRegex + "))?", std::regex::ECMAScript); - static std::regex flakeRegex( - "((" + flakeIdRegexS + ")(?:/(?:" + refAndOrRevRegex + "))?)" + static std::regex flakeShorthandRegex( + flakeShorthandRegexS + "(?:#(" + queryRegex + "))?", std::regex::ECMAScript); @@ -95,7 +95,7 @@ std::pair parseFlakeRefWithFragment( /* Check if 'url' is a flake ID. This is an abbreviated syntax for 'flake:?ref=&rev='. */ - if (std::regex_match(url, match, flakeRegex)) { + if (std::regex_match(url, match, flakeShorthandRegex)) { auto parsedURL = ParsedURL{ .url = url, .base = "flake:" + match.str(1), diff --git a/src/libutil/url-parts.hh b/src/libutil/url-parts.hh index 6efcc7e50..1f570567c 100644 --- a/src/libutil/url-parts.hh +++ b/src/libutil/url-parts.hh @@ -46,4 +46,7 @@ const static std::string refAndOrRevRegex = "(?:(" + revRegexS + ")|(?:(" + refR const static std::string flakeIdRegexS = "[a-zA-Z][a-zA-Z0-9_-]*"; extern std::regex flakeIdRegex; +const static std::string flakeShorthandRegexS = "((" + flakeIdRegexS + ")(?:/(?:" + refAndOrRevRegex + "))?)"; +extern std::regex flakeShorthandRegex; + } diff --git a/src/libutil/url.cc b/src/libutil/url.cc index 46688cef5..87146ca56 100644 --- a/src/libutil/url.cc +++ b/src/libutil/url.cc @@ -9,6 +9,7 @@ std::regex refRegex(refRegexS, std::regex::ECMAScript); std::regex badGitRefRegex(badGitRefRegexS, std::regex::ECMAScript); std::regex revRegex(revRegexS, std::regex::ECMAScript); std::regex flakeIdRegex(flakeIdRegexS, std::regex::ECMAScript); +std::regex flakeShorthandRegex(flakeShorthandRegexS, std::regex::ECMAScript); ParsedURL parseURL(const std::string & url) { diff --git a/src/nix/registry-add.md b/src/nix/registry-add.md index a947fa0b3..90b54a596 100644 --- a/src/nix/registry-add.md +++ b/src/nix/registry-add.md @@ -31,8 +31,9 @@ R""( # Description This command adds an entry to the user registry that maps flake -reference *from-url* to flake reference *to-url*. If an entry for -*from-url* already exists, it is overwritten. +reference *from-url* to flake reference *to-url*, where *from-url* +must be a shorthand like 'nixpkgs' or 'nixpkgs/nixos-20.03'. If an +entry for *from-url* already exists, it is overwritten. Entries can be removed using [`nix registry remove`](./nix3-registry-remove.md). diff --git a/src/nix/registry.cc b/src/nix/registry.cc index f509ccae8..9619b85d4 100644 --- a/src/nix/registry.cc +++ b/src/nix/registry.cc @@ -5,6 +5,7 @@ #include "flake/flake.hh" #include "store-api.hh" #include "fetchers.hh" +#include "url-parts.hh" #include "registry.hh" using namespace nix; @@ -109,7 +110,14 @@ struct CmdRegistryAdd : MixEvalArgs, Command, RegistryCommand void run() override { + std::smatch match; + if (!std::regex_match(fromUrl, match, flakeShorthandRegex)) { + throw UsageError("'from-url' argument must be a shorthand like 'nixpkgs' or 'nixpkgs/nixos-20.03'"); + } auto fromRef = parseFlakeRef(fromUrl); + if (fromRef.input.direct) { + throw UsageError("'from-url' argument must be an indirect flakeref like 'nixpkgs' or 'flake:nixpkgs'"); + } auto toRef = parseFlakeRef(toUrl); auto registry = getRegistry(); fetchers::Attrs extraAttrs; diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh index 68a2fd2ce..97dc6d818 100644 --- a/tests/functional/flakes/flakes.sh +++ b/tests/functional/flakes/flakes.sh @@ -366,6 +366,17 @@ nix registry pin flake1 flake3 nix registry remove flake1 [[ $(nix registry list | wc -l) == 5 ]] +# 'nix registry add' should accept flake shorthands (with or without branch or rev) +# in the from argument, but reject fully-qualified from-urls (direct or indirect). +nix registry add nixpkgz github:NixOS/nixpkgz +nix registry remove nixpkgz +nix registry add nixpkgz/branch github:NixOS/nixpkgz +nix registry remove nixpkgz/branch +nix registry add nixpkgz/branch/1db42b7fe3878f3f5f7a4f2dc210772fd080e205 github:NixOS/nixpkgz +nix registry remove nixpkgz/branch/1db42b7fe3878f3f5f7a4f2dc210772fd080e205 +! nix registry add flake:nixpkgz github:NixOS/nixpkgz +! nix registry add github:NixOS/nixpkgz github:NixOS/nixpkgz + # Test 'nix registry list' with a disabled global registry. nix registry add user-flake1 git+file://$flake1Dir nix registry add user-flake2 git+file://$flake2Dir