diff mbox series

[2/2] fsck --name-objects: be more careful parsing generation numbers

Message ID 03efb76b31e46ffe340fe0c6ab5fc4d804b2c273.1612980090.git.gitgitgadget@gmail.com (mailing list archive)
State Accepted
Commit e89f89361cd7b706858eb22a6cf3d59d31a00acf
Headers show
Series Fix fsck --name-objects bug | expand

Commit Message

Johannes Schindelin Feb. 10, 2021, 6:01 p.m. UTC
From: Johannes Schindelin <johannes.schindelin@gmx.de>

In 7b35efd734e (fsck_walk(): optionally name objects on the go,
2016-07-17), the `fsck` machinery learned to optionally name the
objects, so that it is easier to see what part of the repository is in a
bad shape, say, when objects are missing.

To save on complexity, this machinery uses a parser to determine the
name of a parent given a commit's name: any `~<n>` suffix is parsed and
the parent's name is formed from the prefix together with `~<n+1>`.

However, this parser has a bug: if it finds a suffix `<n>` that is _not_
`~<n>`, it will mistake the empty string for the prefix and `<n>` for
the generation number. In other words, it will generate a name of the
form `~<bogus-number>`.

Let's fix this.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fsck.c          |  5 +++++
 t/t1450-fsck.sh | 10 ++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

Comments

Junio C Hamano Feb. 10, 2021, 8:38 p.m. UTC | #1
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> In 7b35efd734e (fsck_walk(): optionally name objects on the go,
> 2016-07-17), the `fsck` machinery learned to optionally name the
> objects, so that it is easier to see what part of the repository is in a
> bad shape, say, when objects are missing.
>
> To save on complexity, this machinery uses a parser to determine the
> name of a parent given a commit's name: any `~<n>` suffix is parsed and
> the parent's name is formed from the prefix together with `~<n+1>`.
>
> However, this parser has a bug: if it finds a suffix `<n>` that is _not_
> `~<n>`, it will mistake the empty string for the prefix and `<n>` for
> the generation number. In other words, it will generate a name of the
> form `~<bogus-number>`.
>
> Let's fix this.

Thanks; will queue.

>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>  fsck.c          |  5 +++++
>  t/t1450-fsck.sh | 10 ++++++----
>  2 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/fsck.c b/fsck.c
> index 73f30773f28a..83d727c6fe33 100644
> --- a/fsck.c
> +++ b/fsck.c
> @@ -461,6 +461,11 @@ static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
>  				generation += power * (name[--len] - '0');
>  			if (power > 1 && len && name[len - 1] == '~')
>  				name_prefix_len = len - 1;
> +			else {
> +				/* Maybe a non-first parent, e.g. HEAD^2 */
> +				generation = 0;
> +				name_prefix_len = len;
> +			}
>  		}
>  	}
>  
> diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
> index 779f700ac4a0..bfa3588f37ab 100755
> --- a/t/t1450-fsck.sh
> +++ b/t/t1450-fsck.sh
> @@ -607,13 +607,15 @@ test_expect_success 'fsck --name-objects' '
>  	git init name-objects &&
>  	(
>  		cd name-objects &&
> +		git config core.logAllRefUpdates false &&
>  		test_commit julius caesar.t &&
> -		test_commit augustus &&
> -		test_commit caesar &&
> +		test_commit augustus44 &&
> +		test_commit caesar  &&
>  		remove_object $(git rev-parse julius:caesar.t) &&
> -		test_must_fail git fsck --name-objects >out &&
>  		tree=$(git rev-parse --verify julius:) &&
> -		test_i18ngrep "$tree (refs/tags/julius:" out
> +		git tag -d julius &&
> +		test_must_fail git fsck --name-objects >out &&
> +		test_i18ngrep "$tree (refs/tags/augustus44\\^:" out
>  	)
>  '
diff mbox series

Patch

diff --git a/fsck.c b/fsck.c
index 73f30773f28a..83d727c6fe33 100644
--- a/fsck.c
+++ b/fsck.c
@@ -461,6 +461,11 @@  static int fsck_walk_commit(struct commit *commit, void *data, struct fsck_optio
 				generation += power * (name[--len] - '0');
 			if (power > 1 && len && name[len - 1] == '~')
 				name_prefix_len = len - 1;
+			else {
+				/* Maybe a non-first parent, e.g. HEAD^2 */
+				generation = 0;
+				name_prefix_len = len;
+			}
 		}
 	}
 
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 779f700ac4a0..bfa3588f37ab 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -607,13 +607,15 @@  test_expect_success 'fsck --name-objects' '
 	git init name-objects &&
 	(
 		cd name-objects &&
+		git config core.logAllRefUpdates false &&
 		test_commit julius caesar.t &&
-		test_commit augustus &&
-		test_commit caesar &&
+		test_commit augustus44 &&
+		test_commit caesar  &&
 		remove_object $(git rev-parse julius:caesar.t) &&
-		test_must_fail git fsck --name-objects >out &&
 		tree=$(git rev-parse --verify julius:) &&
-		test_i18ngrep "$tree (refs/tags/julius:" out
+		git tag -d julius &&
+		test_must_fail git fsck --name-objects >out &&
+		test_i18ngrep "$tree (refs/tags/augustus44\\^:" out
 	)
 '