-
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This might be temporary, it might not. I still prefer the functionality of nix-super but my repo never explicitly relied on it other than default flake anyway. If the eval time improvements are good, I will switch.
- Loading branch information
Showing
2 changed files
with
307 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
289 changes: 289 additions & 0 deletions
289
modules/core/common/system/nix/overlays/patches/0001-nix-default-flake.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,289 @@ | ||
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc | ||
index ab0e4fd1c..e56c59712 100644 | ||
--- a/src/libcmd/installables.cc | ||
+++ b/src/libcmd/installables.cc | ||
@@ -37,6 +37,23 @@ void completeFlakeInputPath( | ||
} | ||
} | ||
|
||
+std::string InstallablesSettings::getDefaultFlake(std::string_view url) | ||
+{ | ||
+ std::string res = defaultFlake; | ||
+ if (res == "") { | ||
+ throw UsageError("don't know how to handle installable '%s' without flake URL, because the option 'default-flake' is not set", url); | ||
+ } | ||
+ return res; | ||
+} | ||
+ | ||
+InstallablesSettings installablesSettings; | ||
+ | ||
+static GlobalConfig::Register rInstallablesSettings(&installablesSettings); | ||
+ | ||
+const static std::regex attrPathRegex( | ||
+ R"((?:[a-zA-Z0-9_"-][a-zA-Z0-9_".-]*(?:\^((\*)|([a-z]+(,[a-z]+)*)))?))", | ||
+ std::regex::ECMAScript); | ||
+ | ||
MixFlakeOptions::MixFlakeOptions() | ||
{ | ||
auto category = "Common flake-related options"; | ||
@@ -276,20 +293,34 @@ void completeFlakeRefWithFragment( | ||
/* Look for flake output attributes that match the | ||
prefix. */ | ||
try { | ||
+ bool isAttrPath = std::regex_match(prefix.begin(), prefix.end(), attrPathRegex); | ||
auto hash = prefix.find('#'); | ||
+ | ||
if (hash == std::string::npos) { | ||
- completeFlakeRef(completions, evalState->store, prefix); | ||
- } else { | ||
+ } | ||
+ | ||
+ if (isAttrPath || hash != std::string::npos) { | ||
completions.setType(AddCompletions::Type::Attrs); | ||
|
||
- auto fragment = prefix.substr(hash + 1); | ||
+ auto fragment = | ||
+ isAttrPath | ||
+ ? prefix | ||
+ : prefix.substr(hash + 1); | ||
+ | ||
std::string prefixRoot = ""; | ||
if (fragment.starts_with(".")){ | ||
fragment = fragment.substr(1); | ||
prefixRoot = "."; | ||
} | ||
- auto flakeRefS = std::string(prefix.substr(0, hash)); | ||
- auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath(".")); | ||
+ auto flakeRefS = | ||
+ isAttrPath | ||
+ ? std::string(installablesSettings.getDefaultFlake(prefix)) | ||
+ : expandTilde(std::string(prefix.substr(0, hash))); | ||
+ | ||
+ // FIXME: do tilde expansion. | ||
+ auto flakeRef = parseFlakeRef( | ||
+ flakeRefS, | ||
+ isAttrPath ? std::optional<std::string>{} : absPath(".")); | ||
|
||
auto evalCache = openEvalCache(*evalState, | ||
std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags))); | ||
@@ -299,6 +330,7 @@ void completeFlakeRefWithFragment( | ||
if (prefixRoot == "."){ | ||
attrPathPrefixes.clear(); | ||
} | ||
+ | ||
/* Complete 'fragment' relative to all the | ||
attrpath prefixes as well as the root of the | ||
flake. */ | ||
@@ -323,7 +355,13 @@ void completeFlakeRefWithFragment( | ||
auto attrPath2 = (*attr)->getAttrPath(attr2); | ||
/* Strip the attrpath prefix. */ | ||
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); | ||
- completions.add(flakeRefS + "#" + prefixRoot + concatStringsSep(".", evalState->symbols.resolve(attrPath2))); | ||
+ | ||
+ std::string resolvedAttrPath2 = prefixRoot + concatStringsSep(".", evalState->symbols.resolve(attrPath2)); | ||
+ | ||
+ if (isAttrPath) | ||
+ completions.add(resolvedAttrPath2); | ||
+ else | ||
+ completions.add(flakeRefS + "#" + resolvedAttrPath2); | ||
} | ||
} | ||
} | ||
@@ -360,7 +398,7 @@ void completeFlakeRef(AddCompletions & completions, ref<Store> store, std::strin | ||
if (!prefix.starts_with("flake:") && from.starts_with("flake:")) { | ||
std::string from2(from, 6); | ||
if (from2.starts_with(prefix)) | ||
- completions.add(from2); | ||
+ completions.add(from2 + "#"); | ||
} else { | ||
if (from.starts_with(prefix)) | ||
completions.add(from); | ||
@@ -475,7 +513,13 @@ Installables SourceExprCommand::parseInstallables( | ||
} | ||
|
||
try { | ||
- auto [flakeRef, fragment] = parseFlakeRefWithFragment(std::string { prefix }, absPath(".")); | ||
+ bool isAttrPath = std::regex_match(std::string { prefix }, attrPathRegex); | ||
+ | ||
+ auto [flakeRef, fragment] = | ||
+ isAttrPath | ||
+ ? std::pair { parseFlakeRef(installablesSettings.getDefaultFlake(s), {}), std::string { prefix } } | ||
+ : parseFlakeRefWithFragment(std::string { prefix }, absPath(".")); | ||
+ | ||
result.push_back(make_ref<InstallableFlake>( | ||
this, | ||
getEvalState(), | ||
diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh | ||
index 95e8841ca..3e43b859d 100644 | ||
--- a/src/libcmd/installables.hh | ||
+++ b/src/libcmd/installables.hh | ||
@@ -12,6 +12,16 @@ | ||
|
||
namespace nix { | ||
|
||
+struct InstallablesSettings : Config | ||
+{ | ||
+ Setting<std::string> defaultFlake{this, "", "default-flake", | ||
+ "The default flake URL when using the command line interface"}; | ||
+ | ||
+ std::string getDefaultFlake(std::string_view url); | ||
+}; | ||
+ | ||
+extern InstallablesSettings installablesSettings; | ||
+ | ||
struct DrvInfo; | ||
|
||
enum class Realise { | ||
diff --git a/src/nix/search.cc b/src/nix/search.cc | ||
index 97ef1375e..41d6f1495 100644 | ||
--- a/src/nix/search.cc | ||
+++ b/src/nix/search.cc | ||
@@ -23,8 +23,9 @@ std::string wrap(std::string prefix, std::string s) | ||
return concatStrings(prefix, s, ANSI_NORMAL); | ||
} | ||
|
||
-struct CmdSearch : InstallableValueCommand, MixJSON | ||
+struct CmdSearch : SourceExprCommand, MixJSON | ||
{ | ||
+ std::string _installable{installablesSettings.defaultFlake}; | ||
std::vector<std::string> res; | ||
std::vector<std::string> excludeRes; | ||
|
||
@@ -40,6 +41,24 @@ struct CmdSearch : InstallableValueCommand, MixJSON | ||
excludeRes.push_back(s); | ||
}}, | ||
}); | ||
+ | ||
+ bool hasInstallable = false; | ||
+ | ||
+ addFlag({ | ||
+ .longName = "installable", | ||
+ .shortName = 'i', | ||
+ .description = "Search within this installable", | ||
+ .labels = {"installable"}, | ||
+ .handler = {[this, &hasInstallable](std::string ss) { | ||
+ hasInstallable = true; | ||
+ _installable = ss; | ||
+ }}, | ||
+ .completer = completePath | ||
+ }); | ||
+ | ||
+ if (hasInstallable && (file || expr)) { | ||
+ throw UsageError("'--installable' cannot be used together with '--file' or '--expr'"); | ||
+ } | ||
} | ||
|
||
std::string description() override | ||
@@ -62,14 +81,21 @@ struct CmdSearch : InstallableValueCommand, MixJSON | ||
}; | ||
} | ||
|
||
- void run(ref<Store> store, ref<InstallableValue> installable) override | ||
+ void run(ref<Store> store) override | ||
{ | ||
+ if (_installable == "" && ! file && ! expr) { | ||
+ throw UsageError("nothing to search from, set 'default-flake' option or specify one of '--installable', '--file', '--expr'"); | ||
+ } | ||
+ | ||
settings.readOnlyMode = true; | ||
evalSettings.enableImportFromDerivation.setDefault(false); | ||
|
||
+ auto installable = InstallableValue::require( | ||
+ parseInstallable(store, (file || expr) ? "" : _installable)); | ||
+ | ||
// Recommend "^" here instead of ".*" due to differences in resulting highlighting | ||
if (res.empty()) | ||
- throw UsageError("Must provide at least one regex! To match all packages, use '%s'.", "nix search <installable> ^"); | ||
+ throw UsageError("Must provide at least one regex! To match all packages, use '%s'.", "nix search ^"); | ||
|
||
std::vector<std::regex> regexes; | ||
std::vector<std::regex> excludeRegexes; | ||
diff --git a/tests/functional/completions.sh b/tests/functional/completions.sh | ||
index d3d5bbd48..a5ab90220 100644 | ||
--- a/tests/functional/completions.sh | ||
+++ b/tests/functional/completions.sh | ||
@@ -38,8 +38,8 @@ EOF | ||
[[ "$(NIX_GET_COMPLETIONS=2 nix flake metad)" == $'normal\nmetadata\t' ]] | ||
|
||
# Filename completion | ||
-[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]] | ||
-[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]] | ||
+#[[ "$(NIX_GET_COMPLETIONS=2 nix build ./f)" == $'filenames\n./foo\t' ]] | ||
+#[[ "$(NIX_GET_COMPLETIONS=2 nix build ./nonexistent)" == $'filenames' ]] | ||
|
||
# Input override completion | ||
[[ "$(NIX_GET_COMPLETIONS=4 nix build ./foo --override-input '')" == $'normal\na\t' ]] | ||
diff --git a/tests/functional/flakes/flakes.sh b/tests/functional/flakes/flakes.sh | ||
index 3ef518b23..8b88dbb8f 100644 | ||
--- a/tests/functional/flakes/flakes.sh | ||
+++ b/tests/functional/flakes/flakes.sh | ||
@@ -116,7 +116,7 @@ nix build -o $TEST_ROOT/result flake1#foo | ||
[[ -e $TEST_ROOT/result/hello ]] | ||
|
||
# Test packages.default. | ||
-nix build -o $TEST_ROOT/result flake1 | ||
+nix build -o $TEST_ROOT/result flake1# | ||
[[ -e $TEST_ROOT/result/hello ]] | ||
|
||
nix build -o $TEST_ROOT/result $flake1Dir | ||
diff --git a/tests/functional/search.sh b/tests/functional/search.sh | ||
index d9c7a75da..35f665db6 100644 | ||
--- a/tests/functional/search.sh | ||
+++ b/tests/functional/search.sh | ||
@@ -3,43 +3,42 @@ source common.sh | ||
clearStore | ||
clearCache | ||
|
||
-(( $(nix search -f search.nix '' hello | wc -l) > 0 )) | ||
+(( $(nix search -f search.nix hello | wc -l) > 0 )) | ||
|
||
# Check descriptions are searched | ||
-(( $(nix search -f search.nix '' broken | wc -l) > 0 )) | ||
+(( $(nix search -f search.nix broken | wc -l) > 0 )) | ||
|
||
# Check search that matches nothing | ||
-(( $(nix search -f search.nix '' nosuchpackageexists | wc -l) == 0 )) | ||
+(( $(nix search -f search.nix nosuchpackageexists | wc -l) == 0 )) | ||
|
||
# Search for multiple arguments | ||
-(( $(nix search -f search.nix '' hello empty | wc -l) == 2 )) | ||
+(( $(nix search -f search.nix hello empty | wc -l) == 2 )) | ||
|
||
# Multiple arguments will not exist | ||
-(( $(nix search -f search.nix '' hello broken | wc -l) == 0 )) | ||
+(( $(nix search -f search.nix hello broken | wc -l) == 0 )) | ||
|
||
# No regex should return an error | ||
-(( $(nix search -f search.nix '' | wc -l) == 0 )) | ||
+(( $(nix search -f search.nix | wc -l) == 0 )) | ||
|
||
## Search expressions | ||
|
||
-# Check that empty search string matches all | ||
-nix search -f search.nix '' ^ | grepQuiet foo | ||
-nix search -f search.nix '' ^ | grepQuiet bar | ||
-nix search -f search.nix '' ^ | grepQuiet hello | ||
+nix search -f search.nix ^ | grepQuiet foo | ||
+nix search -f search.nix ^ | grepQuiet bar | ||
+nix search -f search.nix ^ | grepQuiet hello | ||
|
||
## Tests for multiple regex/match highlighting | ||
|
||
e=$'\x1b' # grep doesn't support \e, \033 or even \x1b | ||
# Multiple overlapping regexes | ||
-(( $(nix search -f search.nix '' 'oo' 'foo' 'oo' | grep -c "$e\[32;1mfoo$e\\[0;1m") == 1 )) | ||
-(( $(nix search -f search.nix '' 'broken b' 'en bar' | grep -c "$e\[32;1mbroken bar$e\\[0m") == 1 )) | ||
+(( $(nix search -f search.nix 'oo' 'foo' 'oo' | grep -c "$e\[32;1mfoo$e\\[0;1m") == 1 )) | ||
+(( $(nix search -f search.nix 'broken b' 'en bar' | grep -c "$e\[32;1mbroken bar$e\\[0m") == 1 )) | ||
|
||
# Multiple matches | ||
# Searching for 'o' should yield the 'o' in 'broken bar', the 'oo' in foo and 'o' in hello | ||
-(( $(nix search -f search.nix '' 'o' | grep -Eoc "$e\[32;1mo{1,2}$e\[(0|0;1)m") == 3 )) | ||
+(( $(nix search -f search.nix 'o' | grep -Eoc "$e\[32;1mo{1,2}$e\[(0|0;1)m") == 3 )) | ||
# Searching for 'b' should yield the 'b' in bar and the two 'b's in 'broken bar' | ||
# NOTE: This does not work with `grep -c` because it counts the two 'b's in 'broken bar' as one matched line | ||
-(( $(nix search -f search.nix '' 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) | ||
+(( $(nix search -f search.nix 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) | ||
|
||
## Tests for --exclude | ||
(( $(nix search -f search.nix ^ -e hello | grep -c hello) == 0 )) |
32a45e3
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.