From patchwork Fri Apr 12 08:02:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627127 Received: from mail-41103.protonmail.ch (mail-41103.protonmail.ch [185.70.41.103]) (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 16F8A1CAA1 for ; Fri, 12 Apr 2024 08:11:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.41.103 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909519; cv=none; b=EGFawFEwfyj66usEIVvQK42q8dnCETtTDei3RR6lL6LQDa/WGKnsqqI4JqtD9VDMy7Uyb0X0X49cxRYAlG7XKObQjmUJzaVf9E8W6qsz1n7Wk30UgTHDbPy+bn2VejPEIRjos7j45kiEN4/9jf76cmS96i9uoOEvaCcPOIFdixA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909519; c=relaxed/simple; bh=acg6uErMN+6ZvUrywvbmTO9QG4lfIFJFCdqgvY98wpM=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=f2EROSgNbaI9AOZBRJeadx4mcUFzTooGtt/BmcsVN9htoyFX/2ISBfu+FgSP0k+Caf8GkC+r/1/fcXsbhqyam2GlBHPzzo14Dc3aq/lU+0F4mXKi9joqWd6FV/DUF/m5xNW97BkS4eMWVZud6IYRCmeGIEHL9nZNIxey7X26iuU= 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=MJH4rEss; arc=none smtp.client-ip=185.70.41.103 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="MJH4rEss" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712908981; x=1713168181; bh=tiGSRuofedbARXrF5142zIgTsD3QEIWWMPyAPNGtgnw=; 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=MJH4rEssiyuTIjFTWdSCivJR26cH1mm/GMyeETdKm2/FdDxrFD9ZqERiXF6eetB9A bak+PW+0fBBJnkxbR02AktieSIh/95xyMsOnd0WP2gBaDhrVc+LChZEvJQj0Qea95U TZnDjqe0wL3lj3HKE8rcQk9j/xIlqsAnKbeHERX46EEUgm+1lGTLJOKMV3fe+pshwn RHBfeupyeQbEZ0T0S1a4b4DCRezjeQaHyHe8Mpe8m9Z2tlM7Hnjl1ZJZv6gZVQcqzq ao86pAV/jEoxjMnMtj4MGd2OIjOX43q5DPz1q9rQXchpegooQLhSrD/4FDkHq38k9v FcXgUm1WJR+aA== Date: Fri, 12 Apr 2024 08:02:56 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 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 | 104 ++++++++++------- t/t9300-fast-import.sh | 258 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 318 insertions(+), 44 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 782bda007c..ce9231afe6 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2258,10 +2258,56 @@ 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 = strchrnul(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 +2345,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 +2410,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 +3176,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 +3193,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..de2f1304e8 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 Fri Apr 12 08:03:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627094 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 1C6234EB31 for ; Fri, 12 Apr 2024 08:03:15 +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=1712909001; cv=none; b=XUprvosGcafhBX7GnxRwk3Yol+spFkNCSm53ZhWVYtdcHyFymuLSSTeVOjecTX3z/eUbwoDwrGx4zW7R0iSHsH+jLfgIAY3MzxYi9pnA/cD8x6SWhzBUhVHfX+/jmfLFFNZOmUzzse5LcSfCFm8UfXo0YiTu17DQfmAz0EsDerU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909001; c=relaxed/simple; bh=pxxmm3bxzfAIUPV62gpv+wcSDBxWNsruE3jxTSTps7A=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XPTwhaHzEY5Yo0T12kDqWNQ54XIjqyqIsG6z+XLSYHMMVqVwJcKSnUB/GRqSPR2BZOQiscwBa9i1SBKzIyRPgLzS+tAwC5La4o92lR+4MClEeESOCpC7nGOgve2eE+tuZ/cM1eYUgS1trGs6kvcbSxRcTmSw1N5py5buMJj3TiE= 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=IdSStasH; 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="IdSStasH" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712908990; x=1713168190; bh=hw2+b6jOE4r+yZIuG8JyvaP6l6clOcSN3si1R7o3CPs=; 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=IdSStasHDSp/JhjcqsXtbwl+XN+zqMl1GnlQh2UIDXgXbf7QTG2BvMKIiz4lCLprd Xosr9ompm7BvPFL+k5lCSJlCsphc4yu/ezpPsnX6J/FuO6QGCaSGDTtNRtSP+J0Oqf VtDp1zS4INf4GdcDBjKR2Rw2uXbeorRX9ur6ve0DaOAfgf2gAx0rzZYj01+FP0TFAP JPF4TlBiXOL5C4fwY3J0uXh6fcQsXbaHskqidXqB3xe/z5HJbCKWbJhZuiyuUEN1D3 i6fkaAUZ0ZcNODaILv8Ce8DO0NECRVx2vuIYoYsjT9QvwZyBas9X169eJDJVdL2E6V PDhzbSLt0pHBQ== Date: Fri, 12 Apr 2024 08:03:04 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 2/8] fast-import: directly use strbufs for paths Message-ID: <9499f34aae0620a659c054a934bc1caf6700d40a.1712907684.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 ce9231afe6..8f6312fbaf 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2307,7 +2307,7 @@ static void parse_path_space(struct strbuf *sb, const char *p, 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; @@ -2344,13 +2344,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; } @@ -2371,10 +2370,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)) @@ -2400,55 +2395,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); @@ -3176,7 +3167,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}; @@ -3193,10 +3184,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. @@ -3204,7 +3194,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 Fri Apr 12 08:03:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627095 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 C885B4EB31 for ; Fri, 12 Apr 2024 08:03:27 +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=1712909013; cv=none; b=ZK4ciyRvkYW3AmitJyRrtd8mYl0Sb9xKBWKwJe5EGQvfVjpMkBzBCyva8bE4y2VSZHvlLEBrz4DyVd9RupEJUJtBTzqxAEIMc4iVMvZj7tqdOBRwd5m2g6kL/XTWXkq3MxDcxJPcHa2HLZDYPNUzsVcPLcrm7XYfUIj2aa912zM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909013; c=relaxed/simple; bh=fk5tBKXogeeNxOI+BpgSFWAM/0UrPKM7HTHjbMaUHpE=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZnH7MuEMtRYNX7P26qX+MftKAcHHkMwo2YCySQWbqN86EDDlwADoAM9xM4OljE8vnrBXdySFyDJpY9xrhL/LWiFBYtoIvOqPlFyrq6pFKb+gcWWfl0/OF7Ec6GO1N3oTHgOhQ9Knm+lyR9QV5P6uODLlTqkEnw7EdB/uKGOKCGM= 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=AOemAehz; 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="AOemAehz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712909002; x=1713168202; bh=thgXpuQLhlSeELSlEyv+Jgf9YztW5j9Uj1Ak+zKfWV4=; 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=AOemAehzS3E9SH9UhmyQOQfGjQcn2+2qePnuLIrTzT+AEZFXpyfXANYWFC5TPBIm8 DHtgkSm8PTLRo0ySsj45Lk+jT9fmMg882ALvkXxduXelPTw6JO21F8T2ZPnig7qgTT KHnhBhP1KzTj9r8VeRkjuV2sn7iSGrWvrRMdB7R5UkBXMXhFdDewjD6xOECpNltUrU QXwjgN5AIGHSPQ2gKqf+FdZZdO0ICRj5b1L/ZwjtLAfXEuPR0cqfCWBGUZzMLVvScp fm26B9Jtgy4niXzPyoOUSJeMFguf1l8sAQcGvy20E0gAK34vJiRkPv9Ms1lyyMriX2 dwX815lvPBeNg== Date: Fri, 12 Apr 2024 08:03:13 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 3/8] fast-import: allow unquoted empty path for root Message-ID: <9b1e6b80f50180d213284849db53fecfdb1ebf3c.1712907684.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 should 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 | 3 - t/t9300-fast-import.sh | 363 +++++++++++++++++++++-------------------- 2 files changed, 190 insertions(+), 176 deletions(-) diff --git a/builtin/fast-import.c b/builtin/fast-import.c index 8f6312fbaf..0da7e8a5a5 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2419,9 +2419,6 @@ static void file_change_cr(const char *p, struct branch *b, int rename) strbuf_reset(&source); parse_path_space(&source, p, &p, "source"); - - if (!*p) - die("Missing dest: %s", command_buf.buf); strbuf_reset(&dest); parse_path_eol(&dest, p, "dest"); diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index de2f1304e8..13f98e6688 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. # # @@ -3321,16 +3332,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 && @@ -3432,30 +3446,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 Fri Apr 12 08:03:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627096 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 7A3D54AEE3 for ; Fri, 12 Apr 2024 08:03:37 +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=1712909022; cv=none; b=Ibw7Nep3q5qHh2wfAHshQoZqxdfyA/D3Fwzt7agEy7nJoHgCwOkJqy5Dak8d7Vs7NDbDiaFF8GWm7n7SaFuV26NT/6w2saUWKPp+s4N6yrciYTStZpHnp/XA1Z4aS2kaYOoPX1+iI11uTb0BKflwJti0iR2p6q8CYbr3Mw4uIPE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909022; c=relaxed/simple; bh=ck3BFtd1ltyhi5GaxmtS2VzFLBxzlWURVPuIGQGM+5c=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tjaATn2Z2S5lPrHZt7qqVJIlH46k1C0xpnKIRPA7MB49oZzYmYP27lszNeafhjB2ZqFcWmr8XnDhJARj2OMsHmudm/NAhanZvXXXG+0KzEQXTbhx+gchdYZV1aULIY3jsOM0J+9OzOW5A3LBM400lFT3BnaCgVfTJUbu/cHlE0Q= 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=V4pB4cdm; 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="V4pB4cdm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712909007; x=1713168207; bh=ck3BFtd1ltyhi5GaxmtS2VzFLBxzlWURVPuIGQGM+5c=; 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=V4pB4cdmxN5FYHKdreujSOxqfZcKJ/d15sqD407dsQt48AoeZBGSATRQ9zt5LrkNv rDqTHjBwgxttU63aNvLD+OOKqY8L8cPPP5Gk2AnJv/KBzYLPQDLmmhIGac5MFQiYH5 8x08nPsDHB8kUZ2+1VZ/MzVojRknZ0LWF+/jBfOGk6weev64NZ6OxdGUS0ZNlerJXK l9KBYtwvwQTJA3+cDEnXBh/pl52gRMJWSxfTRJdQr3qbfF0HMMeitavvcEbIz+yX3y CaC2TcICo6WzTH0cYZ3k4brgFJ9rY/oykrwP9oayicj9pcdicCVfXL/FhLZevZSAH3 5cAbKblJ2JtBw== Date: Fri, 12 Apr 2024 08:03:22 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 4/8] fast-import: remove dead strbuf Message-ID: <1a2b0dc6162c754fa63525c017801b2cf25fead3.1712907684.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 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 0da7e8a5a5..7a398dc975 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2444,7 +2444,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; @@ -2509,10 +2508,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 Fri Apr 12 08:03:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627097 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 AA93B53E26 for ; Fri, 12 Apr 2024 08:03:40 +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=1712909025; cv=none; b=orFsMffpif5cuLop1TtPi82afyTCCsVkwdQJ80G0dA6AzRDIrDylFLs22Eu/fehAnQIvL3n1O2+vgClmQMg4inHftfrJEfT62sBP16wKZdHAc6BE5Buto6w6xTbx4LlUHn9qwJn93BKaT+iUgGV+K6RM/63iHJPZmC7f7FwKkgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909025; c=relaxed/simple; bh=mA0IGHDr4QwxD9W8rUpULBVY+RI3BDSzCtgMfFGWBB4=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sfdAOJ9aDYOxUzg6iHevQuEcKj9kWVjXFJWBQMEaDAAAvrOEWuApdj+QeaLhVfBv+xPx9ul1zj26780PzCD1ToS58JqFG7M2P9PHTw8weksTMKOQWFfN6AtRKz73SciSBshrTf+DPxBZV0GBgDEYqWCXzYX55zA3jKxFc7THooo= 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=gTY8YW3S; 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="gTY8YW3S" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712909016; x=1713168216; bh=L8jIZIyOQXAe8rEhPm5KHRj2e5XKT0YZoFwgpOEWRk4=; 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=gTY8YW3SVFTKsdlzwKiKFwnCGcWQyuXLiqjg754kAyF0xOhfaF3wvOVsL8Aal1ckg kTt4t8kIt2AAnjkVENHOWQltGn/t3daTsPMrvYAPV4BF22KHs7HhllfFJlvVsw45PQ uYNfIS9y7g2ZjQJbJtu2YEyoAlu5q8xB8h5DiNHMOHPv/mQgUUStN/ACft0o4sDNO4 UXE9HgTzZOFFPiGaEMGA0fcMSbKiTilmkMyv0ihixSE/V7XNFWyUsyfUZIpQUcZU+K nhKcFFb0qEkSul9xK1MjA3lnPSX3P6ROdmcoS93tS6pRxKL3YJBqlI6ObwaFCW41wJ v61SkOKUR2PdA== Date: Fri, 12 Apr 2024 08:03:30 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 5/8] fast-import: improve documentation for path quoting 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 It describes what characters cannot be in an unquoted path, but not their semantics. Reframe it as a definition of unquoted paths. From the perspective of the parser, whether it starts with `"` is what defines whether it will parse it as quoted or unquoted. The restrictions on characters in unquoted paths (with starting-", LF, and spaces) are explained in the quoted paragraph. Move it to the unquoted paragraph and reword. 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 | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index b2607366b9..1882758b8a 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -630,18 +630,24 @@ 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 -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"`). +When a `` does not start with a 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 cannot be represented as an unquoted string and must be +quoted. Additionally, the source `` in `filecopy` or `filerename` +must be quoted if it contains SP. -The value of `` must be in canonical form. That is it must not: +When a `` starts with a double quote (`"`), it is a C-style quoted +string, where the complete filename is enclosed in a pair of double +quotes and escape sequences are used. Certain characters must be escaped +by preceding them with a backslash: `LF` is written as `\n`, backslash +as `\\`, and double quote as `\"`. All filenames can be represented as +quoted strings. + +A `` must use UNIX-style directory separators (forward slash `/`) +and its value 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 Fri Apr 12 08:03:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627098 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 78D0E54FA0 for ; Fri, 12 Apr 2024 08:03:47 +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=1712909032; cv=none; b=s/4pqhP4yMMg9eu5Bo9e6vrRsAxm4o4CyVQaBx700Qw+AhYlgBXVLa+AOoWc4brX+Ckq+YfVN+8Ute8ulnOuouhsmeJq5WtKd1YdOL6WNbZFOT6id52i3U10ntrib7Wn82AdVTYeRsu+h28ifLm93lXg5q+USOr0c3JZWcpNNIM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909032; c=relaxed/simple; bh=7xKOVItu/+8PyIgxSMpe2CCS4ftKTouQR7f72k3jCzQ=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=j2oxf1S1Db2bYU/HMi9oNlgHjezxBzUHN8ETU+MC5XhyZYVWITIMJvFhvgXZ+KgEcnFm1bi9A44vQ+6QJZ6ROoBD64BDBoUZssMRR1VFxnwbCyPxHLF6X/aAqgIA6dBsMl0XIqxcsj7zk1alUh7ungyPw+zYRWaDW+bylLOLLTQ= 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=la4QBVoR; 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="la4QBVoR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712909022; x=1713168222; bh=G4hbb5RTa8FsnX1s+q65L8FvP/XusNnsJEuXyUfeBs8=; 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=la4QBVoRCcC1wN78cnHKqISJiUqQ9t2Y26CfgVniB/QSXf0A/Kg/nefQ1du37OX6R dSx/yAPnaarQA5aepIpdGAa2O/RI3SBDL6tT46OP6ec+jOVEoCdG6HGrIQ8mfsGaaj /1XSxmKJG6idkXwmMkI0pzRJ3yGRB3w4fJ6eHSDgTxx1olwh/KCMpQVZRCe6BQogJV VoNHIJB0Y+LQ3t+3XiSGpqnMNPyx2/JcE+P6nDOZ+fbh40Fsk8xQ0Ds9Xn9MFhgHSR S7qi6aOxsyiMqD5vXBBSfsYVk/dm25zU4uIesCLjTe3rjgEv+rOR2zLsfYWYosuieX wiggWPPA6O1TA== Date: Fri, 12 Apr 2024 08:03:38 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 6/8] fast-import: document C-style escapes for paths Message-ID: <4b6017ded8ec434fc6d7ac90964b59e40f6dd561.1712907684.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 | 6 +++++- t/t9300-fast-import.sh | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 1882758b8a..c6082c3b49 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -643,7 +643,11 @@ When a `` starts with a double quote (`"`), it is a C-style quoted string, where the complete filename is enclosed in a pair of double quotes and escape sequences are used. Certain characters must be escaped by preceding them with a backslash: `LF` is written as `\n`, backslash -as `\\`, and double quote as `\"`. All filenames can be represented as +as `\\`, and double quote as `\"`. Some characters 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`). All filenames can be represented as quoted strings. A `` must use UNIX-style directory separators (forward slash `/`) diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 13f98e6688..5cde8f8d01 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3189,8 +3189,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). @@ -3256,8 +3257,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 Fri Apr 12 08:03:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627099 Received: from mail-4018.proton.ch (mail-4018.proton.ch [185.70.40.18]) (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 338C44F613 for ; Fri, 12 Apr 2024 08:04:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.40.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909046; cv=none; b=GUtuF/LB2wypwuO28f0eckPW90SfSnCFHAAXUlJxYTBPw3mil+0LkIJUIXhDOGXA5Xche79y0327LntRoPJMKztfMrkKGp57IrJgWXoV1g+qGaY4NN6Tj+LtKLR1sGFZmdKXrolCIjBgqx5h1ruyVXhZ7rDt+PpSc/OmKABHlIA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909046; c=relaxed/simple; bh=k+pLT4PIYqviTDyYAphQAwEACvBr1m+hE52S9ZgE7Mg=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BizQZEZi8JWvmF2QBgizs7DmyAkepVoEAVeITWlQFHc8lJZLqsUiTCkQbPIfclMtu5jODY5PGchhEoywtXFg6U3d3zCOoMdZSFxC18fG36iZP3iMTEoRVZfvJSEPVtW9c/dwkak3qbMsN++PAJT71BuVAaf6Y9qIBanv3OO/LTs= 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=HRjixYZ4; arc=none smtp.client-ip=185.70.40.18 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="HRjixYZ4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712909032; x=1713168232; bh=Wjx0/vNzkEA8Dge4sHLHtIbHEcUPnEm25eCrjqldGkQ=; 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=HRjixYZ4/sGewhdKvEsLKZ8F8PhjLU0qafI9n9RlB7DG0/Cip+QaYHuLlONH9O7Qe mmK04cpfJxpfoamcqlf1U7LFcYkKwTpI9Dmn12lump8bG4bU4isgFmzdXOKKvnSo4E kCDe2+I9ifOqbZE1DDqzBWiH30tyN/SZE+9aRXmNUhrUDRzeuYMSORN4F16JXzCRrd X3gUB4400gWabnmE0gqoieu/k6v/CluQDuArjBUlofHTpe1U7zO+deh12slFL0sRel cvvfLp161Vzu98ACtlWtDJxk5q4cHVUTtK58VmLOzRLBbfPFRn4m/u0fG1BCHghYwA dwOI2+ddmK5AA== Date: Fri, 12 Apr 2024 08:03:47 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 7/8] fast-import: forbid escaped NUL in paths Message-ID: <5b464f4b014760d0d9ca3413dacaa7e48f22291f.1712907684.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 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 c6082c3b49..8b6dde45f1 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -661,6 +661,7 @@ and its value 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 7a398dc975..98096b6fa7 100644 --- a/builtin/fast-import.c +++ b/builtin/fast-import.c @@ -2269,6 +2269,8 @@ static void parse_path(struct strbuf *sb, const char *p, const char **endp, 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 5cde8f8d01..1e68426852 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3300,6 +3300,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" From patchwork Fri Apr 12 08:03:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thalia Archibald X-Patchwork-Id: 13627100 Received: from mail-4018.proton.ch (mail-4018.proton.ch [185.70.40.18]) (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 9045F50A62 for ; Fri, 12 Apr 2024 08:04:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.40.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909049; cv=none; b=HScN5tXjd9GbXyGOULeuzI6XjGdDb2Xsfm5Y9+ViVUGhtQtyqkT3gbrmJ0UwjwgBZzUdKGgEPg9CFGVIQ0tmKb4iwR4zY8+mk9zA2/KPsoaxbgrbYel+EwU9p1I+JIa8ebcjgFF4EWywxkLtgEymnkyhlMYpEe792ro1YmLVjlM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712909049; c=relaxed/simple; bh=s+KSrfGpa9OJzLKh4Gc7sETgBpDLK6OMh3A+HZM9tSc=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EMOfH9zJvRGUy7ytE7dRrhannYkIEuKGSA9ola1p51J4rI8k9ZxYh4soDV/zs0+umL8qs0MjN19MHfsVfyKEYIe03zOj6lZq5gz3wIsNr4n49Odl5uU6Hv4B3Fomt6B3w65rOY4FYOUc5UgnXog0KUi5zJhbj2afu+1D684SqHU= 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=gEYxJISR; arc=none smtp.client-ip=185.70.40.18 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="gEYxJISR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=archibald.dev; s=protonmail3; t=1712909041; x=1713168241; bh=nNlap/Saz/8xmDFehKd1u6H0Jzz6QfvQuLUSTi4ywVM=; 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=gEYxJISRtZ+ahFW9SQDkFlGBc2cwfXQ78t2oWLimKD25l/wAVFtuRaE/aBYysYoDD f68VgkrlI6d62dRO/KL0K62rCYkCruExMCMejhvokjI3xVKl1Iak3yKBHsVIBXeI+N sr7oLD0crz7oENciRBaVv7NVUWLwTGOnVCOdxNly5hzWkJLXMlWA7ob/zIKxooKbyB ZymWug8HnxqQY0PvF96QjfBYs4asbmt82wQpIznd8+i75wcjDYHfohv+Li8vZmm+WO 8HurjghUT0RgXbWCl/HNsEPis4Eo9iiUfCNVhmWV5oP82R2tswVvs4AxLA/BEWCaFJ DxhJxa3/jXNaQ== Date: Fri, 12 Apr 2024 08:03:55 +0000 To: git@vger.kernel.org From: Thalia Archibald Cc: Junio C Hamano , Patrick Steinhardt , Chris Torek , Elijah Newren , Thalia Archibald Subject: [PATCH v4 8/8] fast-import: make comments more precise Message-ID: <6eb66fce45f16a87fa01e3e38d85c9e32131b0d4.1712907684.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 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 98096b6fa7..fd23a00150 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) {