aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorThéophane Hufschmitt <7226587+thufschmitt@users.noreply.github.com>2023-10-31 16:19:05 +0100
committerLunaphied <lunaphied@lunaphied.me>2024-03-25 17:36:24 -0600
commit86881226b0e51c204f07385b7b57743c23e34d44 (patch)
tree737e75ee7cc6ec8932b850ff6f20adfc4e285628 /src/libutil
parentaa7653608d4d0028bb98af491aec76b2fea7f882 (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.cc13
-rw-r--r--src/libutil/args.hh14
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