diff options
author | Théophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com> | 2023-10-31 16:19:05 +0100 |
---|---|---|
committer | Lunaphied <lunaphied@lunaphied.me> | 2024-03-25 17:36:24 -0600 |
commit | 86881226b0e51c204f07385b7b57743c23e34d44 (patch) | |
tree | 737e75ee7cc6ec8932b850ff6f20adfc4e285628 /src/libutil | |
parent | aa7653608d4d0028bb98af491aec76b2fea7f882 (diff) |
Merge pull request #8817 from iFreilicht/flake-update-lock-overhaul
Overhaul `nix flake update` and `nix flake lock` UX
(cherry picked from commit 12a0ae73dbb37becefa5a442eb4532ff0de9ce65)
Change-Id: Iff3b4f4235ebb1948ec612036b39ab29e4ca22b2
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/args.cc | 13 | ||||
-rw-r--r-- | src/libutil/args.hh | 14 |
2 files changed, 25 insertions, 2 deletions
diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 77069c7b9..3e39b4d7c 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -255,7 +255,18 @@ bool Args::processArgs(const Strings & args, bool finish) } if (!anyCompleted) exp.handler.fun(ss); - expectedArgs.pop_front(); + + /* Move the list element to the processedArgs. This is almost the same as + `processedArgs.push_back(expectedArgs.front()); expectedArgs.pop_front()`, + except that it will only adjust the next and prev pointers of the list + elements, meaning the actual contents don't move in memory. This is + critical to prevent invalidating internal pointers! */ + processedArgs.splice( + processedArgs.end(), + expectedArgs, + expectedArgs.begin(), + ++expectedArgs.begin()); + res = true; } diff --git a/src/libutil/args.hh b/src/libutil/args.hh index c90a48ad4..77f7ff2a8 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -200,13 +200,25 @@ protected: /** * Queue of expected positional argument forms. * - * Positional arugment descriptions are inserted on the back. + * Positional argument descriptions are inserted on the back. * * As positional arguments are passed, these are popped from the * front, until there are hopefully none left as all args that were * expected in fact were passed. */ std::list<ExpectedArg> expectedArgs; + /** + * List of processed positional argument forms. + * + * All items removed from `expectedArgs` are added here. After all + * arguments were processed, this list should be exactly the same as + * `expectedArgs` was before. + * + * This list is used to extend the lifetime of the argument forms. + * If this is not done, some closures that reference the command + * itself will segfault. + */ + std::list<ExpectedArg> processedArgs; /** * Process some positional arugments |