From: Phillip Wood <phillip.wood123@gmail.com>
To: "brian m. carlson" <sandals@crustytoothpaste.net>, git@vger.kernel.org
Cc: Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH v5 4/4] builtin/stash: provide a way to import stashes from a ref
Date: Mon, 12 May 2025 10:10:46 +0100 [thread overview]
Message-ID: <94b26c62-c8da-49ba-a4f1-66da20956c0b@gmail.com> (raw)
In-Reply-To: <20250508234458.3665894-5-sandals@crustytoothpaste.net>
Hi brian
On 09/05/2025 00:44, brian m. carlson wrote:
>
> @@ -1962,6 +1971,99 @@ static int write_commit_with_parents(struct repository *r,
> return ret;
> }
>
> +static int do_import_stash(struct repository *r, const char *rev)
> +{
> + struct object_id chain;
> + struct oid_array items = OID_ARRAY_INIT;
> + int res = 0;
> + int i;
> + const char *buffer = NULL;
> + struct commit *this = NULL;
> + char *msg = NULL;
> +
> + if (repo_get_oid(r, rev, &chain))
> + return error(_("not a valid revision: %s"), rev);
> +
> + /*
> + * Walk the commit history, finding each stash entry, and load data into
> + * the array.
> + */
> + for (i = 0;; i++) {
> + struct object_id tree, oid;
> + char revision[GIT_MAX_HEXSZ + 1];
> +
> + oid_to_hex_r(revision, &chain);
> +
> + if (get_oidf(&tree, "%s:", revision) ||
> + !oideq(&tree, r->hash_algo->empty_tree)) {
> + res = error(_("%s is not a valid exported stash commit"), revision);
> + goto out;
> + }
> + if (get_oidf(&chain, "%s^1", revision) ||
> + get_oidf(&oid, "%s^2", revision))
> + break;
> + oid_array_append(&items, &oid);
> + }
This loop could use some improvement - it does not use the loop
variable, it accepts any commit with an empty tree as a valid exported
stash, it is pretty lax about checking that the commits in the chain
have either zero or two parents, it does not check if the second parent
looks like a stash and it is forever converting between strings and
object_ids. I think it would be better to loop over commits rather than
object ids then you can walk the history using the pointers to the
parent commits. Something like
if (repo_get_oid(r, rev, &chain))
return error(_("not a valid revision: %s"), rev);
this = lookup_commit_reference(r, &chain);
if (!this)
return error(_("not a commit: %s"), rev);
/*
* Walk the commit history, finding each stash entry, and load data into
* the array.
*/
for (;;) {
struct commit *stash;
struct tree *tree = repo_get_commit_tree(r, this);
if (!tree ||
!oideq(&tree->object.oid, r->hash_algo->empty_tree) ||
(this->parents &&
(!this->parents->next || this->parents->next->next))) {
res = error(_("%s is not a valid exported stash commit"),
oid_to_hex(&this->object.oid));
goto out;
}
if (!this->parents)
break;
stash = this->parents->next->item;
if (repo_parse_commit(r, this->parents->item) ||
repo_parse_commit(r, stash)) {
res = error(_("cannot parse parents of commit: %s"),
oid_to_hex(&this->object.oid));
goto out;
}
if (check_stash_topology(r, stash)) {
res = error(_("%s does not look like a stash commit"),
oid_to_hex(&stash->object.oid));
goto out;
}
/* TODO:
* - store commits, not objects
*/
oid_array_append(&items, &this->parents->next->item->object.oid);
this = this->parents->item;
}
I've appended a fixup commit below that applies on top of your
patch. The fixups for this patch and the previous one can be fetched
with
git fetch https://github.com/phillipwood/git.git bc/stash-import-export-fixups
if you want to use them.
Best Wishes
Phillip
---- >8 ----
From: Phillip Wood <phillip.wood@dunelm.org.uk>
Subject: [PATCH] fixup! builtin/stash: provide a way to import stashes from a
ref
Strengthen the checks on imported commits to ensure that the chain of
imported stashes consists of commits with exactly two parents where the
first parent is either the root commit or another imported stash commit
and the second parent looks like a stash commit.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
builtin/stash.c | 43 +++++++++++++++++++++++++++++++------------
1 file changed, 31 insertions(+), 12 deletions(-)
diff --git a/builtin/stash.c b/builtin/stash.c
index 02cf344ed9..7d3a8c03a0 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -2011,25 +2011,44 @@ static int do_import_stash(struct repository *r, const char *rev)
if (repo_get_oid(r, rev, &chain))
return error(_("not a valid revision: %s"), rev);
+ this = lookup_commit_reference(r, &chain);
+ if (!this)
+ return error(_("not a commit: %s"), rev);
/*
* Walk the commit history, finding each stash entry, and load data into
* the array.
*/
- for (i = 0;; i++) {
- struct object_id tree, oid;
- char revision[GIT_MAX_HEXSZ + 1];
-
- oid_to_hex_r(revision, &chain);
-
- if (get_oidf(&tree, "%s:", revision) ||
- !oideq(&tree, r->hash_algo->empty_tree)) {
- res = error(_("%s is not a valid exported stash commit"), revision);
+ for (;;) {
+ struct commit *stash;
+ struct tree *tree = repo_get_commit_tree(r, this);
+
+ if (!tree ||
+ !oideq(&tree->object.oid, r->hash_algo->empty_tree) ||
+ (this->parents &&
+ (!this->parents->next || this->parents->next->next))) {
+ res = error(_("%s is not a valid exported stash commit"),
+ oid_to_hex(&this->object.oid));
goto out;
}
- if (get_oidf(&chain, "%s^1", revision) ||
- get_oidf(&oid, "%s^2", revision))
+ if (!this->parents)
break;
- oid_array_append(&items, &oid);
+ stash = this->parents->next->item;
+ if (repo_parse_commit(r, this->parents->item) ||
+ repo_parse_commit(r, stash)) {
+ res = error(_("cannot parse parents of commit: %s"),
+ oid_to_hex(&this->object.oid));
+ goto out;
+ }
+ if (check_stash_topology(r, stash)) {
+ res = error(_("%s does not look like a stash commit"),
+ oid_to_hex(&stash->object.oid));
+ goto out;
+ }
+ /* TODO:
+ * - store commits, not objects
+ */
+ oid_array_append(&items, &this->parents->next->item->object.oid);
+ this = this->parents->item;
}
/*
--
2.49.0.300.g813f75aecee
next prev parent reply other threads:[~2025-05-12 9:10 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-08 23:44 [PATCH v5 0/4] Importing and exporting stashes to refs brian m. carlson
2025-05-08 23:44 ` [PATCH v5 1/4] object-name: make get_oid quietly return an error brian m. carlson
2025-05-09 1:55 ` Junio C Hamano
2025-05-09 19:50 ` brian m. carlson
2025-05-08 23:44 ` [PATCH v5 2/4] builtin/stash: factor out revision parsing into a function brian m. carlson
2025-05-09 15:27 ` Junio C Hamano
2025-05-08 23:44 ` [PATCH v5 3/4] builtin/stash: provide a way to export stashes to a ref brian m. carlson
2025-05-09 16:38 ` Junio C Hamano
2025-05-09 19:31 ` Junio C Hamano
2025-05-10 21:24 ` Jeff King
2025-05-12 9:10 ` Phillip Wood
2025-05-12 15:53 ` Junio C Hamano
2025-05-08 23:44 ` [PATCH v5 4/4] builtin/stash: provide a way to import stashes from " brian m. carlson
2025-05-09 19:54 ` Junio C Hamano
2025-05-11 23:44 ` brian m. carlson
2025-05-10 17:21 ` Jeff King
2025-05-12 12:42 ` Junio C Hamano
2025-05-12 12:58 ` Jeff King
2025-05-12 16:05 ` Junio C Hamano
2025-05-12 21:19 ` brian m. carlson
2025-05-10 21:33 ` Jeff King
2025-05-12 9:10 ` Phillip Wood [this message]
2025-05-09 1:10 ` [PATCH v5 0/4] Importing and exporting stashes to refs Junio C Hamano
2025-05-09 20:16 ` brian m. carlson
2025-05-09 16:53 ` D. Ben Knoble
2025-05-09 20:15 ` brian m. carlson
2025-05-10 19:13 ` D. Ben Knoble
2025-05-22 18:55 ` [PATCH] Makefile: avoid constant rebuilds with compilation database brian m. carlson
2025-05-22 18:55 ` [PATCH v6 0/5] Importing and exporting stashes to refs brian m. carlson
2025-06-01 22:32 ` [PATCH v7 0/4] " brian m. carlson
2025-06-01 22:32 ` [PATCH v7 1/4] object-name: make get_oid quietly return an error brian m. carlson
2025-06-01 22:32 ` [PATCH v7 2/4] builtin/stash: factor out revision parsing into a function brian m. carlson
2025-06-01 22:32 ` [PATCH v7 3/4] builtin/stash: provide a way to export stashes to a ref brian m. carlson
2025-06-05 9:25 ` Phillip Wood
2025-06-11 11:31 ` Kristoffer Haugsbakk
2025-06-11 23:35 ` brian m. carlson
2025-06-01 22:32 ` [PATCH v7 4/4] builtin/stash: provide a way to import stashes from " brian m. carlson
2025-06-05 9:38 ` [PATCH v7 0/4] Importing and exporting stashes to refs Phillip Wood
2025-06-12 1:12 ` [PATCH v8 " brian m. carlson
2025-06-12 1:12 ` [PATCH v8 1/4] object-name: make get_oid quietly return an error brian m. carlson
2025-06-12 1:12 ` [PATCH v8 2/4] builtin/stash: factor out revision parsing into a function brian m. carlson
2025-06-12 1:12 ` [PATCH v8 3/4] builtin/stash: provide a way to export stashes to a ref brian m. carlson
2025-06-12 1:12 ` [PATCH v8 4/4] builtin/stash: provide a way to import stashes from " brian m. carlson
2025-06-25 8:40 ` [PATCH v8 0/4] Importing and exporting stashes to refs Phillip Wood
2025-06-25 16:30 ` Junio C Hamano
2025-05-22 18:55 ` [PATCH v6 1/5] object-name: make get_oid quietly return an error brian m. carlson
2025-05-22 19:27 ` Junio C Hamano
2025-05-22 18:55 ` [PATCH v6 2/5] reflog-walk: expose read_complete_reflog brian m. carlson
2025-05-22 21:53 ` Ramsay Jones
2025-05-23 23:22 ` brian m. carlson
2025-05-24 1:09 ` Ramsay Jones
2025-05-26 19:55 ` brian m. carlson
2025-05-29 16:01 ` Phillip Wood
2025-05-29 21:59 ` Junio C Hamano
2025-05-22 18:55 ` [PATCH v6 3/5] builtin/stash: factor out revision parsing into a function brian m. carlson
2025-05-22 20:34 ` Junio C Hamano
2025-05-23 23:25 ` brian m. carlson
2025-05-24 0:23 ` Junio C Hamano
2025-05-26 19:36 ` brian m. carlson
2025-05-22 18:55 ` [PATCH v6 4/5] builtin/stash: provide a way to export stashes to a ref brian m. carlson
2025-05-22 20:51 ` Junio C Hamano
2025-05-26 19:42 ` brian m. carlson
2025-05-29 16:01 ` Phillip Wood
2025-05-22 18:55 ` [PATCH v6 5/5] builtin/stash: provide a way to import stashes from " brian m. carlson
2025-05-22 21:09 ` Junio C Hamano
2025-05-26 20:03 ` brian m. carlson
2025-05-22 21:15 ` Junio C Hamano
2025-05-23 13:17 ` Phillip Wood
2025-05-22 19:00 ` [PATCH] Makefile: avoid constant rebuilds with compilation database brian m. carlson
2025-05-22 19:08 ` Junio C Hamano
2025-06-11 11:35 ` [PATCH v5 0/4] Importing and exporting stashes to refs Kristoffer Haugsbakk
2025-06-12 0:45 ` brian m. carlson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=94b26c62-c8da-49ba-a4f1-66da20956c0b@gmail.com \
--to=phillip.wood123@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=phillip.wood@dunelm.org.uk \
--cc=sandals@crustytoothpaste.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).