From patchwork Mon Apr 1 09:02:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612630 Received: from mail-4317.proton.ch (mail-4317.proton.ch [185.70.43.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 279E12F55 for ; Mon, 1 Apr 2024 09:02:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962180; cv=none; b=UzN0hAWUKAC/XOmDJtyav3qZ+y9ImxMhgKdIhc2mpznOee+vnFhAEq4fjjjKcHhiwlCXtCKEnmVzjwUVjFDH5HAPOxD9i7LbCy2xjFrd87vZLs1gfPomTYda1cJhxQe0EPd2KuCZwrTJI9w3Eux/Ucuweva7eYjqzH3xOgCSPBk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962180; c=relaxed/simple; bh=H3zDYpYy2Kk3ua9/i2fa91rlRBRf5ioq9zRY5nLdnBM=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=F0y1+NcFgopGaejdNsT7UyuxY3lcx+tXrxB8cpBsmhyCcyY3TIhQlTxiCzzrtKyCd2Yqhz/CnIGm2KzvGYleFawiRNpFpJ7Yj3lcKkmLg6lEUflb4UMdhjn4hhx2htH+/CIGTruSjH+zFnC1CpZLyl6EJD2nHMsWWK3QXOdkhcw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=l8hRt7cu; arc=none smtp.client-ip=185.70.43.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="l8hRt7cu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962174; x=1712221374; bh=0MSaNrZWvBJqAIOrTPzotFThP8ESonD26dCL8LojDv0=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=l8hRt7cuwULawZOd9OKOGNvPi/pTuihoYVNR+c6ueUnzNij+C1AjbL3mfrQceLwjb v5iYDXz5YzkV3Ac2WcGMTynZnUfiR18Gsf7MxHKGv/cbkSneftcgCJKKzYhyW/xkxE ln4gJ84DwWuL0VHmBzF6nbC744L+Rlgg4GWNrRKmCNsKj3GLPnUBt+fGA5/xd/t1X4 nIeJHDpR+ZhGTVy+YifvoKu1PKFuASrvrxcjrU9Km9xmT+eAUZQVNlPpXIBrbizQqh 9p/U1JzSw0Ld0jIENffU2Zt2DWTMUfoDFizpHsjq2sxa5sz2zz11vp+pbEHWG2u+we zQEJgk9XrWu/Q== Date: Mon, 01 Apr 2024 09:02:47 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 1/8] fast-import: tighten path unquoting Message-ID: In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Path parsing in fast-import is inconsistent and many unquoting errors are suppressed or not checked. appears in the grammar in these places: filemodify ::= 'M' SP ( | 'inline') SP LF filedelete ::= 'D' SP LF filecopy ::= 'C' SP SP LF filerename ::= 'R' SP SP LF ls ::= 'ls' SP SP LF ls-commit ::= 'ls' SP LF and fast-import.c parses them in five different ways: 1. For filemodify and filedelete: Try to unquote . If it unquotes without errors, use the unquoted version; otherwise, treat it as literal bytes to the end of the line (including any number of SP). 2. For filecopy (source) and filerename (source): Try to unquote . If it unquotes without errors, use the unquoted version; otherwise, treat it as literal bytes up to, but not including, the next SP. 3. For filecopy (dest) and filerename (dest): Like 1., but an unquoted empty string is forbidden. 4. For ls: If starts with `"`, unquote it and report parse errors; otherwise, treat it as literal bytes to the end of the line (including any number of SP). 5. For ls-commit: Unquote and report parse errors. (It must start with `"` to disambiguate from ls.) In the first three, any errors from trying to unquote a string are suppressed, so a quoted string that contains invalid escapes would be interpreted as literal bytes. For example, `"\xff"` would fail to unquote (because hex escapes are not supported), and it would instead be interpreted as the byte sequence '"', '\\', 'x', 'f', 'f', '"', which is certainly not intended. Some front-ends erroneously use their language's standard quoting routine instead of matching Git's, which could silently introduce escapes that would be incorrectly parsed due to this and lead to data corruption. The documentation states “To use a source path that contains SP the path must be quoted.”, so it is expected that some implementations depend on spaces being allowed in paths in the final position. Thus we have two documented ways to parse paths, so simplify the implementation to that. Now we have: 1. `parse_path_eol` for filemodify, filedelete, filecopy (dest), filerename (dest), ls, and ls-commit: If starts with `"`, unquote it and report parse errors; otherwise, treat it as literal bytes to the end of the line (including any number of SP). 2. `parse_path_space` for filecopy (source) and filerename (source): If starts with `"`, unquote it and report parse errors; otherwise, treat it as literal bytes up to, but not including, the next SP. It must be followed by SP. There remain two special cases: The dest in filecopy and rename cannot be an unquoted empty string (this will be addressed subsequently) and in ls-commit must be quoted to disambiguate it from ls. Signed-off-by: Thalia Archibald --- builtin/fast-import.c | 102 ++++++++++------- t/t9300-fast-import.sh | 251 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 309 insertions(+), 44 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 782bda007c..6f9048a037 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2258,10 +2258,54 @@ static uintmax_t parse_mark_ref_space(const char **p) return mark; } +/* + * Parse the path string into the strbuf. It may be quoted with escape sequences + * or unquoted without escape sequences. When unquoted, it may only contain a + * space if `include_spaces` is nonzero. + */ +static void parse_path(struct strbuf *sb, const char *p, const char **endp, int include_spaces, const char *field) +{ + if (*p == '"') { + if (unquote_c_style(sb, p, endp)) + die("Invalid %s: %s", field, command_buf.buf); + } else { + if (include_spaces) + *endp = p + strlen(p); + else + *endp = strchr(p, ' '); + strbuf_add(sb, p, *endp - p); + } +} + +/* + * Parse the path string into the strbuf, and complain if this is not the end of + * the string. It may contain spaces even when unquoted. + */ +static void parse_path_eol(struct strbuf *sb, const char *p, const char *field) +{ + const char *end; + + parse_path(sb, p, &end, 1, field); + if (*end) + die("Garbage after %s: %s", field, command_buf.buf); +} + +/* + * Parse the path string into the strbuf, and ensure it is followed by a space. + * It may not contain spaces when unquoted. Update *endp to point to the first + * character after the space. + */ +static void parse_path_space(struct strbuf *sb, const char *p, const char **endp, const char *field) +{ + parse_path(sb, p, endp, 0, field); + if (**endp != ' ') + die("Missing space after %s: %s", field, command_buf.buf); + (*endp)++; +} + static void file_change_m(const char *p, struct branch *b) { static struct strbuf uq = STRBUF_INIT; - const char *endp; struct object_entry *oe; struct object_id oid; uint16_t mode, inline_data = 0; @@ -2299,11 +2343,8 @@ static void file_change_m(const char *p, struct branch *b) } strbuf_reset(&uq); - if (!unquote_c_style(&uq, p, &endp)) { - if (*endp) - die("Garbage after path in: %s", command_buf.buf); - p = uq.buf; - } + parse_path_eol(&uq, p, "path"); + p = uq.buf; /* Git does not track empty, non-toplevel directories. */ if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *p) { @@ -2367,48 +2408,29 @@ static void file_change_m(const char *p, struct branch *b) static void file_change_d(const char *p, struct branch *b) { static struct strbuf uq = STRBUF_INIT; - const char *endp; strbuf_reset(&uq); - if (!unquote_c_style(&uq, p, &endp)) { - if (*endp) - die("Garbage after path in: %s", command_buf.buf); - p = uq.buf; - } + parse_path_eol(&uq, p, "path"); + p = uq.buf; tree_content_remove(&b->branch_tree, p, NULL, 1); } -static void file_change_cr(const char *s, struct branch *b, int rename) +static void file_change_cr(const char *p, struct branch *b, int rename) { - const char *d; + const char *s, *d; static struct strbuf s_uq = STRBUF_INIT; static struct strbuf d_uq = STRBUF_INIT; - const char *endp; struct tree_entry leaf; strbuf_reset(&s_uq); - if (!unquote_c_style(&s_uq, s, &endp)) { - if (*endp != ' ') - die("Missing space after source: %s", command_buf.buf); - } else { - endp = strchr(s, ' '); - if (!endp) - die("Missing space after source: %s", command_buf.buf); - strbuf_add(&s_uq, s, endp - s); - } + parse_path_space(&s_uq, p, &p, "source"); s = s_uq.buf; - endp++; - if (!*endp) + if (!p) die("Missing dest: %s", command_buf.buf); - - d = endp; strbuf_reset(&d_uq); - if (!unquote_c_style(&d_uq, d, &endp)) { - if (*endp) - die("Garbage after dest in: %s", command_buf.buf); - d = d_uq.buf; - } + parse_path_eol(&d_uq, p, "dest"); + d = d_uq.buf; memset(&leaf, 0, sizeof(leaf)); if (rename) @@ -3152,6 +3174,7 @@ static void print_ls(int mode, const unsigned char *hash, const char *path) static void parse_ls(const char *p, struct branch *b) { + static struct strbuf uq = STRBUF_INIT; struct tree_entry *root = NULL; struct tree_entry leaf = {NULL}; @@ -3168,16 +3191,9 @@ static void parse_ls(const char *p, struct branch *b) root->versions[1].mode = S_IFDIR; load_tree(root); } - if (*p == '"') { - static struct strbuf uq = STRBUF_INIT; - const char *endp; - strbuf_reset(&uq); - if (unquote_c_style(&uq, p, &endp)) - die("Invalid path: %s", command_buf.buf); - if (*endp) - die("Garbage after path in: %s", command_buf.buf); - p = uq.buf; - } + strbuf_reset(&uq); + parse_path_eol(&uq, p, "path"); + p = uq.buf; tree_content_get(root, p, &leaf, 1); /* * A directory in preparation would have a sha1 of zero diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 60e30fed3c..0fb5612b07 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -2142,6 +2142,7 @@ test_expect_success 'Q: deny note on empty branch' ' EOF test_must_fail git fast-import has a special +# case. Test every occurrence of in the grammar against every error case. +# + +# +# Valid paths at the end of a line: filemodify, filedelete, filecopy (dest), +# filerename (dest), and ls. +# +# commit :301 from root -- modify hello.c (for setup) +# commit :302 from :301 -- modify $path +# commit :303 from :302 -- delete $path +# commit :304 from :301 -- copy hello.c $path +# commit :305 from :301 -- rename hello.c $path +# ls :305 $path +# +test_path_eol_success () { + local test="$1" path="$2" unquoted_path="$3" + test_expect_success "S: paths at EOL with $test must work" ' + test_when_finished "git branch -D S-path-eol" && + + git fast-import --export-marks=marks.out <<-EOF >out 2>err && + blob + mark :401 + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data <tree_m.exp && + git ls-tree $commit_m | sort >tree_m.out && + test_cmp tree_m.exp tree_m.out && + + printf "100644 blob $blob1\thello.c\n" >tree_d.exp && + git ls-tree $commit_d >tree_d.out && + test_cmp tree_d.exp tree_d.out && + + ( printf "100644 blob $blob1\t'"$unquoted_path"'\n" && + printf "100644 blob $blob1\thello.c\n" ) | sort >tree_c.exp && + git ls-tree $commit_c | sort >tree_c.out && + test_cmp tree_c.exp tree_c.out && + + printf "100644 blob $blob1\t'"$unquoted_path"'\n" >tree_r.exp && + git ls-tree $commit_r >tree_r.out && + test_cmp tree_r.exp tree_r.out && + + test_cmp out tree_r.exp + ' +} + +test_path_eol_success 'quoted spaces' '" hello world.c "' ' hello world.c ' +test_path_eol_success 'unquoted spaces' ' hello world.c ' ' hello world.c ' + +# +# Valid paths before a space: filecopy (source) and filerename (source). +# +# commit :301 from root -- modify $path (for setup) +# commit :302 from :301 -- copy $path hello2.c +# commit :303 from :301 -- rename $path hello2.c +# +test_path_space_success () { + local test="$1" path="$2" unquoted_path="$3" + test_expect_success "S: paths before space with $test must work" ' + test_when_finished "git branch -D S-path-space" && + + git fast-import --export-marks=marks.out <<-EOF 2>err && + blob + mark :401 + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data <tree_c.exp && + git ls-tree $commit_c | sort >tree_c.out && + test_cmp tree_c.exp tree_c.out && + + printf "100644 blob $blob\thello2.c\n" >tree_r.exp && + git ls-tree $commit_r >tree_r.out && + test_cmp tree_r.exp tree_r.out + ' +} + +test_path_space_success 'quoted spaces' '" hello world.c "' ' hello world.c ' +test_path_space_success 'no unquoted spaces' 'hello_world.c' 'hello_world.c' + +# +# Test a single commit change with an invalid path. Run it with all occurrences +# of in the grammar against all error kinds. +# +test_path_fail () { + local change="$1" what="$2" prefix="$3" path="$4" suffix="$5" err_grep="$6" + test_expect_success "S: $change with $what must fail" ' + test_must_fail git fast-import <<-EOF 2>err && + blob + mark :1 + data < $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE + data <, the must be quoted. +test_path_eol_quoted_fail 'ls (without dataref in commit)' 'ls ' path '' + ### ### series T (ls) ### From patchwork Mon Apr 1 09:03:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612631 Received: from mail-4317.proton.ch (mail-4317.proton.ch [185.70.43.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1E5FDF4A for ; Mon, 1 Apr 2024 09:03:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962197; cv=none; b=t8YcHnxc/gNlZ3VgO5W9K/y9zBS0rhCmXXf1oj/xrt+tMtVE6yQbCRsHHXnZYfFvXQjkrD63qU3AfQpAo1bKJsNmMAiYw0tqhoQZo3uaOfbIvp4SlKrNBTxonTZcztGJ6UZK4OKs85bXt1/4evr7DlbFIPzJNZT7YXtvkDYvzh0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962197; c=relaxed/simple; bh=4YZNmSDNODYP1WfulaPsDxzaVRGWBYwT6PhvSafTARE=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uuFSUN3vLsHZ1TxNsG6C+LUI6x8wI5L4UUzSvIvvtvKmCOgAyIqCCI233vbxqdXl9xKsl9jdYyHVI4AzHrANImF0G/n3Leaprkg3d1Ge22NmgumBbdXokLnlJ07IYqjORD+D6sNiZKtqvLqRwkqYZWetr1dFlT4EqWnm5ehFokU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=H20s88Ax; arc=none smtp.client-ip=185.70.43.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="H20s88Ax" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962193; x=1712221393; bh=m4PCs2DrYcfclFDtryZauhCQaCZ1BZAunH+n4xCGjbk=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=H20s88AxUGJ8JRJPYgG/fc8ghxl+uPCLdGFEpertLwktiZnNxuK1UtXwJxyAO3XbB dgzVe3wMD7I8BYdMl1Poyw3KVUskNQyv80vARfN5QHzNFz9tydMI+8z1XG0im/48kb S9DPRg06xZI2XQRESvTaVaBepTDSqCVve6NbgMCtMPPKj2I8FIh1aju6E0BhyYYTPX Ho4s5ZsNRoDM8WX/eQnGlFJFp1QWO9mu3ecou78RDOPSkyCdwp81VTLcghxH2c3iEg kchgqRHDT37x+PdH/18TSOse+2mqmG0ld19iWh+pLRaRayN1uY26EXQQ7RZ4vDCiEb 282Isi16ExXsw== Date: Mon, 01 Apr 2024 09:03:06 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 2/8] fast-import: directly use strbufs for paths Message-ID: <82a6f53c1326a420348eb70461f5929340a930d3.1711960552.git.thalia@archibald.dev> In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Previously, one case would not write the path to the strbuf: when the path is unquoted and at the end of the string. It was essentially copy-on-write. However, with the logic simplification of the previous commit, this case was eliminated and the strbuf is always populated. Directly use the strbufs now instead of an alias. Since this already changes all the lines that use the strbufs, rename them from `uq` to be more descriptive. That they are unquoted is not their most important property, so name them after what they carry. Additionally, `file_change_m` no longer needs to copy the path before reading inline data. Signed-off-by: Thalia Archibald --- builtin/fast-import.c | 64 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 6f9048a037..fad9324e59 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2305,7 +2305,7 @@ static void parse_path_space(struct strbuf *sb, const char *p, const char **endp static void file_change_m(const char *p, struct branch *b) { - static struct strbuf uq = STRBUF_INIT; + static struct strbuf path = STRBUF_INIT; struct object_entry *oe; struct object_id oid; uint16_t mode, inline_data = 0; @@ -2342,13 +2342,12 @@ static void file_change_m(const char *p, struct branch *b) die("Missing space after SHA1: %s", command_buf.buf); } - strbuf_reset(&uq); - parse_path_eol(&uq, p, "path"); - p = uq.buf; + strbuf_reset(&path); + parse_path_eol(&path, p, "path"); /* Git does not track empty, non-toplevel directories. */ - if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *p) { - tree_content_remove(&b->branch_tree, p, NULL, 0); + if (S_ISDIR(mode) && is_empty_tree_oid(&oid) && *path.buf) { + tree_content_remove(&b->branch_tree, path.buf, NULL, 0); return; } @@ -2369,10 +2368,6 @@ static void file_change_m(const char *p, struct branch *b) if (S_ISDIR(mode)) die("Directories cannot be specified 'inline': %s", command_buf.buf); - if (p != uq.buf) { - strbuf_addstr(&uq, p); - p = uq.buf; - } while (read_next_command() != EOF) { const char *v; if (skip_prefix(command_buf.buf, "cat-blob ", &v)) @@ -2398,55 +2393,51 @@ static void file_change_m(const char *p, struct branch *b) command_buf.buf); } - if (!*p) { + if (!*path.buf) { tree_content_replace(&b->branch_tree, &oid, mode, NULL); return; } - tree_content_set(&b->branch_tree, p, &oid, mode, NULL); + tree_content_set(&b->branch_tree, path.buf, &oid, mode, NULL); } static void file_change_d(const char *p, struct branch *b) { - static struct strbuf uq = STRBUF_INIT; + static struct strbuf path = STRBUF_INIT; - strbuf_reset(&uq); - parse_path_eol(&uq, p, "path"); - p = uq.buf; - tree_content_remove(&b->branch_tree, p, NULL, 1); + strbuf_reset(&path); + parse_path_eol(&path, p, "path"); + tree_content_remove(&b->branch_tree, path.buf, NULL, 1); } static void file_change_cr(const char *p, struct branch *b, int rename) { - const char *s, *d; - static struct strbuf s_uq = STRBUF_INIT; - static struct strbuf d_uq = STRBUF_INIT; + static struct strbuf source = STRBUF_INIT; + static struct strbuf dest = STRBUF_INIT; struct tree_entry leaf; - strbuf_reset(&s_uq); - parse_path_space(&s_uq, p, &p, "source"); - s = s_uq.buf; + strbuf_reset(&source); + parse_path_space(&source, p, &p, "source"); if (!p) die("Missing dest: %s", command_buf.buf); - strbuf_reset(&d_uq); - parse_path_eol(&d_uq, p, "dest"); - d = d_uq.buf; + strbuf_reset(&dest); + parse_path_eol(&dest, p, "dest"); memset(&leaf, 0, sizeof(leaf)); if (rename) - tree_content_remove(&b->branch_tree, s, &leaf, 1); + tree_content_remove(&b->branch_tree, source.buf, &leaf, 1); else - tree_content_get(&b->branch_tree, s, &leaf, 1); + tree_content_get(&b->branch_tree, source.buf, &leaf, 1); if (!leaf.versions[1].mode) - die("Path %s not in branch", s); - if (!*d) { /* C "path/to/subdir" "" */ + die("Path %s not in branch", source.buf); + if (!*dest.buf) { /* C "path/to/subdir" "" */ tree_content_replace(&b->branch_tree, &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); return; } - tree_content_set(&b->branch_tree, d, + tree_content_set(&b->branch_tree, dest.buf, &leaf.versions[1].oid, leaf.versions[1].mode, leaf.tree); @@ -3174,7 +3165,7 @@ static void print_ls(int mode, const unsigned char *hash, const char *path) static void parse_ls(const char *p, struct branch *b) { - static struct strbuf uq = STRBUF_INIT; + static struct strbuf path = STRBUF_INIT; struct tree_entry *root = NULL; struct tree_entry leaf = {NULL}; @@ -3191,10 +3182,9 @@ static void parse_ls(const char *p, struct branch *b) root->versions[1].mode = S_IFDIR; load_tree(root); } - strbuf_reset(&uq); - parse_path_eol(&uq, p, "path"); - p = uq.buf; - tree_content_get(root, p, &leaf, 1); + strbuf_reset(&path); + parse_path_eol(&path, p, "path"); + tree_content_get(root, path.buf, &leaf, 1); /* * A directory in preparation would have a sha1 of zero * until it is saved. Save, for simplicity. @@ -3202,7 +3192,7 @@ static void parse_ls(const char *p, struct branch *b) if (S_ISDIR(leaf.versions[1].mode)) store_tree(&leaf); - print_ls(leaf.versions[1].mode, leaf.versions[1].oid.hash, p); + print_ls(leaf.versions[1].mode, leaf.versions[1].oid.hash, path.buf); if (leaf.tree) release_tree_content_recursive(leaf.tree); if (!b || root != &b->branch_tree) From patchwork Mon Apr 1 09:03:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612632 Received: from mail-40136.proton.ch (mail-40136.proton.ch [185.70.40.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 860FDDDD9 for ; Mon, 1 Apr 2024 09:03:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.40.136 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962206; cv=none; b=qUJmDIF7vSmSGz3MX3NaDthSOhxVEenn38FuPlWUP4CAJg1PYxzUw84TY20/0lN/DgkNTJYbmHYuWMJVZV9V/ZEqThA/CKFzFcWkY5jB0/fLw3+tCFrKWxBw+CsN9x242jDTLuaAkNgk85aIlSxRD9pSIUt0SVJn2OLxjIIIF1M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962206; c=relaxed/simple; bh=lNk1VZ0eoSs3tItjU/+t7XUglRL8rOEodzakiZk8ffE=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dwNP0wGRjS1CaR046q08RhYephyueko9TP2C7DVAXmXaFcrDYHjtJpp1X3mc6KyzLwcuORGrahfr+fNWTTNwefuVRKI0OxF6bzrx+NXuYj0oAotXeF2FA7bejLUjmdQ5Zx1oJFOqHss6u2JDckEqhsTFKMnLThkVI0shiAsG0jE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=Qzv6fBrr; arc=none smtp.client-ip=185.70.40.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="Qzv6fBrr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962201; x=1712221401; bh=5YcOISS7WoymSRdDQr1Q458cauXRvOuVmowxf0obNmc=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=Qzv6fBrrrfZfZi9zFYyZSEga/WBIGhyX3ZxuVVcTxee6Z7oBBNdfLW8/5XIsUXDYJ X/lSu8Utpa3dL6CC3llW9UetALWOq/Us6fe6ePoNobjgW6hWuXR4iL4YNo9TzpCqVt B338lLw9mUKL4wuQJj9wyN/Zrw0uUVkO+0ECwanTN7Hd3lR6+u0DEzMjqESoOkZ2kb wdGy1VZd62ILlBX8UhS0PzFgz7vQl06xGBCB6wRl9sE9aW2RPYZqZQ+U4TtZBEEnYl 5a+wARDCcKrj7pucFZ2OqM2aEi46b3u6kjEHVkNF4Wqam6z3UzvHeUYD81fTMu91my kNVaJ6mwfEGeg== Date: Mon, 01 Apr 2024 09:03:17 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 3/8] fast-import: allow unquoted empty path for root Message-ID: <893bbf5e734903382c22893121252ed49b3c7a69.1711960552.git.thalia@archibald.dev> In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Ever since filerename was added in f39a946a1f (Support wholesale directory renames in fast-import, 2007-07-09) and filecopy in b6f3481bb4 (Teach fast-import to recursively copy files/directories, 2007-07-15), both have produced an error when the destination path is empty. Later, when support for targeting the root directory with an empty string was added in 2794ad5244 (fast-import: Allow filemodify to set the root, 2010-10-10), this had the effect of allowing the quoted empty string (`""`), but forbidding its unquoted variant (``). This seems to have been intended as simple data validation for parsing two paths, rather than a syntax restriction, because it was not extended to the other operations. All other occurrences of paths (in filemodify, filedelete, the source of filecopy and filerename, and ls) allow both. For most of this feature's lifetime, the documentation has not prescribed the use of quoted empty strings. In e5959106d6 (Documentation/fast-import: put explanation of M 040000 "" in context, 2011-01-15), its documentation was changed from “`` may also be an empty string (`""`) to specify the root of the tree” to “The root of the tree can be represented by an empty string as ``”. Thus, we can assume that some front-ends have depended on this behavior. Remove this restriction for the destination paths of filecopy and filerename and change tests targeting the root to test `""` and ``. Signed-off-by: Thalia Archibald --- builtin/fast-import.c | 5 +- t/t9300-fast-import.sh | 363 +++++++++++++++++++++-------------------- 2 files changed, 191 insertions(+), 177 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index fad9324e59..58cc8d4ede 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2416,11 +2416,8 @@ static void file_change_cr(const char *p, struct branch *b, int rename) struct tree_entry leaf; strbuf_reset(&source); - parse_path_space(&source, p, &p, "source"); - - if (!p) - die("Missing dest: %s", command_buf.buf); strbuf_reset(&dest); + parse_path_space(&source, p, &p, "source"); parse_path_eol(&dest, p, "dest"); memset(&leaf, 0, sizeof(leaf)); diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 0fb5612b07..635b1b9af7 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -1059,30 +1059,33 @@ test_expect_success 'M: rename subdirectory to new subdirectory' ' compare_diff_raw expect actual ' -test_expect_success 'M: rename root to subdirectory' ' - cat >input <<-INPUT_END && - commit refs/heads/M4 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <input <<-INPUT_END && + commit refs/heads/M4 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <expect <<-EOF && - :100644 100644 $oldf $oldf R100 file2/oldf sub/file2/oldf - :100755 100755 $f4id $f4id R100 file4 sub/file4 - :100755 100755 $newf $newf R100 i/am/new/to/you sub/i/am/new/to/you - :100755 100755 $f6id $f6id R100 newdir/exec.sh sub/newdir/exec.sh - :100644 100644 $f5id $f5id R100 newdir/interesting sub/newdir/interesting - EOF - git fast-import actual && - compare_diff_raw expect actual -' + cat >expect <<-EOF && + :100644 100644 $oldf $oldf R100 file2/oldf sub/file2/oldf + :100755 100755 $f4id $f4id R100 file4 sub/file4 + :100755 100755 $newf $newf R100 i/am/new/to/you sub/i/am/new/to/you + :100755 100755 $f6id $f6id R100 newdir/exec.sh sub/newdir/exec.sh + :100644 100644 $f5id $f5id R100 newdir/interesting sub/newdir/interesting + EOF + git fast-import actual && + compare_diff_raw expect actual + ' +done ### ### series N @@ -1259,49 +1262,52 @@ test_expect_success PIPE 'N: empty directory reads as missing' ' test_cmp expect actual ' -test_expect_success 'N: copy root directory by tree hash' ' - cat >expect <<-EOF && - :100755 000000 $newf $zero D file3/newf - :100644 000000 $oldf $zero D file3/oldf - EOF - root=$(git rev-parse refs/heads/branch^0^{tree}) && - cat >input <<-INPUT_END && - commit refs/heads/N6 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <expect <<-EOF && + :100755 000000 $newf $zero D file3/newf + :100644 000000 $oldf $zero D file3/oldf + EOF + root_tree=$(git rev-parse refs/heads/branch^0^{tree}) && + cat >input <<-INPUT_END && + commit refs/heads/N6 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <actual && - compare_diff_raw expect actual -' + from refs/heads/branch^0 + M 040000 $root_tree '"$root"' + INPUT_END + git fast-import actual && + compare_diff_raw expect actual + ' -test_expect_success 'N: copy root by path' ' - cat >expect <<-EOF && - :100755 100755 $newf $newf C100 file2/newf oldroot/file2/newf - :100644 100644 $oldf $oldf C100 file2/oldf oldroot/file2/oldf - :100755 100755 $f4id $f4id C100 file4 oldroot/file4 - :100755 100755 $f6id $f6id C100 newdir/exec.sh oldroot/newdir/exec.sh - :100644 100644 $f5id $f5id C100 newdir/interesting oldroot/newdir/interesting - EOF - cat >input <<-INPUT_END && - commit refs/heads/N-copy-root-path - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <expect <<-EOF && + :100755 100755 $newf $newf C100 file2/newf oldroot/file2/newf + :100644 100644 $oldf $oldf C100 file2/oldf oldroot/file2/oldf + :100755 100755 $f4id $f4id C100 file4 oldroot/file4 + :100755 100755 $f6id $f6id C100 newdir/exec.sh oldroot/newdir/exec.sh + :100644 100644 $f5id $f5id C100 newdir/interesting oldroot/newdir/interesting + EOF + cat >input <<-INPUT_END && + commit refs/heads/N-copy-root-path + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <actual && - compare_diff_raw expect actual -' + from refs/heads/branch^0 + C '"$root"' oldroot + INPUT_END + git fast-import actual && + compare_diff_raw expect actual + ' +done test_expect_success 'N: delete directory by copying' ' cat >expect <<-\EOF && @@ -1431,98 +1437,102 @@ test_expect_success 'N: reject foo/ syntax in ls argument' ' INPUT_END ' -test_expect_success 'N: copy to root by id and modify' ' - echo "hello, world" >expect.foo && - echo hello >expect.bar && - git fast-import <<-SETUP_END && - commit refs/heads/N7 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <expect.foo && + echo hello >expect.bar && + git fast-import <<-SETUP_END && + commit refs/heads/N7 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE - data < $GIT_COMMITTER_DATE + data <actual.foo && - git show N8:foo/bar >actual.bar && - test_cmp expect.foo actual.foo && - test_cmp expect.bar actual.bar -' + M 040000 $tree '"$root"' + M 644 inline foo/foo + data <actual.foo && + git show N8:foo/bar >actual.bar && + test_cmp expect.foo actual.foo && + test_cmp expect.bar actual.bar + ' -test_expect_success 'N: extract subtree' ' - branch=$(git rev-parse --verify refs/heads/branch^{tree}) && - cat >input <<-INPUT_END && - commit refs/heads/N9 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <input <<-INPUT_END && + commit refs/heads/N9 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <expect.baz && - echo hello, world >expect.qux && - git fast-import <<-SETUP_END && - commit refs/heads/N10 - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <expect.baz && + echo hello, world >expect.qux && + git fast-import <<-SETUP_END && + commit refs/heads/N10 + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data < $GIT_COMMITTER_DATE - data < $GIT_COMMITTER_DATE + data <actual.baz && - git show N11:bar/qux >actual.qux && - git show N11:bar/quux >actual.quux && - test_cmp expect.baz actual.baz && - test_cmp expect.qux actual.qux && - test_cmp expect.qux actual.quux' + M 040000 $tree '"$root"' + M 100644 inline foo/bar/qux + data <actual.baz && + git show N11:bar/qux >actual.qux && + git show N11:bar/quux >actual.quux && + test_cmp expect.baz actual.baz && + test_cmp expect.qux actual.qux && + test_cmp expect.qux actual.quux + ' +done ### ### series O @@ -3067,6 +3077,7 @@ test_expect_success 'S: ls with garbage after sha1 must fail' ' # There are two sorts of ways a path can be parsed, depending on whether it is # the last field on the line. Additionally, ls without a has a special # case. Test every occurrence of in the grammar against every error case. +# Paths for the root (empty strings) are tested elsewhere. # # @@ -3314,16 +3325,19 @@ test_path_eol_quoted_fail 'ls (without dataref in commit)' 'ls ' path '' ### # Setup is carried over from series S. -test_expect_success 'T: ls root tree' ' - sed -e "s/Z\$//" >expect <<-EOF && - 040000 tree $(git rev-parse S^{tree}) Z - EOF - sha1=$(git rev-parse --verify S) && - git fast-import --import-marks=marks <<-EOF >actual && - ls $sha1 "" - EOF - test_cmp expect actual -' +for root in '""' '' +do + test_expect_success "T: ls root ($root) tree" ' + sed -e "s/Z\$//" >expect <<-EOF && + 040000 tree $(git rev-parse S^{tree}) Z + EOF + sha1=$(git rev-parse --verify S) && + git fast-import --import-marks=marks <<-EOF >actual && + ls $sha1 $root + EOF + test_cmp expect actual + ' +done test_expect_success 'T: delete branch' ' git branch to-delete && @@ -3425,30 +3439,33 @@ test_expect_success 'U: validate directory delete result' ' compare_diff_raw expect actual ' -test_expect_success 'U: filedelete root succeeds' ' - cat >input <<-INPUT_END && - commit refs/heads/U - committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE - data <input <<-INPUT_END && + commit refs/heads/U-delete-root + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data <expect <<-EOF && - :100644 000000 $f7id $ZERO_OID D hello.c - EOF + test_expect_success "U: validate root ($root) delete result" ' + cat >expect <<-EOF && + :100644 000000 $f7id $ZERO_OID D hello.c + EOF - git diff-tree -M -r U^1 U >actual && + git diff-tree -M -r U U-delete-root >actual && - compare_diff_raw expect actual -' + compare_diff_raw expect actual + ' +done ### ### series V (checkpoint) From patchwork Mon Apr 1 09:03:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612633 Received: from mail-4317.proton.ch (mail-4317.proton.ch [185.70.43.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CF6A6DDD9 for ; Mon, 1 Apr 2024 09:03:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962217; cv=none; b=QswQE3ErbUE3OQO6oUEcSTu5HKS+uCXZeBXyafIPpAflvaIs00Atq3r72MSatjNeQilfd0rZJ8ze1kyAhPQkauEnaF1lc+Kly5HW2S4uJA6JhxBchEVHgf9+elWN7ZNMm4cQ4TjN//Dw1Aaq9CVV8aHqSZXSt5VrzLVKyWi0V7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962217; c=relaxed/simple; bh=qd8TlIaNuav2xetbnliokn0aFyCHjRofZL/i5SeubgU=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TUH7MOHYMhwXZHz+0DD/D9GLcUJmsbi2RwsgpXNA/JB2WrstNpdd0Ok0DHB+/Knf1CxZGWxkBYjCqHU0WpxaVvydwwXbLXS+eynuSiB9G+yU/GIcRQp/UkjHiwrpkMknsADrBkttVryI1PzjGZOtrzdkuOPun0PqkB4VfnESBsM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=EiZFdyQN; arc=none smtp.client-ip=185.70.43.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="EiZFdyQN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962212; x=1712221412; bh=qd8TlIaNuav2xetbnliokn0aFyCHjRofZL/i5SeubgU=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=EiZFdyQNiLKdQmnpWbsQjYDMGTdlQHU75kOECGRFxUmWhWCzyJUilDRsTbJ5P59lM 430ja5n1/SIK88rtqIodY4ZQC6C046TPKp4ZCFgF/83b5tiq43Kz5UemfIEBwd5fin yh7j/ovsM8NEo+t/UNCnmofYIcYjeZSbPR2yAmiSI39aQE/P0QWeyxfzosSDuOyLt+ IfHWX/e+2upVeCLxBT198vB5BOZTQbsavJXZ9X0/MtBX3Cg2f/GmtLUdm+cQT53Rr8 oKyIrYBHkyS+u430IWMPrcwWYUE2iXPDIVLoOqkYfY0IyH9JfMW8jV/ubacyQLI9/q sWJwkF6lmbbRA== Date: Mon, 01 Apr 2024 09:03:25 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 4/8] fast-import: remove dead strbuf Message-ID: In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The strbuf in `note_change_n` is to copy the remainder of `p` before potentially invalidating it when reading the next line. However, `p` is not used after that point. It has been unused since the function was created in a8dd2e7d2b (fast-import: Add support for importing commit notes, 2009-10-09) and looks to be a fossil from adapting `file_change_m`. Remove it. Signed-off-by: Thalia Archibald --- builtin/fast-import.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 58cc8d4ede..fc6eeaf89c 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2442,7 +2442,6 @@ static void file_change_cr(const char *p, struct branch *b, int rename) static void note_change_n(const char *p, struct branch *b, unsigned char *old_fanout) { - static struct strbuf uq = STRBUF_INIT; struct object_entry *oe; struct branch *s; struct object_id oid, commit_oid; @@ -2507,10 +2506,6 @@ static void note_change_n(const char *p, struct branch *b, unsigned char *old_fa die("Invalid ref name or SHA1 expression: %s", p); if (inline_data) { - if (p != uq.buf) { - strbuf_addstr(&uq, p); - p = uq.buf; - } read_next_command(); parse_and_store_blob(&last_blob, &oid, 0); } else if (oe) { From patchwork Mon Apr 1 09:03:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612634 Received: from mail-4022.proton.ch (mail-4022.proton.ch [185.70.40.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C18A0DDD9 for ; Mon, 1 Apr 2024 09:03:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.40.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962225; cv=none; b=WQvXU76ua8qmPuVofjc9xcNMH+/kwEoyTFfGxYISjyNn9g/t3h4Qp2dKsoRJGLXClDN0ykmOzDsap617hSu/eCfRRca276aZmNStM5rgMwPEWY4AsGnxmPgbGdTGC373goi2uWgHBGRSFSf2tew/KDu4WHi+9rU/zGfHfp/+FMQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962225; c=relaxed/simple; bh=WPzqEvQpU4C2O5x6yCuxGCvax9aBUfOqE3w3ExSwJHg=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=m0vbA15pUdMRYajcw7HDH+/lOrtJmywvW5YF0ADvJJqXCiij4XL7jZMYWueXHQhz5MUy1SImB/Es3EEbzY5qe29n1g9mvlMis72jXKVZwOgh+PDzKZ028cRwYhFLwjGsuUHLC+X+JfxCAXfVUoHN9HGAOj+qfdtqgTiTOOgbyU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=s9KQJh+c; arc=none smtp.client-ip=185.70.40.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="s9KQJh+c" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962221; x=1712221421; bh=N8XgjHlZHmADcp4IaJMk7NLtAcvIzKo5zzwBmK4XP6I=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=s9KQJh+c+h+iZxDvyGAJYnOV45vV9oN27UY8/Tox1EMNsUJgkSMYM+pd+2ziEmpcZ iv/QpHPTW7fZNH+ECYTAkR8bYUC8ckLv+juOUQUiuIU1WObdb+/ocpxRLvdehkn6Er hVITK4dvDllHRmFZl1BpfC19A320h91pJP0xSxejUKbQ9hRaaIdNVwPKYklK4wkX2Y Ny5PE0kTb+Fq0LPeDAGBTvi6CIzTphMv2NduVhfC0Rh6ZG61IUkqojfM7BQfs5Ae+e z5vajwDsAPJkujQmvduRmIhK82wx+i5KLpyKiDvFqjzM75E1YR5PGP7MqYVuT81qSE t9gbYOJSZgGRw== Date: Mon, 01 Apr 2024 09:03:33 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 5/8] fast-import: improve documentation for unquoted paths Message-ID: <1f34b632d72b0b04d22da54b8eac1520e262620a.1711960552.git.thalia@archibald.dev> In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 It describes what cannot be in an unquoted path, but not what it is. Reframe it as a definition of unquoted paths. The requirement that it not start with `"` is the core element that implies the rest. The restriction that the source paths of filecopy and filerename cannot contain SP is only stated in their respective sections. Restate it in the section. Signed-off-by: Thalia Archibald --- Documentation/git-fast-import.txt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index b2607366b9..f26d7a8571 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -630,18 +630,23 @@ in octal. Git only supports the following modes: In both formats `` is the complete path of the file to be added (if not already existing) or modified (if already existing). -A `` string must use UNIX-style directory separators (forward -slash `/`), may contain any byte other than `LF`, and must not -start with double quote (`"`). +A `` can be written as unquoted bytes or a C-style quoted string: -A path can use C-style string quoting; this is accepted in all cases -and mandatory if the filename starts with double quote or contains -`LF`. In C-style quoting, the complete name should be surrounded with +When a `` does not start with double quote (`"`), it is an +unquoted string and is parsed as literal bytes without any escape +sequences. However, if the filename contains `LF` or starts with double +quote, it must be written as a quoted string. Additionally, the source +`` in `filecopy` or `filerename` must be quoted if it contains SP. + +A `` can use C-style string quoting; this is accepted in all cases +and mandatory in the cases where the filename cannot be represented as +an unquoted string. In C-style quoting, the complete name should be surrounded with double quotes, and any `LF`, backslash, or double quote characters must be escaped by preceding them with a backslash (e.g., `"path/with\n, \\ and \" in it"`). -The value of `` must be in canonical form. That is it must not: +A `` must use UNIX-style directory separators (forward slash `/`) +and must be in canonical form. That is it must not: * contain an empty directory component (e.g. `foo//bar` is invalid), * end with a directory separator (e.g. `foo/` is invalid), From patchwork Mon Apr 1 09:03:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612635 Received: from mail-4323.proton.ch (mail-4323.proton.ch [185.70.43.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62F6223AD for ; Mon, 1 Apr 2024 09:03:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.23 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962239; cv=none; b=M8Lk6hMDbvu44/7+YSVnadaAD7/GiyLiLNkJ1XbSw+mq1aZKbFSrWA1Xh9ZHkVVPmQvxN9A1/bSA7wHJ9skUQZZq/y1KBEgLH3ck1HQZDjtYoIDHqET5mq8qxcqBqj8Z04CzbZnm+wWsObdD4D2M2mQj4L8KUMNzO9aw5knOn+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962239; c=relaxed/simple; bh=RULk3FuWOcXjpjRjWyi//9PdpEVbGX8v1RZeFtgUiQ4=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mmElaIPx5JHQ0GkcSaOEy+8TApdWEn0wKP4WR3kNdg5+0lziNlwQWiNFoyzmPxeN7EMBr+n/Btv6ace3ZWA3xH52wPMPgWycliKq3yqVLYskFUdeVFggllka8IF9dr0D1YWWZS7YTi+3OHvB1szsl9tK0yeGkUbGj31unWwbxiU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=Ks75bcGG; arc=none smtp.client-ip=185.70.43.23 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="Ks75bcGG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962230; x=1712221430; bh=EJX6m+m9j7rw3DbT12K6UuCwOLwHBDsscJdzur9bYHs=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=Ks75bcGGQyIIvP38sX93Eyq/nhPoIZ0Z+k0dVoY1cfM7OW4paf3k2ndABaax+WVtX PwJrfg14ypAW2Xn1Pv82+wrulYrxEhxGGijmQmyluvN16yAY9TTbVEsb9JngJoIYiQ 0bndT+kv0X5Qct9Zf8efD4/3bKGcctVEtqlJ8yeiJdb8vR+MaRKfc2CJuvwCSSWDkU cQ8pv+ayX/8O31vu0bVcp4mxR3v7L9il/xzOfp+c0P1VrqlbeBZP/3/B6HQt6qhniQ J1VBH+mJ2miSydTqhrrAG8Z6PnOlk4QlaZCqkUXWCO5mTsbKd6QdJYJRJ1wB8fxrMe gPkTfICs0UOZw== Date: Mon, 01 Apr 2024 09:03:42 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 6/8] fast-import: document C-style escapes for paths Message-ID: <82a4da68afbc92925ac716a9b098f1a79a3b2ab5.1711960552.git.thalia@archibald.dev> In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Simply saying “C-style” string quoting is imprecise, as only a subset of C escapes are supported. Document the exact escapes. Signed-off-by: Thalia Archibald --- Documentation/git-fast-import.txt | 12 ++++++++---- t/t9300-fast-import.sh | 10 ++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index f26d7a8571..db53b50268 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -640,10 +640,14 @@ quote, it must be written as a quoted string. Additionally, the source A `` can use C-style string quoting; this is accepted in all cases and mandatory in the cases where the filename cannot be represented as -an unquoted string. In C-style quoting, the complete name should be surrounded with -double quotes, and any `LF`, backslash, or double quote characters -must be escaped by preceding them with a backslash (e.g., -`"path/with\n, \\ and \" in it"`). +an unquoted string. In C-style quoting, the complete filename is +surrounded with double quote (`"`) and certain characters must be +escaped by preceding them with a backslash: `LF` is written as `\n`, +backslash as `\\`, and double quote as `\"`. Some characters may may +optionally be written with escape sequences: `\a` for bell, `\b` for +backspace, `\f` for form feed, `\n` for line feed, `\r` for carriage +return, `\t` for horizontal tab, and `\v` for vertical tab. Any byte can +be written with 3-digit octal codes (e.g., `\033`). A `` must use UNIX-style directory separators (forward slash `/`) and must be in canonical form. That is it must not: diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 635b1b9af7..e10962dffe 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3185,8 +3185,9 @@ test_path_eol_success () { ' } -test_path_eol_success 'quoted spaces' '" hello world.c "' ' hello world.c ' -test_path_eol_success 'unquoted spaces' ' hello world.c ' ' hello world.c ' +test_path_eol_success 'quoted spaces' '" hello world.c "' ' hello world.c ' +test_path_eol_success 'unquoted spaces' ' hello world.c ' ' hello world.c ' +test_path_eol_success 'octal escapes' '"\150\151\056\143"' 'hi.c' # # Valid paths before a space: filecopy (source) and filerename (source). @@ -3250,8 +3251,9 @@ test_path_space_success () { ' } -test_path_space_success 'quoted spaces' '" hello world.c "' ' hello world.c ' -test_path_space_success 'no unquoted spaces' 'hello_world.c' 'hello_world.c' +test_path_space_success 'quoted spaces' '" hello world.c "' ' hello world.c ' +test_path_space_success 'no unquoted spaces' 'hello_world.c' 'hello_world.c' +test_path_space_success 'octal escapes' '"\150\151\056\143"' 'hi.c' # # Test a single commit change with an invalid path. Run it with all occurrences From patchwork Mon Apr 1 09:03:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612636 Received: from mail-4317.proton.ch (mail-4317.proton.ch [185.70.43.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59F04DF4A for ; Mon, 1 Apr 2024 09:03:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962240; cv=none; b=Fnj1MVqTb1CvxTzv+OnHNGs8NtYCQZ0bZOVuU81uS/zKvYUlb7haute/gDl4RsMEy3+YyJwrd4xYg7GkaZgeenK6dcKasj0RFaAHvIqaFNnyPdirEMnR98xk113N+SK6tv4bEezn3wOmLV6FnNLDfdvwdJfP6kd7UopRUsT5R5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962240; c=relaxed/simple; bh=7NsE98hYeiijkvMPS61sXwedLvFOZ9LzDmrEjWY8yHc=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dXko50DZFw7ZtMW3QiUs0EudlXf7nWtuP5KW7zsoPlJPVBdoUZMSf+mTLdEdkAFr5Ex8LAd3eSeuq3W4tshBiNjz6xZmFlY2Kp118NnhTsxEUn1USMYlw8rGQDehOKrrzWwPVWNL2M03muU1Ho6L5DWdhyOvhy+0I+uRwBo6p+I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=qMkqa/dW; arc=none smtp.client-ip=185.70.43.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="qMkqa/dW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962237; x=1712221437; bh=p9i5QU41goC8z573jarcFAXqwBkvjBExzLiu4phrKPk=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=qMkqa/dWuzonxG5o0vcZn4vfoVoIqjDnBw0cC1gfgnyLSLMhosJTh8N1xN5Mo7rgg 86kOidOdmYksD+oVI70AzUFXIurC8l4ucWuPye1T/dEvPp5gG3rcLcn6WhbI3kNytT qIVulqNstRl1P8/PPQusCeXALDWSIUL9+q9CeC2ZzflK1KCFQzRfM3FUSkgOoSEpjk ptNjQhDM7QjRuQG2nrtt90wwWO6YGAQJf59CxeDKuflcSAH97vrXHFLL0LxV+c0sO2 I0XRhW8HXozYDKhbLxZY1TlsHuOqL5ipjtc8L4ThopFb1L4OuiGZ/XXD9ZDhLKSIcK g4xwYSpDUCUvQ== Date: Mon, 01 Apr 2024 09:03:50 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 7/8] fast-import: forbid escaped NUL in paths Message-ID: In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 NUL cannot appear in paths. Even disregarding filesystem path limitations, the tree object format delimits with NUL, so such a path cannot be encoded by Git. When a quoted path is unquoted, it could possibly contain NUL from "\000". Forbid it so it isn't truncated. fast-import still has other issues with NUL, but those will be addressed later. Signed-off-by: Thalia Archibald --- Documentation/git-fast-import.txt | 1 + builtin/fast-import.c | 2 ++ t/t9300-fast-import.sh | 1 + 3 files changed, 4 insertions(+) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index db53b50268..edda30f90c 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -660,6 +660,7 @@ and must be in canonical form. That is it must not: The root of the tree can be represented by an empty string as ``. +`` cannot contain NUL, either literally or escaped as `\000`. It is recommended that `` always be encoded using UTF-8. `filedelete` diff --git a/builtin/fast-import.c b/builtin/fast-import.c index fc6eeaf89c..9d0f53fe04 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2268,6 +2268,8 @@ static void parse_path(struct strbuf *sb, const char *p, const char **endp, int if (*p == '"') { if (unquote_c_style(sb, p, endp)) die("Invalid %s: %s", field, command_buf.buf); + if (strlen(sb->buf) != sb->len) + die("NUL in %s: %s", field, command_buf.buf); } else { if (include_spaces) *endp = p + strlen(p); diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index e10962dffe..794a96df38 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3294,6 +3294,7 @@ test_path_base_fail () { local change="$1" prefix="$2" field="$3" suffix="$4" test_path_fail "$change" 'unclosed " in '"$field" "$prefix" '"hello.c' "$suffix" "Invalid $field" test_path_fail "$change" "invalid escape in quoted $field" "$prefix" '"hello\xff"' "$suffix" "Invalid $field" + test_path_fail "$change" "escaped NUL in quoted $field" "$prefix" '"hello\000"' "$suffix" "NUL in $field" } test_path_eol_quoted_fail () { local change="$1" prefix="$2" field="$3" suffix="$4" From patchwork Mon Apr 1 09:03:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13612637 Received: from mail-4317.proton.ch (mail-4317.proton.ch [185.70.43.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8BD1D101DE for ; Mon, 1 Apr 2024 09:04:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.17 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962248; cv=none; b=Q3WinmYXSpKUCft4HntxrBZc1JsWeJHWI66IohDKrD6vVHG9arZrhUKmJQt589ospTQNXvFJj3SM3GVCTvhuSLg3VZTnDAJcUtDc7xnQ5t0H90KLi4VwN9lmOoxmEXY9vjGlUp4cgdiyt0USJ45zvX5PtItzvat3HahoZ7afVWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1711962248; c=relaxed/simple; bh=lxKQiZeAi091TK8XrXF3SjDYsgforJ8wmqtfVzbX8k4=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lAV88zUVpAhW46W81eFVlNzVtUR6gUPMhS2RMOpq+A14TeYckaNv5HyEbVMI60WZY0ZSw9eXRwnYumikdqET4Iw7e5o+gKVn3TGaiMKR21Ag715azNAcnsPe4AYy9td7mRMZj0dnF1PBD/k1p+CNU4OlwbTS+tMH4y2Qm2zjGLQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev; spf=pass smtp.mailfrom=archibald.dev; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b=NzYV+YU7; arc=none smtp.client-ip=185.70.43.17 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=archibald.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=archibald.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=archibald.dev header.i=@archibald.dev header.b="NzYV+YU7" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1711962243; x=1712221443; bh=LbwfwuG5yvnK2WLJSglf4xuZZDIRNeLFqr+TcKdtjgY=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=NzYV+YU7O95cZuCZbRZ3zg6McqVjQlFFyU+qBZGelIUlsPota9fEkctvVachKkRbs B68jzdpKTpXN0oDBvfMrjMKxOiRL6EeJ9nuHVlc08f0AmTTQuB4KlE9/hAHd6QpTA+ xqHWbv2z9nkE6e2b2atifNWYMUP4D5lGD8COS9eV2yp8wHNtnosfgv5kcLVK5j0Gv4 C7Vb4jjwrs4cF8rTVyP70G4xozcpco3qyaJKnj+hf88f5mD/k7fjL52p2b0u8MyXCj n/Cu2/ZD1H0eJRPBeAovf3H5L5iJUhnH9H4teoFce+B2/06EB3Sg2P2nSHKsenHZT+ sR5n58an6QTHA== Date: Mon, 01 Apr 2024 09:03:58 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Patrick Steinhardt , Elijah Newren , Thalia Archibald Subject: [PATCH v2 8/8] fast-import: make comments more precise Message-ID: In-Reply-To: References: <20240322000304.76810-1-thalia@archibald.dev> Feedback-ID: 63908566:user:proton Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The former is somewhat imprecise. The latter became out of sync with the behavior in e814c39c2f (fast-import: refactor parsing of spaces, 2014-06-18). Signed-off-by: Thalia Archibald --- builtin/fast-import.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 9d0f53fe04..9b66ffd2d0 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2210,7 +2210,7 @@ static int parse_mapped_oid_hex(const char *hex, struct object_id *oid, const ch * * idnum ::= ':' bigint; * - * Return the first character after the value in *endptr. + * Update *endptr to point to the first character after the value. * * Complain if the following character is not what is expected, * either a space or end of the string. @@ -2243,8 +2243,8 @@ static uintmax_t parse_mark_ref_eol(const char *p) } /* - * Parse the mark reference, demanding a trailing space. Return a - * pointer to the space. + * Parse the mark reference, demanding a trailing space. Update *p to + * point to the first character after the space. */ static uintmax_t parse_mark_ref_space(const char **p) {