git@vger.kernel.org list mirror (unofficial, one of many)
 help / color / mirror / Atom feed
* [PATCH 00/14] Hash-independent tests, part 5
@ 2019-08-18 19:16 brian m. carlson
  2019-08-18 19:16 ` [PATCH 01/14] t3201: abstract away SHA-1-specific constants brian m. carlson
                   ` (14 more replies)
  0 siblings, 15 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

This is the fifth series of test fixes for SHA-256 compatibility.  It
consists of 15 patches fixing various tests from t3201 through t4009 and
has only test fixes: no test helper changes are included.

There are approximately 75 remaining test patches (plus some additional
code changes) required for the test suite to pass successfully with
SHA-256, which does not include the patches required to replace SHA-1
near-collisions in tests with actual SHA-256 near-collisions.

brian m. carlson (14):
  t3201: abstract away SHA-1-specific constants
  t3206: abstract away hash size constants
  t3301: abstract away SHA-1-specific constants
  t3305: make hash size independent
  t3306: abstract away SHA-1-specific constants
  t3404: abstract away SHA-1-specific constants
  t3430: avoid hard-coded object IDs
  t3506: make hash independent
  t3600: make hash size independent
  t3800: make hash-size independent
  t3903: abstract away SHA-1-specific constants
  t4000: make hash size independent
  t4002: make hash independent
  t4009: make hash size independent

 t/t3201-branch-contains.sh    |   8 +-
 t/t3206-range-diff.sh         | 227 +++++++++++++++------
 t/t3301-notes.sh              | 140 ++++++++-----
 t/t3305-notes-fanout.sh       |  22 +-
 t/t3306-notes-prune.sh        |  45 ++---
 t/t3404-rebase-interactive.sh |  22 +-
 t/t3430-rebase-merges.sh      |  23 ++-
 t/t3506-cherry-pick-ff.sh     |   8 +-
 t/t3600-rm.sh                 |   4 +-
 t/t3800-mktag.sh              |  49 ++---
 t/t3903-stash.sh              |  32 ++-
 t/t4000-diff-format.sh        |   2 +-
 t/t4002-diff-basic.sh         | 367 ++++++++++++++++++++++++----------
 t/t4009-diff-rename-4.sh      |  19 +-
 14 files changed, 640 insertions(+), 328 deletions(-)


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 01/14] t3201: abstract away SHA-1-specific constants
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 02/14] t3206: abstract away hash size constants brian m. carlson
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3201-branch-contains.sh | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh
index 0ea4fc4694..40251c9f8f 100755
--- a/t/t3201-branch-contains.sh
+++ b/t/t3201-branch-contains.sh
@@ -192,10 +192,10 @@ test_expect_success 'branch --merged with --verbose' '
 	EOF
 	test_cmp expect actual &&
 	git branch --verbose --merged topic >actual &&
-	cat >expect <<-\EOF &&
-	  master c77a0a9 second on master
-	* topic  2c939f4 [ahead 1] foo
-	  zzz    c77a0a9 second on master
+	cat >expect <<-EOF &&
+	  master $(git rev-parse --short master) second on master
+	* topic  $(git rev-parse --short topic ) [ahead 1] foo
+	  zzz    $(git rev-parse --short zzz   ) second on master
 	EOF
 	test_i18ncmp expect actual
 '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 02/14] t3206: abstract away hash size constants
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
  2019-08-18 19:16 ` [PATCH 01/14] t3201: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 03/14] t3301: abstract away SHA-1-specific constants brian m. carlson
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

The various short object IDs in the range-diff output differ between
hash algorithms.  Use test_oid_cache to look up values for both SHA-1
and SHA-256.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3206-range-diff.sh | 227 +++++++++++++++++++++++++++++++-----------
 1 file changed, 167 insertions(+), 60 deletions(-)

diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index ec548654ce..0120f769f1 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -8,17 +8,124 @@ test_description='range-diff tests'
 # harm than good.  We need some real history.
 
 test_expect_success 'setup' '
-	git fast-import < "$TEST_DIRECTORY"/t3206/history.export
+	git fast-import < "$TEST_DIRECTORY"/t3206/history.export &&
+	test_oid_cache <<-EOF
+	# topic
+	t1 sha1:4de457d
+	t2 sha1:fccce22
+	t3 sha1:147e64e
+	t4 sha1:a63e992
+	t1 sha256:b89f8b9
+	t2 sha256:5f12aad
+	t3 sha256:ea8b273
+	t4 sha256:14b7336
+
+	# unmodified
+	u1 sha1:35b9b25
+	u2 sha1:de345ab
+	u3 sha1:9af6654
+	u4 sha1:2901f77
+	u1 sha256:e3731be
+	u2 sha256:14fadf8
+	u3 sha256:736c4bc
+	u4 sha256:673e77d
+
+	# reordered
+	r1 sha1:aca177a
+	r2 sha1:14ad629
+	r3 sha1:ee58208
+	r4 sha1:307b27a
+	r1 sha256:f59d3aa
+	r2 sha256:fb261a8
+	r3 sha256:cb2649b
+	r4 sha256:958577e
+
+	# removed (deleted)
+	d1 sha1:7657159
+	d2 sha1:43d84d3
+	d3 sha1:a740396
+	d1 sha256:e312513
+	d2 sha256:eb19258
+	d3 sha256:1ccb3c1
+
+	# added
+	a1 sha1:2716022
+	a2 sha1:b62accd
+	a3 sha1:df46cfa
+	a4 sha1:3e64548
+	a5 sha1:12b4063
+	a1 sha256:d724f4d
+	a2 sha256:1de7762
+	a3 sha256:e159431
+	a4 sha256:b3e483c
+	a5 sha256:90866a7
+
+	# rebased
+	b1 sha1:cc9c443
+	b2 sha1:c5d9641
+	b3 sha1:28cc2b6
+	b4 sha1:5628ab7
+	b5 sha1:a31b12e
+	b1 sha256:a1a8717
+	b2 sha256:20a5862
+	b3 sha256:587172a
+	b4 sha256:2721c5d
+	b5 sha256:7b57864
+
+	# changed
+	c1 sha1:a4b3333
+	c2 sha1:f51d370
+	c3 sha1:0559556
+	c4 sha1:d966c5c
+	c1 sha256:f8c2b9d
+	c2 sha256:3fb6318
+	c3 sha256:168ab68
+	c4 sha256:3526539
+
+	# changed-message
+	m1 sha1:f686024
+	m2 sha1:4ab067d
+	m3 sha1:b9cb956
+	m4 sha1:8add5f1
+	m1 sha256:31e6281
+	m2 sha256:a06bf1b
+	m3 sha256:82dc654
+	m4 sha256:48470c5
+
+	# renamed
+	n1 sha1:f258d75
+	n2 sha1:017b62d
+	n3 sha1:3ce7af6
+	n4 sha1:1e6226b
+	n1 sha256:ad52114
+	n2 sha256:3b54c8f
+	n3 sha256:3b0a644
+	n4 sha256:e461653
+
+	# added and removed
+	s1 sha1:096b1ba
+	s2 sha1:d92e698
+	s3 sha1:9a1db4d
+	s4 sha1:fea3b5c
+	s1 sha256:a7f9134
+	s2 sha256:b4c2580
+	s3 sha256:1d62aa2
+	s4 sha256:48160e8
+
+	# Empty delimiter (included so lines match neatly)
+	__ sha1:-------
+	__ sha256:-------
+	EOF
 '
 
 test_expect_success 'simple A..B A..C (unmodified)' '
 	git range-diff --no-color master..topic master..unmodified \
 		>actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  35b9b25 s/5/A/
-	2:  fccce22 = 2:  de345ab s/4/A/
-	3:  147e64e = 3:  9af6654 s/11/B/
-	4:  a63e992 = 4:  2901f77 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid u1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid u2) s/4/A/
+	3:  $(test_oid t3) = 3:  $(test_oid u3) s/11/B/
+	4:  $(test_oid t4) = 4:  $(test_oid u4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -38,10 +145,10 @@ test_expect_success 'simple A B C (unmodified)' '
 test_expect_success 'trivial reordering' '
 	git range-diff --no-color master topic reordered >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  aca177a s/5/A/
-	3:  147e64e = 2:  14ad629 s/11/B/
-	4:  a63e992 = 3:  ee58208 s/12/B/
-	2:  fccce22 = 4:  307b27a s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid r1) s/5/A/
+	3:  $(test_oid t3) = 2:  $(test_oid r2) s/11/B/
+	4:  $(test_oid t4) = 3:  $(test_oid r3) s/12/B/
+	2:  $(test_oid t2) = 4:  $(test_oid r4) s/4/A/
 	EOF
 	test_cmp expected actual
 '
@@ -49,10 +156,10 @@ test_expect_success 'trivial reordering' '
 test_expect_success 'removed a commit' '
 	git range-diff --no-color master topic removed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  7657159 s/5/A/
-	2:  fccce22 < -:  ------- s/4/A/
-	3:  147e64e = 2:  43d84d3 s/11/B/
-	4:  a63e992 = 3:  a740396 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid d1) s/5/A/
+	2:  $(test_oid t2) < -:  $(test_oid __) s/4/A/
+	3:  $(test_oid t3) = 2:  $(test_oid d2) s/11/B/
+	4:  $(test_oid t4) = 3:  $(test_oid d3) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -60,11 +167,11 @@ test_expect_success 'removed a commit' '
 test_expect_success 'added a commit' '
 	git range-diff --no-color master topic added >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  2716022 s/5/A/
-	2:  fccce22 = 2:  b62accd s/4/A/
-	-:  ------- > 3:  df46cfa s/6/A/
-	3:  147e64e = 4:  3e64548 s/11/B/
-	4:  a63e992 = 5:  12b4063 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid a1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid a2) s/4/A/
+	-:  $(test_oid __) > 3:  $(test_oid a3) s/6/A/
+	3:  $(test_oid t3) = 4:  $(test_oid a4) s/11/B/
+	4:  $(test_oid t4) = 5:  $(test_oid a5) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -72,10 +179,10 @@ test_expect_success 'added a commit' '
 test_expect_success 'new base, A B C' '
 	git range-diff --no-color master topic rebased >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  cc9c443 s/5/A/
-	2:  fccce22 = 2:  c5d9641 s/4/A/
-	3:  147e64e = 3:  28cc2b6 s/11/B/
-	4:  a63e992 = 4:  5628ab7 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid b1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid b2) s/4/A/
+	3:  $(test_oid t3) = 3:  $(test_oid b3) s/11/B/
+	4:  $(test_oid t4) = 4:  $(test_oid b4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -84,11 +191,11 @@ test_expect_success 'new base, B...C' '
 	# this syntax includes the commits from master!
 	git range-diff --no-color topic...rebased >actual &&
 	cat >expected <<-EOF &&
-	-:  ------- > 1:  a31b12e unrelated
-	1:  4de457d = 2:  cc9c443 s/5/A/
-	2:  fccce22 = 3:  c5d9641 s/4/A/
-	3:  147e64e = 4:  28cc2b6 s/11/B/
-	4:  a63e992 = 5:  5628ab7 s/12/B/
+	-:  $(test_oid __) > 1:  $(test_oid b5) unrelated
+	1:  $(test_oid t1) = 2:  $(test_oid b1) s/5/A/
+	2:  $(test_oid t2) = 3:  $(test_oid b2) s/4/A/
+	3:  $(test_oid t3) = 4:  $(test_oid b3) s/11/B/
+	4:  $(test_oid t4) = 5:  $(test_oid b4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -96,9 +203,9 @@ test_expect_success 'new base, B...C' '
 test_expect_success 'changed commit' '
 	git range-diff --no-color topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
-	2:  fccce22 = 2:  f51d370 s/4/A/
-	3:  147e64e ! 3:  0559556 s/11/B/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
 	    @@ file: A
 	      9
 	      10
@@ -108,7 +215,7 @@ test_expect_success 'changed commit' '
 	      12
 	      13
 	      14
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	    @@ file
 	     @@ file: A
 	      9
@@ -125,10 +232,10 @@ test_expect_success 'changed commit' '
 test_expect_success 'changed commit with --no-patch diff option' '
 	git range-diff --no-color --no-patch topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
-	2:  fccce22 = 2:  f51d370 s/4/A/
-	3:  147e64e ! 3:  0559556 s/11/B/
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -136,16 +243,16 @@ test_expect_success 'changed commit with --no-patch diff option' '
 test_expect_success 'changed commit with --stat diff option' '
 	git range-diff --no-color --stat topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
-	2:  fccce22 = 2:  f51d370 s/4/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
-	3:  147e64e ! 3:  0559556 s/11/B/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
 	EOF
@@ -155,9 +262,9 @@ test_expect_success 'changed commit with --stat diff option' '
 test_expect_success 'changed commit with sm config' '
 	git range-diff --no-color --submodule=log topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
-	2:  fccce22 = 2:  f51d370 s/4/A/
-	3:  147e64e ! 3:  0559556 s/11/B/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
 	    @@ file: A
 	      9
 	      10
@@ -167,7 +274,7 @@ test_expect_success 'changed commit with sm config' '
 	      12
 	      13
 	      14
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	    @@ file
 	     @@ file: A
 	      9
@@ -184,8 +291,8 @@ test_expect_success 'changed commit with sm config' '
 test_expect_success 'renamed file' '
 	git range-diff --no-color --submodule=log topic...renamed-file >actual &&
 	sed s/Z/\ /g >expected <<-EOF &&
-	1:  4de457d = 1:  f258d75 s/5/A/
-	2:  fccce22 ! 2:  017b62d s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid n1) s/5/A/
+	2:  $(test_oid t2) ! 2:  $(test_oid n2) s/4/A/
 	    @@ Metadata
 	    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
 	    Z
@@ -198,7 +305,7 @@ test_expect_success 'renamed file' '
 	    Z@@
 	    Z 1
 	    Z 2
-	3:  147e64e ! 3:  3ce7af6 s/11/B/
+	3:  $(test_oid t3) ! 3:  $(test_oid n3) s/11/B/
 	    @@ Metadata
 	    Z ## Commit message ##
 	    Z    s/11/B/
@@ -210,7 +317,7 @@ test_expect_success 'renamed file' '
 	    Z 8
 	    Z 9
 	    Z 10
-	4:  a63e992 ! 4:  1e6226b s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid n4) s/12/B/
 	    @@ Metadata
 	    Z ## Commit message ##
 	    Z    s/12/B/
@@ -229,8 +336,8 @@ test_expect_success 'renamed file' '
 test_expect_success 'file added and later removed' '
 	git range-diff --no-color --submodule=log topic...added-removed >actual &&
 	sed s/Z/\ /g >expected <<-EOF &&
-	1:  4de457d = 1:  096b1ba s/5/A/
-	2:  fccce22 ! 2:  d92e698 s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid s1) s/5/A/
+	2:  $(test_oid t2) ! 2:  $(test_oid s2) s/4/A/
 	    @@ Metadata
 	    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
 	    Z
@@ -246,7 +353,7 @@ test_expect_success 'file added and later removed' '
 	    Z 7
 	    +
 	    + ## new-file (new) ##
-	3:  147e64e ! 3:  9a1db4d s/11/B/
+	3:  $(test_oid t3) ! 3:  $(test_oid s3) s/11/B/
 	    @@ Metadata
 	    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
 	    Z
@@ -262,7 +369,7 @@ test_expect_success 'file added and later removed' '
 	    Z 14
 	    +
 	    + ## new-file (deleted) ##
-	4:  a63e992 = 4:  fea3b5c s/12/B/
+	4:  $(test_oid t4) = 4:  $(test_oid s4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -275,8 +382,8 @@ test_expect_success 'no commits on one side' '
 test_expect_success 'changed message' '
 	git range-diff --no-color topic...changed-message >actual &&
 	sed s/Z/\ /g >expected <<-EOF &&
-	1:  4de457d = 1:  f686024 s/5/A/
-	2:  fccce22 ! 2:  4ab067d s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid m1) s/5/A/
+	2:  $(test_oid t2) ! 2:  $(test_oid m2) s/4/A/
 	    @@ Metadata
 	    Z ## Commit message ##
 	    Z    s/4/A/
@@ -286,16 +393,16 @@ test_expect_success 'changed message' '
 	    Z ## file ##
 	    Z@@
 	    Z 1
-	3:  147e64e = 3:  b9cb956 s/11/B/
-	4:  a63e992 = 4:  8add5f1 s/12/B/
+	3:  $(test_oid t3) = 3:  $(test_oid m3) s/11/B/
+	4:  $(test_oid t4) = 4:  $(test_oid m4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
 
 test_expect_success 'dual-coloring' '
-	sed -e "s|^:||" >expect <<-\EOF &&
-	:<YELLOW>1:  a4b3333 = 1:  f686024 s/5/A/<RESET>
-	:<RED>2:  f51d370 <RESET><YELLOW>!<RESET><GREEN> 2:  4ab067d<RESET><YELLOW> s/4/A/<RESET>
+	sed -e "s|^:||" >expect <<-EOF &&
+	:<YELLOW>1:  $(test_oid c1) = 1:  $(test_oid m1) s/5/A/<RESET>
+	:<RED>2:  $(test_oid c2) <RESET><YELLOW>!<RESET><GREEN> 2:  $(test_oid m2)<RESET><YELLOW> s/4/A/<RESET>
 	:    <REVERSE><CYAN>@@<RESET> <RESET>Metadata<RESET>
 	:      ## Commit message ##<RESET>
 	:         s/4/A/<RESET>
@@ -305,7 +412,7 @@ test_expect_success 'dual-coloring' '
 	:      ## file ##<RESET>
 	:    <CYAN> @@<RESET>
 	:      1<RESET>
-	:<RED>3:  0559556 <RESET><YELLOW>!<RESET><GREEN> 3:  b9cb956<RESET><YELLOW> s/11/B/<RESET>
+	:<RED>3:  $(test_oid c3) <RESET><YELLOW>!<RESET><GREEN> 3:  $(test_oid m3)<RESET><YELLOW> s/11/B/<RESET>
 	:    <REVERSE><CYAN>@@<RESET> <RESET>file: A<RESET>
 	:      9<RESET>
 	:      10<RESET>
@@ -315,7 +422,7 @@ test_expect_success 'dual-coloring' '
 	:      12<RESET>
 	:      13<RESET>
 	:      14<RESET>
-	:<RED>4:  d966c5c <RESET><YELLOW>!<RESET><GREEN> 4:  8add5f1<RESET><YELLOW> s/12/B/<RESET>
+	:<RED>4:  $(test_oid c4) <RESET><YELLOW>!<RESET><GREEN> 4:  $(test_oid m4)<RESET><YELLOW> s/12/B/<RESET>
 	:    <REVERSE><CYAN>@@<RESET> <RESET>file<RESET>
 	:    <CYAN> @@ file: A<RESET>
 	:      9<RESET>

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 03/14] t3301: abstract away SHA-1-specific constants
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
  2019-08-18 19:16 ` [PATCH 01/14] t3201: abstract away SHA-1-specific constants brian m. carlson
  2019-08-18 19:16 ` [PATCH 02/14] t3206: abstract away hash size constants brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 04/14] t3305: make hash size independent brian m. carlson
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.  Move some invocations of test_commit around so
that we can compute the object IDs for these commits.

Compute several object IDs in the tests instead of using hard-coded
values so that the test works with any hash algorithm.  Since the actual
values are sorted by the object ID of the object being annotated, sort
the expected values accordingly as well.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3301-notes.sh | 140 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 90 insertions(+), 50 deletions(-)

diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 704bbc6541..d3fa298c6a 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -66,8 +66,9 @@ test_expect_success 'show notes entry with %N' '
 '
 
 test_expect_success 'create reflog entry' '
+	ref=$(git rev-parse --short refs/notes/commits) &&
 	cat <<-EOF >expect &&
-		a1d8fa6 refs/notes/commits@{0}: notes: Notes added by '\''git notes add'\''
+		$ref refs/notes/commits@{0}: notes: Notes added by '\''git notes add'\''
 	EOF
 	git reflog show refs/notes/commits >actual &&
 	test_cmp expect actual
@@ -134,8 +135,9 @@ test_expect_success 'can overwrite existing note with "git notes add -f"' '
 '
 
 test_expect_success 'show notes' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 7a4ca6ee52a974a66cbaa78e33214535dff1d691
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:14:13 2005 -0700
 
@@ -152,8 +154,9 @@ test_expect_success 'show notes' '
 test_expect_success 'show multi-line notes' '
 	test_commit 3rd &&
 	MSG="b3${LF}c3c3c3c3${LF}d3d3d3" git notes add &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-multiline <<-EOF &&
-		commit d07d62e5208f22eb5695e7eb47667dc8b9860290
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:15:13 2005 -0700
 
@@ -174,8 +177,9 @@ test_expect_success 'show -F notes' '
 	test_commit 4th &&
 	echo "xyzzy" >note5 &&
 	git notes add -F note5 &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-F <<-EOF &&
-		commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:16:13 2005 -0700
 
@@ -198,10 +202,13 @@ test_expect_success 'Re-adding -F notes without -f fails' '
 '
 
 test_expect_success 'git log --pretty=raw does not show notes' '
+	commit=$(git rev-parse HEAD) &&
+	tree=$(git rev-parse HEAD^{tree}) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11
-		tree 05ac65288c4c4b3b709a020ae94b2ece2f2201ae
-		parent d07d62e5208f22eb5695e7eb47667dc8b9860290
+		commit $commit
+		tree $tree
+		parent $parent
 		author A U Thor <author@example.com> 1112912173 -0700
 		committer C O Mitter <committer@example.com> 1112912173 -0700
 
@@ -291,8 +298,9 @@ test_expect_success 'git log --no-notes resets ref list' '
 test_expect_success 'show -m notes' '
 	test_commit 5th &&
 	git notes add -m spam -m "foo${LF}bar${LF}baz" &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-m <<-EOF &&
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -313,8 +321,9 @@ test_expect_success 'show -m notes' '
 
 test_expect_success 'remove note with add -f -F /dev/null' '
 	git notes add -f -F /dev/null &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-rm-F <<-EOF &&
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -356,14 +365,16 @@ test_expect_success 'create note with combination of -m and -F' '
 test_expect_success 'remove note with "git notes remove"' '
 	git notes remove HEAD^ &&
 	git notes remove &&
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect-rm-remove <<-EOF &&
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
 		${indent}5th
 
-		commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:16:13 2005 -0700
 
@@ -459,9 +470,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '
 '
 
 test_expect_success 'list notes with "git notes list"' '
-	cat >expect <<-EOF &&
-		c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 7a4ca6ee52a974a66cbaa78e33214535dff1d691
-		c18dc024e14f08d18d14eea0d747ff692d66d6a3 d07d62e5208f22eb5695e7eb47667dc8b9860290
+	commit_2=$(git rev-parse 2nd) &&
+	commit_3=$(git rev-parse 3rd) &&
+	sort -t" " -k2 >expect <<-EOF &&
+		$(git rev-parse refs/notes/commits:$commit_2) $commit_2
+		$(git rev-parse refs/notes/commits:$commit_3) $commit_3
 	EOF
 	git notes list >actual &&
 	test_cmp expect actual
@@ -474,7 +487,7 @@ test_expect_success 'list notes with "git notes"' '
 
 test_expect_success 'list specific note with "git notes list <object>"' '
 	cat >expect <<-EOF &&
-		c18dc024e14f08d18d14eea0d747ff692d66d6a3
+		$(git rev-parse refs/notes/commits:$commit_3)
 	EOF
 	git notes list HEAD^^ >actual &&
 	test_cmp expect actual
@@ -498,10 +511,11 @@ test_expect_success 'append to existing note with "git notes append"' '
 '
 
 test_expect_success '"git notes list" does not expand to "git notes list HEAD"' '
-	cat >expect_list <<-EOF &&
-		c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 7a4ca6ee52a974a66cbaa78e33214535dff1d691
-		4b6ad22357cc8a1296720574b8d2fbc22fab0671 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
-		c18dc024e14f08d18d14eea0d747ff692d66d6a3 d07d62e5208f22eb5695e7eb47667dc8b9860290
+	commit_5=$(git rev-parse 5th) &&
+	sort -t" " -k2 >expect_list <<-EOF &&
+		$(git rev-parse refs/notes/commits:$commit_2) $commit_2
+		$(git rev-parse refs/notes/commits:$commit_3) $commit_3
+		$(git rev-parse refs/notes/commits:$commit_5) $commit_5
 	EOF
 	git notes list >actual &&
 	test_cmp expect_list actual
@@ -531,8 +545,9 @@ test_expect_success 'appending empty string to non-existing note does not create
 test_expect_success 'create other note on a different notes ref (setup)' '
 	test_commit 6th &&
 	GIT_NOTES_REF="refs/notes/other" git notes add -m "other note" &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-not-other <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -569,8 +584,10 @@ test_expect_success 'Do not show note when core.notesRef is overridden' '
 '
 
 test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect-both <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -582,7 +599,7 @@ test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '
 		Notes (other):
 		${indent}other note
 
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -616,8 +633,9 @@ test_expect_success 'notes.displayRef can be given more than once' '
 '
 
 test_expect_success 'notes.displayRef respects order' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-both-reversed <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -642,14 +660,16 @@ test_expect_success 'GIT_NOTES_DISPLAY_REF works' '
 '
 
 test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect-none <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
 		${indent}6th
 
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -666,8 +686,9 @@ test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' '
 '
 
 test_expect_success '--no-standard-notes' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-commits <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -712,8 +733,10 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '
 '
 
 test_expect_success 'create note from other note with "git notes add -C"' '
+	test_commit 7th &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit fb01e0ca8c33b6cc0c6451dde747f97df567cb5c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:19:13 2005 -0700
 
@@ -722,7 +745,6 @@ test_expect_success 'create note from other note with "git notes add -C"' '
 		Notes:
 		${indent}order test
 	EOF
-	test_commit 7th &&
 	git notes add -C $(git notes list HEAD^) &&
 	git log -1 >actual &&
 	test_cmp expect actual &&
@@ -744,8 +766,9 @@ test_expect_success 'create note from non-blob with "git notes add -C" fails' '
 '
 
 test_expect_success 'create note from blob with "git notes add -C" reuses blob id' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 9a4c31c7f722b5d517e92c64e932dd751e1413bf
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:20:13 2005 -0700
 
@@ -762,8 +785,10 @@ test_expect_success 'create note from blob with "git notes add -C" reuses blob i
 '
 
 test_expect_success 'create note from other note with "git notes add -c"' '
+	test_commit 9th &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 2e0db4bc649e174d667a1cde19e725cf897a5bd2
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:21:13 2005 -0700
 
@@ -772,7 +797,6 @@ test_expect_success 'create note from other note with "git notes add -c"' '
 		Notes:
 		${indent}yet another note
 	EOF
-	test_commit 9th &&
 	MSG="yet another note" git notes add -c $(git notes list HEAD^^) &&
 	git log -1 >actual &&
 	test_cmp expect actual
@@ -785,8 +809,9 @@ test_expect_success 'create note from non-existing note with "git notes add -c"
 '
 
 test_expect_success 'append to note from other note with "git notes append -C"' '
+	commit=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 2e0db4bc649e174d667a1cde19e725cf897a5bd2
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:21:13 2005 -0700
 
@@ -803,8 +828,9 @@ test_expect_success 'append to note from other note with "git notes append -C"'
 '
 
 test_expect_success 'create note from other note with "git notes append -c"' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 7c3b87ab368f81e11b1ea87b2ab99a71ccd25406
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:22:13 2005 -0700
 
@@ -819,8 +845,9 @@ test_expect_success 'create note from other note with "git notes append -c"' '
 '
 
 test_expect_success 'append to note from other note with "git notes append -c"' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 7c3b87ab368f81e11b1ea87b2ab99a71ccd25406
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:22:13 2005 -0700
 
@@ -837,8 +864,10 @@ test_expect_success 'append to note from other note with "git notes append -c"'
 '
 
 test_expect_success 'copy note with "git notes copy"' '
+	test_commit 11th &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit a446fff8777efdc6eb8f4b7c8a5ff699484df0d5
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:23:13 2005 -0700
 
@@ -849,7 +878,6 @@ test_expect_success 'copy note with "git notes copy"' '
 		${indent}
 		${indent}yet another note
 	EOF
-	test_commit 11th &&
 	git notes copy HEAD^ HEAD &&
 	git log -1 >actual &&
 	test_cmp expect actual &&
@@ -864,8 +892,9 @@ test_expect_success 'prevent overwrite with "git notes copy"' '
 '
 
 test_expect_success 'allow overwrite with "git notes copy -f"' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit a446fff8777efdc6eb8f4b7c8a5ff699484df0d5
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:23:13 2005 -0700
 
@@ -889,8 +918,10 @@ test_expect_success 'cannot copy note from object without notes' '
 '
 
 test_expect_success 'git notes copy --stdin' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit e871aa61182b1d95d0a6fb75445d891722863b6b
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:25:13 2005 -0700
 
@@ -901,7 +932,7 @@ test_expect_success 'git notes copy --stdin' '
 		${indent}
 		${indent}yet another note
 
-		commit 65e263ded02ae4e8839bc151095113737579dc12
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:24:13 2005 -0700
 
@@ -922,21 +953,23 @@ test_expect_success 'git notes copy --stdin' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (unconfigured)' '
+	test_commit 14th &&
+	test_commit 15th &&
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
 		${indent}15th
 
-		commit 07c85d77059393ed0154b8c96906547a59dfcddd
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:26:13 2005 -0700
 
 		${indent}14th
 	EOF
-	test_commit 14th &&
-	test_commit 15th &&
 	(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&
 	echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |
 	git notes copy --for-rewrite=foo &&
@@ -945,8 +978,10 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (enabled)' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -957,7 +992,7 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '
 		${indent}
 		${indent}yet another note
 
-		commit 07c85d77059393ed0154b8c96906547a59dfcddd
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:26:13 2005 -0700
 
@@ -986,8 +1021,9 @@ test_expect_success 'git notes copy --for-rewrite (disabled)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (overwrite)' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1015,8 +1051,9 @@ test_expect_success 'git notes copy --for-rewrite (ignore)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (append)' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1037,8 +1074,9 @@ test_expect_success 'git notes copy --for-rewrite (append)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (append two to one)' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1075,8 +1113,9 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '
 '
 
 test_expect_success 'GIT_NOTES_REWRITE_MODE works' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1095,8 +1134,9 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '
 '
 
 test_expect_success 'GIT_NOTES_REWRITE_REF works' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 04/14] t3305: make hash size independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (2 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 03/14] t3301: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 05/14] t3306: abstract away SHA-1-specific constants brian m. carlson
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Instead of hard-coding 40-character shell patterns, use grep to
determine if all of the paths have either zero or one levels of fanout,
as appropriate.

Note that the final test is implicitly dependent on the hash algorithm.
Depending on the algorithm in use, the fanout may or may not completely
compress.  In its current state, this is not a problem, but it could be
if the hash algorithm changes again.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3305-notes-fanout.sh | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh
index 54460beec4..831f83d211 100755
--- a/t/t3305-notes-fanout.sh
+++ b/t/t3305-notes-fanout.sh
@@ -35,15 +35,10 @@ test_expect_success 'many notes created with git-notes triggers fanout' '
 	git ls-tree -r --name-only refs/notes/commits |
 	while read path
 	do
-		case "$path" in
-		??/??????????????????????????????????????)
-			: true
-			;;
-		*)
+		echo $path | grep "^../[0-9a-f]*$" || {
 			echo "Invalid path \"$path\"" &&
-			return 1
-			;;
-		esac
+			return 1;
+		}
 	done
 '
 
@@ -77,15 +72,10 @@ test_expect_success 'deleting most notes triggers fanout consolidation' '
 	git ls-tree -r --name-only refs/notes/commits |
 	while read path
 	do
-		case "$path" in
-		????????????????????????????????????????)
-			: true
-			;;
-		*)
+		echo $path | grep -v "^../.*" || {
 			echo "Invalid path \"$path\"" &&
-			return 1
-			;;
-		esac
+			return 1;
+		}
 	done
 '
 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 05/14] t3306: abstract away SHA-1-specific constants
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (3 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 04/14] t3305: make hash size independent brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 06/14] t3404: " brian m. carlson
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.  Convert some single-line heredocs into inline
uses of echo now that they can be expressed succinctly.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3306-notes-prune.sh | 45 ++++++++++++++++++++----------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh
index 61748088eb..8f4102ff9e 100755
--- a/t/t3306-notes-prune.sh
+++ b/t/t3306-notes-prune.sh
@@ -11,23 +11,26 @@ test_expect_success 'setup: create a few commits with notes' '
 	test_tick &&
 	git commit -m 1st &&
 	git notes add -m "Note #1" &&
+	first=$(git rev-parse HEAD) &&
 	: > file2 &&
 	git add file2 &&
 	test_tick &&
 	git commit -m 2nd &&
 	git notes add -m "Note #2" &&
+	second=$(git rev-parse HEAD) &&
 	: > file3 &&
 	git add file3 &&
 	test_tick &&
 	git commit -m 3rd &&
-	COMMIT_FILE=.git/objects/5e/e1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
+	third=$(git rev-parse HEAD) &&
+	COMMIT_FILE=$(echo $third | sed "s!^..!.git/objects/&/!") &&
 	test -f $COMMIT_FILE &&
 	test-tool chmtime =+0 $COMMIT_FILE &&
 	git notes add -m "Note #3"
 '
 
 cat > expect <<END_OF_LOG
-commit 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29
+commit $third
 Author: A U Thor <author@example.com>
 Date:   Thu Apr 7 15:15:13 2005 -0700
 
@@ -36,7 +39,7 @@ Date:   Thu Apr 7 15:15:13 2005 -0700
 Notes:
     Note #3
 
-commit 08341ad9e94faa089d60fd3f523affb25c6da189
+commit $second
 Author: A U Thor <author@example.com>
 Date:   Thu Apr 7 15:14:13 2005 -0700
 
@@ -45,7 +48,7 @@ Date:   Thu Apr 7 15:14:13 2005 -0700
 Notes:
     Note #2
 
-commit ab5f302035f2e7aaf04265f08b42034c23256e1f
+commit $first
 Author: A U Thor <author@example.com>
 Date:   Thu Apr 7 15:13:13 2005 -0700
 
@@ -70,16 +73,16 @@ test_expect_success 'remove some commits' '
 
 test_expect_success 'verify that commits are gone' '
 
-	test_must_fail git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f
+	test_must_fail git cat-file -p $third &&
+	git cat-file -p $second &&
+	git cat-file -p $first
 '
 
 test_expect_success 'verify that notes are still present' '
 
-	git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
+	git notes show $third &&
+	git notes show $second &&
+	git notes show $first
 '
 
 test_expect_success 'prune -n does not remove notes' '
@@ -90,13 +93,10 @@ test_expect_success 'prune -n does not remove notes' '
 	test_cmp expect actual
 '
 
-cat > expect <<EOF
-5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29
-EOF
 
 test_expect_success 'prune -n lists prunable notes' '
 
-
+	echo $third >expect &&
 	git notes prune -n > actual &&
 	test_cmp expect actual
 '
@@ -109,9 +109,9 @@ test_expect_success 'prune notes' '
 
 test_expect_success 'verify that notes are gone' '
 
-	test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
+	test_must_fail git notes show $third &&
+	git notes show $second &&
+	git notes show $first
 '
 
 test_expect_success 'remove some commits' '
@@ -121,21 +121,18 @@ test_expect_success 'remove some commits' '
 	git gc --prune=now
 '
 
-cat > expect <<EOF
-08341ad9e94faa089d60fd3f523affb25c6da189
-EOF
-
 test_expect_success 'prune -v notes' '
 
+	echo $second >expect &&
 	git notes prune -v > actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'verify that notes are gone' '
 
-	test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	test_must_fail git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
+	test_must_fail git notes show $third &&
+	test_must_fail git notes show $second &&
+	git notes show $first
 '
 
 test_done

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 06/14] t3404: abstract away SHA-1-specific constants
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (4 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 05/14] t3306: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 07/14] t3430: avoid hard-coded object IDs brian m. carlson
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.  Add a use of $EMPTY_TREE instead of a
hard-coded value.  Remove a comment about hard-coded hashes which is no
longer applicable.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3404-rebase-interactive.sh | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 461dd539ff..87ee69f78e 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -29,9 +29,6 @@ Initial setup:
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
-# WARNING: Modifications to the initial repository can change the SHA ID used
-# in the expect2 file for the 'stop on conflicting pick' test.
-
 test_expect_success 'setup' '
 	test_commit A file1 &&
 	test_commit B file1 &&
@@ -233,25 +230,28 @@ test_expect_success 'exchange two commits' '
 	set_fake_editor &&
 	FAKE_LINES="2 1" git rebase -i HEAD~2 &&
 	test H = $(git cat-file commit HEAD^ | sed -ne \$p) &&
-	test G = $(git cat-file commit HEAD | sed -ne \$p)
+	test G = $(git cat-file commit HEAD | sed -ne \$p) &&
+	blob1=$(git rev-parse --short HEAD^:file1) &&
+	blob2=$(git rev-parse --short HEAD:file1) &&
+	commit=$(git rev-parse --short HEAD)
 '
 
 test_expect_success 'stop on conflicting pick' '
-	cat >expect <<-\EOF &&
+	cat >expect <<-EOF &&
 	diff --git a/file1 b/file1
-	index f70f10e..fd79235 100644
+	index $blob1..$blob2 100644
 	--- a/file1
 	+++ b/file1
 	@@ -1 +1 @@
 	-A
 	+G
 	EOF
-	cat >expect2 <<-\EOF &&
+	cat >expect2 <<-EOF &&
 	<<<<<<< HEAD
 	D
 	=======
 	G
-	>>>>>>> 5d18e54... G
+	>>>>>>> $commit... G
 	EOF
 	git tag new-branch1 &&
 	set_fake_editor &&
@@ -1003,7 +1003,7 @@ test_expect_success 'rebase -i --root temporary sentinel commit' '
 	git checkout B &&
 	set_fake_editor &&
 	test_must_fail env FAKE_LINES="2" git rebase -i --root &&
-	git cat-file commit HEAD | grep "^tree 4b825dc642cb" &&
+	git cat-file commit HEAD | grep "^tree $EMPTY_TREE" &&
 	git rebase --abort
 '
 
@@ -1161,7 +1161,7 @@ test_expect_success 'rebase -i error on commits with \ in message' '
 	test_expect_code 1 grep  "	emp" error
 '
 
-test_expect_success 'short SHA-1 setup' '
+test_expect_success SHA1 'short SHA-1 setup' '
 	test_when_finished "git checkout master" &&
 	git checkout --orphan collide &&
 	git rm -rf . &&
@@ -1173,7 +1173,7 @@ test_expect_success 'short SHA-1 setup' '
 	)
 '
 
-test_expect_success 'short SHA-1 collide' '
+test_expect_success SHA1 'short SHA-1 collide' '
 	test_when_finished "reset_rebase && git checkout master" &&
 	git checkout collide &&
 	(

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 07/14] t3430: avoid hard-coded object IDs
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (5 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 06/14] t3404: " brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 08/14] t3506: make hash independent brian m. carlson
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Compute the object IDs used in the todo list instead of hard-coding
them.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3430-rebase-merges.sh | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index 7b6c4847ad..c1ea2ee297 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -37,20 +37,27 @@ test_expect_success 'setup' '
 	test_commit A &&
 	git checkout -b first &&
 	test_commit B &&
+	b=$(git rev-parse --short HEAD) &&
 	git checkout master &&
 	test_commit C &&
+	c=$(git rev-parse --short HEAD) &&
 	test_commit D &&
+	d=$(git rev-parse --short HEAD) &&
 	git merge --no-commit B &&
 	test_tick &&
 	git commit -m E &&
 	git tag -m E E &&
+	e=$(git rev-parse --short HEAD) &&
 	git checkout -b second C &&
 	test_commit F &&
+	f=$(git rev-parse --short HEAD) &&
 	test_commit G &&
+	g=$(git rev-parse --short HEAD) &&
 	git checkout master &&
 	git merge --no-commit G &&
 	test_tick &&
 	git commit -m H &&
+	h=$(git rev-parse --short HEAD) &&
 	git tag -m H H &&
 	git checkout A &&
 	test_commit conflicting-G G.t
@@ -93,24 +100,24 @@ test_expect_success 'create completely different structure' '
 '
 
 test_expect_success 'generate correct todo list' '
-	cat >expect <<-\EOF &&
+	cat >expect <<-EOF &&
 	label onto
 
 	reset onto
-	pick d9df450 B
+	pick $b B
 	label E
 
 	reset onto
-	pick 5dee784 C
+	pick $c C
 	label branch-point
-	pick ca2c861 F
-	pick 088b00a G
+	pick $f F
+	pick $g G
 	label H
 
 	reset branch-point # C
-	pick 12bd07b D
-	merge -C 2051b56 E # E
-	merge -C 233d48a H # H
+	pick $d D
+	merge -C $e E # E
+	merge -C $h H # H
 
 	EOF
 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 08/14] t3506: make hash independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (6 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 07/14] t3430: avoid hard-coded object IDs brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 09/14] t3600: make hash size independent brian m. carlson
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

This test uses a hard-coded object ID to ensure that the result of
cherry-pick --ff is correct.  Use test_oid to make this work for both
SHA-1 and SHA-256.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3506-cherry-pick-ff.sh | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index 127dd0082f..9d5adbc130 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -16,7 +16,11 @@ test_expect_success setup '
 	git add file1 &&
 	test_tick &&
 	git commit -m "second" &&
-	git tag second
+	git tag second &&
+	test_oid_cache <<-EOF
+	cp_ff sha1:1df192cd8bc58a2b275d842cede4d221ad9000d1
+	cp_ff sha256:e70d6b7fc064bddb516b8d512c9057094b96ce6ff08e12080acc4fe7f1d60a1d
+	EOF
 '
 
 test_expect_success 'cherry-pick using --ff fast forwards' '
@@ -102,7 +106,7 @@ test_expect_success 'cherry pick a root commit with --ff' '
 	git add file2 &&
 	git commit --amend -m "file2" &&
 	git cherry-pick --ff first &&
-	test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1"
+	test "$(git rev-parse --verify HEAD)" = "$(test_oid cp_ff)"
 '
 
 test_expect_success 'cherry-pick --ff on unborn branch' '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 09/14] t3600: make hash size independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (7 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 08/14] t3506: make hash independent brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 10/14] t3800: make hash-size independent brian m. carlson
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Instead of hard-coding a fixed length invalid object ID in the test,
compute one using the lookup tables.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3600-rm.sh | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 66282a720e..8c8cca5bfb 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -240,12 +240,14 @@ test_expect_success 'refresh index before checking if it is up-to-date' '
 '
 
 test_expect_success 'choking "git rm" should not let it die with cruft' '
+	test_oid_init &&
 	git reset -q --hard &&
 	test_when_finished "rm -f .git/index.lock && git reset -q --hard" &&
 	i=0 &&
+	hash=$(test_oid deadbeef) &&
 	while test $i -lt 12000
 	do
-		echo "100644 1234567890123456789012345678901234567890 0	some-file-$i"
+		echo "100644 $hash 0	some-file-$i"
 		i=$(( $i + 1 ))
 	done | git update-index --index-info &&
 	git rm -n "some-file-*" | : &&

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 10/14] t3800: make hash-size independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (8 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 09/14] t3600: make hash size independent brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 11/14] t3903: abstract away SHA-1-specific constants brian m. carlson
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Replace references to several hard-coded object IDs with a variable
referring to the generated commit.  Avoid matching on exact character
positions, which will be different depending on the hash in use.  In the
test for a valid object ID, use an obviously invalid one from the lookup
table.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3800-mktag.sh | 49 ++++++++++++++++++++++++------------------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 8eb47942e2..64dcc5ec28 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -23,6 +23,7 @@ check_verify_failure () {
 # first create a commit, so we have a valid object/type
 # for the tag.
 test_expect_success 'setup' '
+	test_oid_init &&
 	echo Hello >A &&
 	git update-index --add A &&
 	git commit -m "Initial commit" &&
@@ -69,28 +70,28 @@ check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
 #  4. type line label check
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 xxxx tag
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char47: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 
 ############################################################
 #  5. type line eol check
 
-echo "object 779e9b33986b1c2670fff52c5067603117b3e895" >tag.sig
+echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char48: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
 
 ############################################################
 #  6. tag line label check #1
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 type tag
 xxx mytag
 tagger . <> 0 +0000
@@ -98,37 +99,37 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char57: no "tag " found$'
+	'^error: char.*: no "tag " found$'
 
 ############################################################
 #  7. tag line label check #2
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 type taggggggggggggggggggggggggggggggg
 tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char87: no "tag " found$'
+	'^error: char.*: no "tag " found$'
 
 ############################################################
 #  8. type line type-name length check
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 type taggggggggggggggggggggggggggggggg
 tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char53: type too long$'
+	'^error: char.*: type too long$'
 
 ############################################################
 #  9. verify object (SHA1/type) check
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $(test_oid deadbeef)
 type tagggg
 tag mytag
 tagger . <> 0 +0000
@@ -150,7 +151,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char67: could not verify tag name$'
+	'^error: char.*: could not verify tag name$'
 
 ############################################################
 # 11. tagger line label check #1
@@ -164,7 +165,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char70: could not find "tagger "$'
+	'^error: char.*: could not find "tagger "$'
 
 ############################################################
 # 12. tagger line label check #2
@@ -179,7 +180,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char70: could not find "tagger "$'
+	'^error: char.*: could not find "tagger "$'
 
 ############################################################
 # 13. disallow missing tag author name
@@ -194,7 +195,7 @@ This is filler
 EOF
 
 check_verify_failure 'disallow missing tag author name' \
-	'^error: char77: missing tagger name$'
+	'^error: char.*: missing tagger name$'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -209,7 +210,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char77: malformed tagger field$'
+	'^error: char.*: malformed tagger field$'
 
 ############################################################
 # 15. allow empty tag email
@@ -238,7 +239,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 EOF
 
 check_verify_failure 'disallow spaces in tag email' \
-	'^error: char77: malformed tagger field$'
+	'^error: char.*: malformed tagger field$'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -252,7 +253,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char107: missing tag timestamp$'
+	'^error: char.*: missing tag timestamp$'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -266,7 +267,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char107: missing tag timestamp$'
+	'^error: char.*: missing tag timestamp$'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -280,7 +281,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char111: malformed tag timestamp$'
+	'^error: char.*: malformed tag timestamp$'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -294,7 +295,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char118: malformed tag timezone$'
+	'^error: char.*: malformed tag timezone$'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -308,7 +309,7 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char118: malformed tag timezone$'
+	'^error: char.*: malformed tag timezone$'
 
 ############################################################
 # 22. detect invalid tag timezone3
@@ -322,7 +323,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 EOF
 
 check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char118: malformed tag timezone$'
+	'^error: char.*: malformed tag timezone$'
 
 ############################################################
 # 23. detect invalid header entry
@@ -337,7 +338,7 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char124: trailing garbage in tag header$'
+	'^error: char.*: trailing garbage in tag header$'
 
 ############################################################
 # 24. create valid tag

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 11/14] t3903: abstract away SHA-1-specific constants
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (9 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 10/14] t3800: make hash-size independent brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 20:27   ` Eric Sunshine
  2019-08-18 19:16 ` [PATCH 12/14] t4000: make hash size independent brian m. carlson
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Abstract away the SHA-1-specific constants by sanitizing diff output to
remove the index lines, since it's clear from the assertions in question
that we are not interested in the specific object IDs.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3903-stash.sh | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index b8e337893f..8e3e0992df 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -7,6 +7,18 @@ test_description='Test git stash'
 
 . ./test-lib.sh
 
+diff_cmp () {
+	for i in "$1" "$2"
+	do
+		sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \
+		-e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \
+		-e 's/^index [0-9a-f]*,[0-9a-f]*\.\.[0-9a-f]*/index 1234567,7654321..89abcde/' \
+		"$i" > "$i.compare"
+	done &&
+	test_cmp "$1.compare" "$2.compare" &&
+	rm -f "$1.compare" "$2.compare"
+}
+
 test_expect_success 'stash some dirty working directory' '
 	echo 1 >file &&
 	git add file &&
@@ -36,7 +48,7 @@ EOF
 test_expect_success 'parents of stash' '
 	test $(git rev-parse stash^) = $(git rev-parse HEAD) &&
 	git diff stash^2..stash >output &&
-	test_cmp expect output
+	diff_cmp expect output
 '
 
 test_expect_success 'applying bogus stash does nothing' '
@@ -210,13 +222,13 @@ test_expect_success 'stash branch' '
 	test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
 	test $(git rev-parse HEAD) = $(git rev-parse master^) &&
 	git diff --cached >output &&
-	test_cmp expect output &&
+	diff_cmp expect output &&
 	git diff >output &&
-	test_cmp expect1 output &&
+	diff_cmp expect1 output &&
 	git add file &&
 	git commit -m alternate\ second &&
 	git diff master..stashbranch >output &&
-	test_cmp output expect2 &&
+	diff_cmp output expect2 &&
 	test 0 = $(git stash list | wc -l)
 '
 
@@ -577,7 +589,7 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
 	+bar
 	EOF
 	git stash show -p ${STASH_ID} >actual &&
-	test_cmp expected actual
+	diff_cmp expected actual
 '
 
 test_expect_success 'stash show - no stashes on stack, stash-like argument' '
@@ -609,7 +621,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
 	+foo
 	EOF
 	git stash show -p ${STASH_ID} >actual &&
-	test_cmp expected actual
+	diff_cmp expected actual
 '
 
 test_expect_success 'stash show --patience shows diff' '
@@ -627,7 +639,7 @@ test_expect_success 'stash show --patience shows diff' '
 	+foo
 	EOF
 	git stash show --patience ${STASH_ID} >actual &&
-	test_cmp expected actual
+	diff_cmp expected actual
 '
 
 test_expect_success 'drop: fail early if specified stash is not a stash ref' '
@@ -791,7 +803,7 @@ test_expect_success 'stash where working directory contains "HEAD" file' '
 	git diff-index --cached --quiet HEAD &&
 	test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" &&
 	git diff stash^..stash >output &&
-	test_cmp expect output
+	diff_cmp expect output
 '
 
 test_expect_success 'store called with invalid commit' '
@@ -847,7 +859,7 @@ test_expect_success 'stash list implies --first-parent -m' '
 	+working
 	EOF
 	git stash list --format=%gd -p >actual &&
-	test_cmp expect actual
+	diff_cmp expect actual
 '
 
 test_expect_success 'stash list --cc shows combined diff' '
@@ -864,7 +876,7 @@ test_expect_success 'stash list --cc shows combined diff' '
 	++working
 	EOF
 	git stash list --format=%gd -p --cc >actual &&
-	test_cmp expect actual
+	diff_cmp expect actual
 '
 
 test_expect_success 'stash is not confused by partial renames' '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 12/14] t4000: make hash size independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (10 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 11/14] t3903: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 19:16 ` [PATCH 13/14] t4002: make hash independent brian m. carlson
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Use $ZERO_OID instead of hard-coding a fixed size all-zeros object ID.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t4000-diff-format.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index 8de36b7d12..e5116a76a1 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -78,7 +78,7 @@ test_expect_success 'git diff-files --no-patch --patch shows the patch' '
 
 test_expect_success 'git diff-files --no-patch --patch-with-raw shows the patch and raw data' '
 	git diff-files --no-patch --patch-with-raw >actual &&
-	grep -q "^:100644 100755 .* 0000000000000000000000000000000000000000 M	path0\$" actual &&
+	grep -q "^:100644 100755 .* $ZERO_OID M	path0\$" actual &&
 	tail -n +4 actual >actual-patch &&
 	compare_diff_patch expected actual-patch
 '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 13/14] t4002: make hash independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (11 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 12/14] t4000: make hash size independent brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-18 20:29   ` Eric Sunshine
  2019-08-18 19:16 ` [PATCH 14/14] t4009: make hash size independent brian m. carlson
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
  14 siblings, 1 reply; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Refactor out the hard-coded object IDs and use test_oid to provide
values for both SHA-1 and SHA-256.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t4002-diff-basic.sh | 367 +++++++++++++++++++++++++++++-------------
 1 file changed, 258 insertions(+), 109 deletions(-)

diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index 3a6c21e825..cbcdd10464 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -7,123 +7,272 @@ test_description='Test diff raw-output.
 
 '
 . ./test-lib.sh
+
 . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
 
-cat >.test-plain-OA <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A	AA
-:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A	AN
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 040000 0000000000000000000000000000000000000000 6d50f65d3bdab91c63444294d38f08aeff328e42 A	DF
-:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D	DM
-:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D	DN
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M	MM
-:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M	MN
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M	TT
-:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 5e5f22072bb39f6e12cf663a57cb634c76eefb49 M	Z
+test_oid_init
+
+test_oid_cache <<\EOF
+aa_1 sha1:ccba72ad3888a3520b39efcf780b9ee64167535d
+aa_1 sha256:9febfbf18197819b2735c45291f138525d2476d59470f98239647544586ba403
+
+aa_2 sha1:6aa2b5335b16431a0ef71e5c0a28be69183cf6a2
+aa_2 sha256:6eaa3437de83f145a4aaa6ba355303075ade547b128ec6a2cd00a81ff7ce7a56
+
+an_1 sha1:7e426fb079479fd67f6d81f984e4ec649a44bc25
+an_1 sha256:8f92a0bec99e399a38e3bd0e1bf19fbf121e0160efb29b857df79d439f1c4536
+
+dd_1 sha1:bcc68ef997017466d5c9094bcf7692295f588c9a
+dd_1 sha256:07e17428b00639b85485d2b01083d219e2f3e3ba8579e9ca44e9cc8dd554d952
+
+df_1 sha1:6d50f65d3bdab91c63444294d38f08aeff328e42
+df_1 sha256:e367cecc27e9bf5451b1c65828cb21938d36a5f8e39c1b03ad6509cc36bb8e9d
+
+df_2 sha1:71420ab81e254145d26d6fc0cddee64c1acd4787
+df_2 sha256:0f0a86d10347ff6921d03a3c954679f3f1d14fa3d5cd82f57b32c09755f3a47d
+
+dfd1 sha1:68a6d8b91da11045cf4aa3a5ab9f2a781c701249
+dfd1 sha256:f3bd3265b02b6978ce86490d8ad026c573639c974b3de1d9faf30d8d5a77d3d5
+
+dm_1 sha1:141c1f1642328e4bc46a7d801a71da392e66791e
+dm_1 sha256:c89f8656e7b94e21ee5fbaf0e2149bbf783c51edbe2ce110349cac13059ee7ed
+
+dm_2 sha1:3c4d8de5fbad08572bab8e10eef8dbb264cf0231
+dm_2 sha256:83a572e37e0c94086294dae2cecc43d9131afd6f6c906e495c78972230b54988
+
+dn_1 sha1:35abde1506ddf806572ff4d407bd06885d0f8ee9
+dn_1 sha256:775d5852582070e620be63327bfa515fab8f71c7ac3e4f0c3cd6267b4377ba28
+
+ll_2 sha1:1d41122ebdd7a640f29d3c9cc4f9d70094374762
+ll_2 sha256:7917b4948a883cfed0a77d3d5a625dc8577d6ddcc3c6c3bbc56c4d4226a2246d
+
+md_1 sha1:03f24c8c4700babccfd28b654e7e8eac402ad6cd
+md_1 sha256:fc9f30369b978595ad685ba11ca9a17de0af16d79cd4b629975f4f1590033902
+
+md_2 sha1:103d9f89b50b9aad03054b579be5e7aa665f2d57
+md_2 sha256:fc78ec75275628762fe520479a6b2398dec295ce7aabcb1d15e5963c7b4e9317
+
+mm_1 sha1:b258508afb7ceb449981bd9d63d2d3e971bf8d34
+mm_1 sha256:a4b7847d228e900e3000285e240c20fd96f9dd41ce1445305f6eada126d4a04a
+
+mm_2 sha1:b431b272d829ff3aa4d1a5085f4394ab4d3305b6
+mm_2 sha256:3f8b83ea36aacf689bcf1a1290a9a8ed341564d32682ea6f76fea9a979186782
+
+mm_3 sha1:19989d4559aae417fedee240ccf2ba315ea4dc2b
+mm_3 sha256:71b3bfc5747ac033fff9ea0ab39ee453a3af2969890e75d6ef547b87544e2681
+
+mn_1 sha1:bd084b0c27c7b6cc34f11d6d0509a29be3caf970
+mn_1 sha256:47a67450583d7a329eb01a7c4ba644945af72c0ed2c7c95eb5a00d6e46d4d483
+
+mn_2 sha1:a716d58de4a570e0038f5c307bd8db34daea021f
+mn_2 sha256:f95104c1ebe27acb84bac25a7be98c71f6b8d3054b21f357a5be0c524ad97e08
+
+nm_1 sha1:c8f25781e8f1792e3e40b74225e20553041b5226
+nm_1 sha256:09baddc7afaa62e62e152c23c9c3ab94bf15a3894031e227e9be7fe68e1f4e49
+
+nm_2 sha1:cdb9a8c3da571502ac30225e9c17beccb8387983
+nm_2 sha256:58b5227956ac2d2a08d0efa513c0ae37430948b16791ea3869a1308dbf05536d
+
+na_1 sha1:15885881ea69115351c09b38371f0348a3fb8c67
+na_1 sha256:18e4fdd1670cd7968ee23d35bfd29e5418d56fb190c840094c1c57ceee0aad8f
+
+nd_1 sha1:a4e179e4291e5536a5e1c82e091052772d2c5a93
+nd_1 sha256:07dac9b01d00956ea0c65bd993d7de4864aeef2ed3cbb1255d9f1d949fcd6df6
+
+ss_1 sha1:40c959f984c8b89a2b02520d17f00d717f024397
+ss_1 sha256:50fc1b5df74d9910db2f9270993484235f15b69b75b01bcfb53e059289d14af9
+
+ss_2 sha1:2ac547ae9614a00d1b28275de608131f7a0e259f
+ss_2 sha256:a90f02e6044f1497d13db587d22ab12f90150a7d1e084afcf96065fab35ae2bc
+
+tt_1 sha1:4ac13458899ab908ef3b1128fa378daefc88d356
+tt_1 sha256:c53113c7dd5060e86b5b251428bd058f6726f66273c6a24bff1c61a04f498dd3
+
+tt_2 sha1:4c86f9a85fbc5e6804ee2e17a797538fbe785bca
+tt_2 sha256:0775f2a296129a7cf2862b46bc0e88c14d593f2773a3e3fb1c5193db6f5a7e77
+
+tt_3 sha1:c4e4a12231b9fa79a0053cb6077fcb21bb5b135a
+tt_3 sha256:47860f93cdd211f96443e0560f21c57ab6c2f4b0ac27ff03651a352e53fe8484
+
+z__1 sha1:7d670fdcdb9929f6c7dac196ff78689cd1c566a1
+z__1 sha256:44d0f37aff5e51cfcfdd1134c93a6419bcca7b9964f792ffcd5f9b4fcba1ee63
+
+z__2 sha1:5e5f22072bb39f6e12cf663a57cb634c76eefb49
+z__2 sha256:d29de162113190fed104eb5f010820cef4e315f89b9326e8497f7219fb737894
+
+z__3 sha1:1ba523955d5160681af65cb776411f574c1e8155
+z__3 sha256:07422d772b07794ab4369a5648e617719f89c2d2212cbeab05d97214b6471636
+
+zaa1 sha1:8acb8e9750e3f644bf323fcf3d338849db106c77
+zaa1 sha256:e79b029282c8abec2d9f3f7faceaf2a1405e02d1f368e66450ae66cf5b68d1f4
+
+zaa2 sha1:6c0b99286d0bce551ac4a7b3dff8b706edff3715
+zaa2 sha256:c82bd78c3e69ea1796e6b1a7a3ba45bb106c50e819296475b862123d3f5cc5a0
+
+zan1 sha1:087494262084cefee7ed484d20c8dc0580791272
+zan1 sha256:4b159eb3804d05599023dd074f771d06d02870f4ab24a7165add8ac3d703b8d3
+
+zdd1 sha1:879007efae624d2b1307214b24a956f0a8d686a8
+zdd1 sha256:eecfdd4d8092dd0363fb6d4548b54c6afc8982c3ed9b34e393f1d6a921d8eaa3
+
+zdm1 sha1:9b541b2275c06e3a7b13f28badf5294e2ae63df4
+zdm1 sha256:ab136e88e19a843c4bf7713d2090d5a2186ba16a6a80dacc12eeddd256a8e556
+
+zdm2 sha1:d77371d15817fcaa57eeec27f770c505ba974ec1
+zdm2 sha256:1c1a5f57363f46a15d95ce8527b3c2c158d88d16853b4acbf81bd20fd2c89a46
+
+zdn1 sha1:beb5d38c55283d280685ea21a0e50cfcc0ca064a
+zdn1 sha256:0f0eca66183617b0aa5ad74b256540329f841470922ca6760263c996d825eb18
+
+zmd1 sha1:d41fda41b7ec4de46b43cb7ea42a45001ae393d5
+zmd1 sha256:1ed32d481852eddf31a0ce12652a0ad14bf5b7a842667b5dbb0b50f35bf1c80a
+
+zmd2 sha1:a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9
+zmd2 sha256:b238da211b404f8917df2d9c6f7030535e904b2186131007a3c292ec6902f933
+
+zmm1 sha1:4ca22bae2527d3d9e1676498a0fba3b355bd1278
+zmm1 sha256:072b1d85b5f34fabc99dfa46008c5418df68302d3e317430006f49b32d244226
+
+zmm2 sha1:61422ba9c2c873416061a88cd40a59a35b576474
+zmm2 sha256:81dd5d2b3c5cda16fef552256aed4e2ea0802a8450a08f308a92142112ff6dda
+
+zmm3 sha1:697aad7715a1e7306ca76290a3dd4208fbaeddfa
+zmm3 sha256:8b10fab49e9be3414aa5e9a93d0e46f9569053440138a7c19a5eb5536d8e95bf
+
+zmn1 sha1:b16d7b25b869f2beb124efa53467d8a1550ad694
+zmn1 sha256:609e4f75d1295e844c826feeba213acb0b6cfc609adfe8ff705b19e3829ae3e9
+
+zmn2 sha1:a5c544c21cfcb07eb80a4d89a5b7d1570002edfd
+zmn2 sha256:d6d03edf2dc1a3b267a8205de5f41a2ff4b03def8c7ae02052b543fb09d589fc
+
+zna1 sha1:d12979c22fff69c59ca9409e7a8fe3ee25eaee80
+zna1 sha256:b37b80e789e8ea32aa323f004628f02013f632124b0282c7fe00a127d3c64c3c
+
+znd1 sha1:a18393c636b98e9bd7296b8b437ea4992b72440c
+znd1 sha256:af92a22eee8c38410a0c9d2b5135a10aeb052cbc7cf675541ed9a67bfcaf7cf9
+
+znm1 sha1:3fdbe17fd013303a2e981e1ca1c6cd6e72789087
+znm1 sha256:f75aeaa0c11e76918e381c105f0752932c6150e941fec565d24fa31098a13dc1
+
+znm2 sha1:7e09d6a3a14bd630913e8c75693cea32157b606d
+znm2 sha256:938d73cfbaa1c902a84fb5b3afd9736aa0590367fb9bd59c6c4d072ce70fcd6d
+EOF
+
+cat >.test-plain-OA <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_1) A	AA
+:000000 100644 $(test_oid zero) $(test_oid an_1) A	AN
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 040000 $(test_oid zero) $(test_oid df_1) A	DF
+:100644 000000 $(test_oid dm_1) $(test_oid zero) D	DM
+:100644 000000 $(test_oid dn_1) $(test_oid zero) D	DN
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 100644 $(test_oid md_1) $(test_oid md_2) M	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_2) M	MM
+:100644 100644 $(test_oid mn_1) $(test_oid mn_2) M	MN
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_2) M	TT
+:040000 040000 $(test_oid z__1) $(test_oid z__2) M	Z
 EOF
 
-cat >.test-recursive-OA <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A	AA
-:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A	AN
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 100644 0000000000000000000000000000000000000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 A	DF/DF
-:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D	DM
-:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D	DN
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M	MM
-:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M	MN
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M	TT
-:000000 100644 0000000000000000000000000000000000000000 8acb8e9750e3f644bf323fcf3d338849db106c77 A	Z/AA
-:000000 100644 0000000000000000000000000000000000000000 087494262084cefee7ed484d20c8dc0580791272 A	Z/AN
-:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D	Z/DD
-:100644 000000 9b541b2275c06e3a7b13f28badf5294e2ae63df4 0000000000000000000000000000000000000000 D	Z/DM
-:100644 000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a 0000000000000000000000000000000000000000 D	Z/DN
-:100644 100644 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 M	Z/MD
-:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 61422ba9c2c873416061a88cd40a59a35b576474 M	Z/MM
-:100644 100644 b16d7b25b869f2beb124efa53467d8a1550ad694 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd M	Z/MN
+cat >.test-recursive-OA <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_1) A	AA
+:000000 100644 $(test_oid zero) $(test_oid an_1) A	AN
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 100644 $(test_oid zero) $(test_oid dfd1) A	DF/DF
+:100644 000000 $(test_oid dm_1) $(test_oid zero) D	DM
+:100644 000000 $(test_oid dn_1) $(test_oid zero) D	DN
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 100644 $(test_oid md_1) $(test_oid md_2) M	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_2) M	MM
+:100644 100644 $(test_oid mn_1) $(test_oid mn_2) M	MN
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_2) M	TT
+:000000 100644 $(test_oid zero) $(test_oid zaa1) A	Z/AA
+:000000 100644 $(test_oid zero) $(test_oid zan1) A	Z/AN
+:100644 000000 $(test_oid zdd1) $(test_oid zero) D	Z/DD
+:100644 000000 $(test_oid zdm1) $(test_oid zero) D	Z/DM
+:100644 000000 $(test_oid zdn1) $(test_oid zero) D	Z/DN
+:100644 100644 $(test_oid zmd1) $(test_oid zmd2) M	Z/MD
+:100644 100644 $(test_oid zmm1) $(test_oid zmm2) M	Z/MM
+:100644 100644 $(test_oid zmn1) $(test_oid zmn2) M	Z/MN
 EOF
-cat >.test-plain-OB <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A	AA
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M	DM
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 1ba523955d5160681af65cb776411f574c1e8155 M	Z
+cat >.test-plain-OB <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_2) A	AA
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:100644 100644 $(test_oid dm_1) $(test_oid dm_2) M	DM
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 000000 $(test_oid md_1) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_3) M	MM
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_3) M	TT
+:040000 040000 $(test_oid z__1) $(test_oid z__3) M	Z
 EOF
-cat >.test-recursive-OB <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A	AA
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M	DM
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:000000 100644 0000000000000000000000000000000000000000 6c0b99286d0bce551ac4a7b3dff8b706edff3715 A	Z/AA
-:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D	Z/DD
-:100644 100644 9b541b2275c06e3a7b13f28badf5294e2ae63df4 d77371d15817fcaa57eeec27f770c505ba974ec1 M	Z/DM
-:100644 000000 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 0000000000000000000000000000000000000000 D	Z/MD
-:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 697aad7715a1e7306ca76290a3dd4208fbaeddfa M	Z/MM
-:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A	Z/NA
-:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D	Z/ND
-:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M	Z/NM
+cat >.test-recursive-OB <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_2) A	AA
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:100644 100644 $(test_oid dm_1) $(test_oid dm_2) M	DM
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 000000 $(test_oid md_1) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_3) M	MM
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_3) M	TT
+:000000 100644 $(test_oid zero) $(test_oid zaa2) A	Z/AA
+:100644 000000 $(test_oid zdd1) $(test_oid zero) D	Z/DD
+:100644 100644 $(test_oid zdm1) $(test_oid zdm2) M	Z/DM
+:100644 000000 $(test_oid zmd1) $(test_oid zero) D	Z/MD
+:100644 100644 $(test_oid zmm1) $(test_oid zmm3) M	Z/MM
+:000000 100644 $(test_oid zero) $(test_oid zna1) A	Z/NA
+:100644 000000 $(test_oid znd1) $(test_oid zero) D	Z/ND
+:100644 100644 $(test_oid znm1) $(test_oid znm2) M	Z/NM
 EOF
-cat >.test-plain-AB <<\EOF
-:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M	AA
-:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D	AN
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:040000 000000 6d50f65d3bdab91c63444294d38f08aeff328e42 0000000000000000000000000000000000000000 D	DF
-:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A	DM
-:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A	DN
-:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M	MN
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:040000 040000 5e5f22072bb39f6e12cf663a57cb634c76eefb49 1ba523955d5160681af65cb776411f574c1e8155 M	Z
+cat >.test-plain-AB <<EOF
+:100644 100644 $(test_oid aa_1) $(test_oid aa_2) M	AA
+:100644 000000 $(test_oid an_1) $(test_oid zero) D	AN
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:040000 000000 $(test_oid df_1) $(test_oid zero) D	DF
+:000000 100644 $(test_oid zero) $(test_oid dm_2) A	DM
+:000000 100644 $(test_oid zero) $(test_oid dn_1) A	DN
+:100644 000000 $(test_oid md_2) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_2) $(test_oid mm_3) M	MM
+:100644 100644 $(test_oid mn_2) $(test_oid mn_1) M	MN
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid tt_2) $(test_oid tt_3) M	TT
+:040000 040000 $(test_oid z__2) $(test_oid z__3) M	Z
 EOF
-cat >.test-recursive-AB <<\EOF
-:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M	AA
-:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D	AN
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:100644 000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 0000000000000000000000000000000000000000 D	DF/DF
-:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A	DM
-:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A	DN
-:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M	MN
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:100644 100644 8acb8e9750e3f644bf323fcf3d338849db106c77 6c0b99286d0bce551ac4a7b3dff8b706edff3715 M	Z/AA
-:100644 000000 087494262084cefee7ed484d20c8dc0580791272 0000000000000000000000000000000000000000 D	Z/AN
-:000000 100644 0000000000000000000000000000000000000000 d77371d15817fcaa57eeec27f770c505ba974ec1 A	Z/DM
-:000000 100644 0000000000000000000000000000000000000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a A	Z/DN
-:100644 000000 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 0000000000000000000000000000000000000000 D	Z/MD
-:100644 100644 61422ba9c2c873416061a88cd40a59a35b576474 697aad7715a1e7306ca76290a3dd4208fbaeddfa M	Z/MM
-:100644 100644 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd b16d7b25b869f2beb124efa53467d8a1550ad694 M	Z/MN
-:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A	Z/NA
-:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D	Z/ND
-:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M	Z/NM
+cat >.test-recursive-AB <<EOF
+:100644 100644 $(test_oid aa_1) $(test_oid aa_2) M	AA
+:100644 000000 $(test_oid an_1) $(test_oid zero) D	AN
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:100644 000000 $(test_oid dfd1) $(test_oid zero) D	DF/DF
+:000000 100644 $(test_oid zero) $(test_oid dm_2) A	DM
+:000000 100644 $(test_oid zero) $(test_oid dn_1) A	DN
+:100644 000000 $(test_oid md_2) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_2) $(test_oid mm_3) M	MM
+:100644 100644 $(test_oid mn_2) $(test_oid mn_1) M	MN
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid tt_2) $(test_oid tt_3) M	TT
+:100644 100644 $(test_oid zaa1) $(test_oid zaa2) M	Z/AA
+:100644 000000 $(test_oid zan1) $(test_oid zero) D	Z/AN
+:000000 100644 $(test_oid zero) $(test_oid zdm2) A	Z/DM
+:000000 100644 $(test_oid zero) $(test_oid zdn1) A	Z/DN
+:100644 000000 $(test_oid zmd2) $(test_oid zero) D	Z/MD
+:100644 100644 $(test_oid zmm2) $(test_oid zmm3) M	Z/MM
+:100644 100644 $(test_oid zmn2) $(test_oid zmn1) M	Z/MN
+:000000 100644 $(test_oid zero) $(test_oid zna1) A	Z/NA
+:100644 000000 $(test_oid znd1) $(test_oid zero) D	Z/ND
+:100644 100644 $(test_oid znm1) $(test_oid znm2) M	Z/NM
 EOF
 
 cmp_diff_files_output () {

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH 14/14] t4009: make hash size independent
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (12 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 13/14] t4002: make hash independent brian m. carlson
@ 2019-08-18 19:16 ` brian m. carlson
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
  14 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 19:16 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

Instead of hard-coding object IDs, compute them and use those in the
comparison.  Note that the comparison code ignores the actual object
IDs, but does check that they're the right size, so computing them is
the easiest way to ensure that they are.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t4009-diff-rename-4.sh | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index 3641fd84d6..b63bdf031f 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -14,6 +14,7 @@ test_expect_success \
     'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
      echo frotz >rezrov &&
     git update-index --add COPYING rezrov &&
+    orig=$(git hash-object COPYING) &&
     tree=$(git write-tree) &&
     echo $tree'
 
@@ -22,6 +23,8 @@ test_expect_success \
     'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
     sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
     rm -f COPYING &&
+    c1=$(git hash-object COPYING.1) &&
+    c2=$(git hash-object COPYING.2) &&
     git update-index --add --remove COPYING COPYING.?'
 
 # tree has COPYING and rezrov.  work tree has COPYING.1 and COPYING.2,
@@ -31,11 +34,11 @@ test_expect_success \
 
 git diff-index -z -C $tree >current
 
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
+cat >expected <<EOF
+:100644 100644 $orig $c1 C1234
 COPYING
 COPYING.1
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234
+:100644 100644 $orig $c2 R1234
 COPYING
 COPYING.2
 EOF
@@ -57,10 +60,10 @@ test_expect_success \
 # about rezrov.
 
 git diff-index -z -C $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M
+cat >expected <<EOF
+:100644 100644 $orig $c2 M
 COPYING
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
+:100644 100644 $orig $c1 C1234
 COPYING
 COPYING.1
 EOF
@@ -82,8 +85,8 @@ test_expect_success \
      git update-index --add --remove COPYING COPYING.1'
 
 git diff-index -z -C --find-copies-harder $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
+cat >expected <<EOF
+:100644 100644 $orig $c1 C1234
 COPYING
 COPYING.1
 EOF

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH 11/14] t3903: abstract away SHA-1-specific constants
  2019-08-18 19:16 ` [PATCH 11/14] t3903: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-18 20:27   ` Eric Sunshine
  2019-08-18 20:34     ` brian m. carlson
  0 siblings, 1 reply; 185+ messages in thread
From: Eric Sunshine @ 2019-08-18 20:27 UTC (permalink / raw)
  To: brian m. carlson
  Cc: Git List, Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

On Sun, Aug 18, 2019 at 3:21 PM brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> Abstract away the SHA-1-specific constants by sanitizing diff output to
> remove the index lines, since it's clear from the assertions in question
> that we are not interested in the specific object IDs.
>
> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
> ---
> diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
> @@ -7,6 +7,18 @@ test_description='Test git stash'
> +diff_cmp () {
> +       for i in "$1" "$2"
> +       do
> +               sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \
> +               -e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \
> +               -e 's/^index [0-9a-f]*,[0-9a-f]*\.\.[0-9a-f]*/index 1234567,7654321..89abcde/' \
> +               "$i" > "$i.compare"
> +       done &&
> +       test_cmp "$1.compare" "$2.compare" &&
> +       rm -f "$1.compare" "$2.compare"
> +}

For safety, it would probably be a good idea to check the exit status
of the 'sed' invocation in the for-loop:

    for i in "$1" "$2"
    do
        sed -e ... "$i" >"$i.compare" || return 1
    done &&
    ...

(Note, also, that I dropped the whitespace after the '>' operator.)

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH 13/14] t4002: make hash independent
  2019-08-18 19:16 ` [PATCH 13/14] t4002: make hash independent brian m. carlson
@ 2019-08-18 20:29   ` Eric Sunshine
  0 siblings, 0 replies; 185+ messages in thread
From: Eric Sunshine @ 2019-08-18 20:29 UTC (permalink / raw)
  To: brian m. carlson
  Cc: Git List, Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

On Sun, Aug 18, 2019 at 3:21 PM brian m. carlson
<sandals@crustytoothpaste.net> wrote:
> Refactor out the hard-coded object IDs and use test_oid to provide
> values for both SHA-1 and SHA-256.

s/Refactor out/Factor out/

> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH 11/14] t3903: abstract away SHA-1-specific constants
  2019-08-18 20:27   ` Eric Sunshine
@ 2019-08-18 20:34     ` brian m. carlson
  0 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-18 20:34 UTC (permalink / raw)
  To: Eric Sunshine
  Cc: Git List, Jeff King, Taylor Blau, Thomas Gummerer, Johannes Schindelin

[-- Attachment #1: Type: text/plain, Size: 473 bytes --]

On 2019-08-18 at 20:27:41, Eric Sunshine wrote:
> For safety, it would probably be a good idea to check the exit status
> of the 'sed' invocation in the for-loop:
> 
>     for i in "$1" "$2"
>     do
>         sed -e ... "$i" >"$i.compare" || return 1
>     done &&
>     ...

I'll do that.

> (Note, also, that I dropped the whitespace after the '>' operator.)

Ah, good catch.
-- 
brian m. carlson: Houston, Texas, US
OpenPGP: https://keybase.io/bk2204

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 868 bytes --]

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 00/14] Hash-independent tests, part 5
  2019-08-18 19:16 [PATCH 00/14] Hash-independent tests, part 5 brian m. carlson
                   ` (13 preceding siblings ...)
  2019-08-18 19:16 ` [PATCH 14/14] t4009: make hash size independent brian m. carlson
@ 2019-08-26  1:43 ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 01/14] t3201: abstract away SHA-1-specific constants brian m. carlson
                     ` (13 more replies)
  14 siblings, 14 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

This is the fifth series of test fixes for SHA-256 compatibility.  It
consists of 15 patches fixing various tests from t3201 through t4009 and
has only test fixes: no test helper changes are included.

Changes from v1:
* Add sanity-checking to the sed invocation.
* Remove whitespace between redirection operator and file name.
* Change "Refactor out" to "Factor out".

brian m. carlson (14):
  t3201: abstract away SHA-1-specific constants
  t3206: abstract away hash size constants
  t3301: abstract away SHA-1-specific constants
  t3305: make hash size independent
  t3306: abstract away SHA-1-specific constants
  t3404: abstract away SHA-1-specific constants
  t3430: avoid hard-coded object IDs
  t3506: make hash independent
  t3600: make hash size independent
  t3800: make hash-size independent
  t3903: abstract away SHA-1-specific constants
  t4000: make hash size independent
  t4002: make hash independent
  t4009: make hash size independent

 t/t3201-branch-contains.sh    |   8 +-
 t/t3206-range-diff.sh         | 227 +++++++++++++++------
 t/t3301-notes.sh              | 140 ++++++++-----
 t/t3305-notes-fanout.sh       |  22 +-
 t/t3306-notes-prune.sh        |  45 ++---
 t/t3404-rebase-interactive.sh |  22 +-
 t/t3430-rebase-merges.sh      |  23 ++-
 t/t3506-cherry-pick-ff.sh     |   8 +-
 t/t3600-rm.sh                 |   4 +-
 t/t3800-mktag.sh              |  49 ++---
 t/t3903-stash.sh              |  32 ++-
 t/t4000-diff-format.sh        |   2 +-
 t/t4002-diff-basic.sh         | 367 ++++++++++++++++++++++++----------
 t/t4009-diff-rename-4.sh      |  19 +-
 14 files changed, 640 insertions(+), 328 deletions(-)

Range-diff against v1:
1:  bfc39503dc ! 1:  1a0bda61ca t3903: abstract away SHA-1-specific constants
    @@ t/t3903-stash.sh: test_description='Test git stash'
     +		sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \
     +		-e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \
     +		-e 's/^index [0-9a-f]*,[0-9a-f]*\.\.[0-9a-f]*/index 1234567,7654321..89abcde/' \
    -+		"$i" > "$i.compare"
    ++		"$i" >"$i.compare" || return 1
     +	done &&
     +	test_cmp "$1.compare" "$2.compare" &&
     +	rm -f "$1.compare" "$2.compare"
2:  2da09f10f4 = 2:  64b2fc645b t4000: make hash size independent
3:  239d6de517 ! 3:  a8f0255ea0 t4002: make hash independent
    @@ Metadata
      ## Commit message ##
         t4002: make hash independent
     
    -    Refactor out the hard-coded object IDs and use test_oid to provide
    -    values for both SHA-1 and SHA-256.
    +    Factor out the hard-coded object IDs and use test_oid to provide values
    +    for both SHA-1 and SHA-256.
     
         Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
     
4:  7cb314ec8a = 4:  837d185fa6 t4009: make hash size independent

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 01/14] t3201: abstract away SHA-1-specific constants
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 02/14] t3206: abstract away hash size constants brian m. carlson
                     ` (12 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3201-branch-contains.sh | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh
index 0ea4fc4694..40251c9f8f 100755
--- a/t/t3201-branch-contains.sh
+++ b/t/t3201-branch-contains.sh
@@ -192,10 +192,10 @@ test_expect_success 'branch --merged with --verbose' '
 	EOF
 	test_cmp expect actual &&
 	git branch --verbose --merged topic >actual &&
-	cat >expect <<-\EOF &&
-	  master c77a0a9 second on master
-	* topic  2c939f4 [ahead 1] foo
-	  zzz    c77a0a9 second on master
+	cat >expect <<-EOF &&
+	  master $(git rev-parse --short master) second on master
+	* topic  $(git rev-parse --short topic ) [ahead 1] foo
+	  zzz    $(git rev-parse --short zzz   ) second on master
 	EOF
 	test_i18ncmp expect actual
 '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 02/14] t3206: abstract away hash size constants
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 01/14] t3201: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 03/14] t3301: abstract away SHA-1-specific constants brian m. carlson
                     ` (11 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

The various short object IDs in the range-diff output differ between
hash algorithms.  Use test_oid_cache to look up values for both SHA-1
and SHA-256.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3206-range-diff.sh | 227 +++++++++++++++++++++++++++++++-----------
 1 file changed, 167 insertions(+), 60 deletions(-)

diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index ec548654ce..0120f769f1 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -8,17 +8,124 @@ test_description='range-diff tests'
 # harm than good.  We need some real history.
 
 test_expect_success 'setup' '
-	git fast-import < "$TEST_DIRECTORY"/t3206/history.export
+	git fast-import < "$TEST_DIRECTORY"/t3206/history.export &&
+	test_oid_cache <<-EOF
+	# topic
+	t1 sha1:4de457d
+	t2 sha1:fccce22
+	t3 sha1:147e64e
+	t4 sha1:a63e992
+	t1 sha256:b89f8b9
+	t2 sha256:5f12aad
+	t3 sha256:ea8b273
+	t4 sha256:14b7336
+
+	# unmodified
+	u1 sha1:35b9b25
+	u2 sha1:de345ab
+	u3 sha1:9af6654
+	u4 sha1:2901f77
+	u1 sha256:e3731be
+	u2 sha256:14fadf8
+	u3 sha256:736c4bc
+	u4 sha256:673e77d
+
+	# reordered
+	r1 sha1:aca177a
+	r2 sha1:14ad629
+	r3 sha1:ee58208
+	r4 sha1:307b27a
+	r1 sha256:f59d3aa
+	r2 sha256:fb261a8
+	r3 sha256:cb2649b
+	r4 sha256:958577e
+
+	# removed (deleted)
+	d1 sha1:7657159
+	d2 sha1:43d84d3
+	d3 sha1:a740396
+	d1 sha256:e312513
+	d2 sha256:eb19258
+	d3 sha256:1ccb3c1
+
+	# added
+	a1 sha1:2716022
+	a2 sha1:b62accd
+	a3 sha1:df46cfa
+	a4 sha1:3e64548
+	a5 sha1:12b4063
+	a1 sha256:d724f4d
+	a2 sha256:1de7762
+	a3 sha256:e159431
+	a4 sha256:b3e483c
+	a5 sha256:90866a7
+
+	# rebased
+	b1 sha1:cc9c443
+	b2 sha1:c5d9641
+	b3 sha1:28cc2b6
+	b4 sha1:5628ab7
+	b5 sha1:a31b12e
+	b1 sha256:a1a8717
+	b2 sha256:20a5862
+	b3 sha256:587172a
+	b4 sha256:2721c5d
+	b5 sha256:7b57864
+
+	# changed
+	c1 sha1:a4b3333
+	c2 sha1:f51d370
+	c3 sha1:0559556
+	c4 sha1:d966c5c
+	c1 sha256:f8c2b9d
+	c2 sha256:3fb6318
+	c3 sha256:168ab68
+	c4 sha256:3526539
+
+	# changed-message
+	m1 sha1:f686024
+	m2 sha1:4ab067d
+	m3 sha1:b9cb956
+	m4 sha1:8add5f1
+	m1 sha256:31e6281
+	m2 sha256:a06bf1b
+	m3 sha256:82dc654
+	m4 sha256:48470c5
+
+	# renamed
+	n1 sha1:f258d75
+	n2 sha1:017b62d
+	n3 sha1:3ce7af6
+	n4 sha1:1e6226b
+	n1 sha256:ad52114
+	n2 sha256:3b54c8f
+	n3 sha256:3b0a644
+	n4 sha256:e461653
+
+	# added and removed
+	s1 sha1:096b1ba
+	s2 sha1:d92e698
+	s3 sha1:9a1db4d
+	s4 sha1:fea3b5c
+	s1 sha256:a7f9134
+	s2 sha256:b4c2580
+	s3 sha256:1d62aa2
+	s4 sha256:48160e8
+
+	# Empty delimiter (included so lines match neatly)
+	__ sha1:-------
+	__ sha256:-------
+	EOF
 '
 
 test_expect_success 'simple A..B A..C (unmodified)' '
 	git range-diff --no-color master..topic master..unmodified \
 		>actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  35b9b25 s/5/A/
-	2:  fccce22 = 2:  de345ab s/4/A/
-	3:  147e64e = 3:  9af6654 s/11/B/
-	4:  a63e992 = 4:  2901f77 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid u1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid u2) s/4/A/
+	3:  $(test_oid t3) = 3:  $(test_oid u3) s/11/B/
+	4:  $(test_oid t4) = 4:  $(test_oid u4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -38,10 +145,10 @@ test_expect_success 'simple A B C (unmodified)' '
 test_expect_success 'trivial reordering' '
 	git range-diff --no-color master topic reordered >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  aca177a s/5/A/
-	3:  147e64e = 2:  14ad629 s/11/B/
-	4:  a63e992 = 3:  ee58208 s/12/B/
-	2:  fccce22 = 4:  307b27a s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid r1) s/5/A/
+	3:  $(test_oid t3) = 2:  $(test_oid r2) s/11/B/
+	4:  $(test_oid t4) = 3:  $(test_oid r3) s/12/B/
+	2:  $(test_oid t2) = 4:  $(test_oid r4) s/4/A/
 	EOF
 	test_cmp expected actual
 '
@@ -49,10 +156,10 @@ test_expect_success 'trivial reordering' '
 test_expect_success 'removed a commit' '
 	git range-diff --no-color master topic removed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  7657159 s/5/A/
-	2:  fccce22 < -:  ------- s/4/A/
-	3:  147e64e = 2:  43d84d3 s/11/B/
-	4:  a63e992 = 3:  a740396 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid d1) s/5/A/
+	2:  $(test_oid t2) < -:  $(test_oid __) s/4/A/
+	3:  $(test_oid t3) = 2:  $(test_oid d2) s/11/B/
+	4:  $(test_oid t4) = 3:  $(test_oid d3) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -60,11 +167,11 @@ test_expect_success 'removed a commit' '
 test_expect_success 'added a commit' '
 	git range-diff --no-color master topic added >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  2716022 s/5/A/
-	2:  fccce22 = 2:  b62accd s/4/A/
-	-:  ------- > 3:  df46cfa s/6/A/
-	3:  147e64e = 4:  3e64548 s/11/B/
-	4:  a63e992 = 5:  12b4063 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid a1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid a2) s/4/A/
+	-:  $(test_oid __) > 3:  $(test_oid a3) s/6/A/
+	3:  $(test_oid t3) = 4:  $(test_oid a4) s/11/B/
+	4:  $(test_oid t4) = 5:  $(test_oid a5) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -72,10 +179,10 @@ test_expect_success 'added a commit' '
 test_expect_success 'new base, A B C' '
 	git range-diff --no-color master topic rebased >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  cc9c443 s/5/A/
-	2:  fccce22 = 2:  c5d9641 s/4/A/
-	3:  147e64e = 3:  28cc2b6 s/11/B/
-	4:  a63e992 = 4:  5628ab7 s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid b1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid b2) s/4/A/
+	3:  $(test_oid t3) = 3:  $(test_oid b3) s/11/B/
+	4:  $(test_oid t4) = 4:  $(test_oid b4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -84,11 +191,11 @@ test_expect_success 'new base, B...C' '
 	# this syntax includes the commits from master!
 	git range-diff --no-color topic...rebased >actual &&
 	cat >expected <<-EOF &&
-	-:  ------- > 1:  a31b12e unrelated
-	1:  4de457d = 2:  cc9c443 s/5/A/
-	2:  fccce22 = 3:  c5d9641 s/4/A/
-	3:  147e64e = 4:  28cc2b6 s/11/B/
-	4:  a63e992 = 5:  5628ab7 s/12/B/
+	-:  $(test_oid __) > 1:  $(test_oid b5) unrelated
+	1:  $(test_oid t1) = 2:  $(test_oid b1) s/5/A/
+	2:  $(test_oid t2) = 3:  $(test_oid b2) s/4/A/
+	3:  $(test_oid t3) = 4:  $(test_oid b3) s/11/B/
+	4:  $(test_oid t4) = 5:  $(test_oid b4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -96,9 +203,9 @@ test_expect_success 'new base, B...C' '
 test_expect_success 'changed commit' '
 	git range-diff --no-color topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
-	2:  fccce22 = 2:  f51d370 s/4/A/
-	3:  147e64e ! 3:  0559556 s/11/B/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
 	    @@ file: A
 	      9
 	      10
@@ -108,7 +215,7 @@ test_expect_success 'changed commit' '
 	      12
 	      13
 	      14
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	    @@ file
 	     @@ file: A
 	      9
@@ -125,10 +232,10 @@ test_expect_success 'changed commit' '
 test_expect_success 'changed commit with --no-patch diff option' '
 	git range-diff --no-color --no-patch topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
-	2:  fccce22 = 2:  f51d370 s/4/A/
-	3:  147e64e ! 3:  0559556 s/11/B/
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -136,16 +243,16 @@ test_expect_success 'changed commit with --no-patch diff option' '
 test_expect_success 'changed commit with --stat diff option' '
 	git range-diff --no-color --stat topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
-	2:  fccce22 = 2:  f51d370 s/4/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
-	3:  147e64e ! 3:  0559556 s/11/B/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	     a => b | 0
 	     1 file changed, 0 insertions(+), 0 deletions(-)
 	EOF
@@ -155,9 +262,9 @@ test_expect_success 'changed commit with --stat diff option' '
 test_expect_success 'changed commit with sm config' '
 	git range-diff --no-color --submodule=log topic...changed >actual &&
 	cat >expected <<-EOF &&
-	1:  4de457d = 1:  a4b3333 s/5/A/
-	2:  fccce22 = 2:  f51d370 s/4/A/
-	3:  147e64e ! 3:  0559556 s/11/B/
+	1:  $(test_oid t1) = 1:  $(test_oid c1) s/5/A/
+	2:  $(test_oid t2) = 2:  $(test_oid c2) s/4/A/
+	3:  $(test_oid t3) ! 3:  $(test_oid c3) s/11/B/
 	    @@ file: A
 	      9
 	      10
@@ -167,7 +274,7 @@ test_expect_success 'changed commit with sm config' '
 	      12
 	      13
 	      14
-	4:  a63e992 ! 4:  d966c5c s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid c4) s/12/B/
 	    @@ file
 	     @@ file: A
 	      9
@@ -184,8 +291,8 @@ test_expect_success 'changed commit with sm config' '
 test_expect_success 'renamed file' '
 	git range-diff --no-color --submodule=log topic...renamed-file >actual &&
 	sed s/Z/\ /g >expected <<-EOF &&
-	1:  4de457d = 1:  f258d75 s/5/A/
-	2:  fccce22 ! 2:  017b62d s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid n1) s/5/A/
+	2:  $(test_oid t2) ! 2:  $(test_oid n2) s/4/A/
 	    @@ Metadata
 	    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
 	    Z
@@ -198,7 +305,7 @@ test_expect_success 'renamed file' '
 	    Z@@
 	    Z 1
 	    Z 2
-	3:  147e64e ! 3:  3ce7af6 s/11/B/
+	3:  $(test_oid t3) ! 3:  $(test_oid n3) s/11/B/
 	    @@ Metadata
 	    Z ## Commit message ##
 	    Z    s/11/B/
@@ -210,7 +317,7 @@ test_expect_success 'renamed file' '
 	    Z 8
 	    Z 9
 	    Z 10
-	4:  a63e992 ! 4:  1e6226b s/12/B/
+	4:  $(test_oid t4) ! 4:  $(test_oid n4) s/12/B/
 	    @@ Metadata
 	    Z ## Commit message ##
 	    Z    s/12/B/
@@ -229,8 +336,8 @@ test_expect_success 'renamed file' '
 test_expect_success 'file added and later removed' '
 	git range-diff --no-color --submodule=log topic...added-removed >actual &&
 	sed s/Z/\ /g >expected <<-EOF &&
-	1:  4de457d = 1:  096b1ba s/5/A/
-	2:  fccce22 ! 2:  d92e698 s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid s1) s/5/A/
+	2:  $(test_oid t2) ! 2:  $(test_oid s2) s/4/A/
 	    @@ Metadata
 	    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
 	    Z
@@ -246,7 +353,7 @@ test_expect_success 'file added and later removed' '
 	    Z 7
 	    +
 	    + ## new-file (new) ##
-	3:  147e64e ! 3:  9a1db4d s/11/B/
+	3:  $(test_oid t3) ! 3:  $(test_oid s3) s/11/B/
 	    @@ Metadata
 	    ZAuthor: Thomas Rast <trast@inf.ethz.ch>
 	    Z
@@ -262,7 +369,7 @@ test_expect_success 'file added and later removed' '
 	    Z 14
 	    +
 	    + ## new-file (deleted) ##
-	4:  a63e992 = 4:  fea3b5c s/12/B/
+	4:  $(test_oid t4) = 4:  $(test_oid s4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
@@ -275,8 +382,8 @@ test_expect_success 'no commits on one side' '
 test_expect_success 'changed message' '
 	git range-diff --no-color topic...changed-message >actual &&
 	sed s/Z/\ /g >expected <<-EOF &&
-	1:  4de457d = 1:  f686024 s/5/A/
-	2:  fccce22 ! 2:  4ab067d s/4/A/
+	1:  $(test_oid t1) = 1:  $(test_oid m1) s/5/A/
+	2:  $(test_oid t2) ! 2:  $(test_oid m2) s/4/A/
 	    @@ Metadata
 	    Z ## Commit message ##
 	    Z    s/4/A/
@@ -286,16 +393,16 @@ test_expect_success 'changed message' '
 	    Z ## file ##
 	    Z@@
 	    Z 1
-	3:  147e64e = 3:  b9cb956 s/11/B/
-	4:  a63e992 = 4:  8add5f1 s/12/B/
+	3:  $(test_oid t3) = 3:  $(test_oid m3) s/11/B/
+	4:  $(test_oid t4) = 4:  $(test_oid m4) s/12/B/
 	EOF
 	test_cmp expected actual
 '
 
 test_expect_success 'dual-coloring' '
-	sed -e "s|^:||" >expect <<-\EOF &&
-	:<YELLOW>1:  a4b3333 = 1:  f686024 s/5/A/<RESET>
-	:<RED>2:  f51d370 <RESET><YELLOW>!<RESET><GREEN> 2:  4ab067d<RESET><YELLOW> s/4/A/<RESET>
+	sed -e "s|^:||" >expect <<-EOF &&
+	:<YELLOW>1:  $(test_oid c1) = 1:  $(test_oid m1) s/5/A/<RESET>
+	:<RED>2:  $(test_oid c2) <RESET><YELLOW>!<RESET><GREEN> 2:  $(test_oid m2)<RESET><YELLOW> s/4/A/<RESET>
 	:    <REVERSE><CYAN>@@<RESET> <RESET>Metadata<RESET>
 	:      ## Commit message ##<RESET>
 	:         s/4/A/<RESET>
@@ -305,7 +412,7 @@ test_expect_success 'dual-coloring' '
 	:      ## file ##<RESET>
 	:    <CYAN> @@<RESET>
 	:      1<RESET>
-	:<RED>3:  0559556 <RESET><YELLOW>!<RESET><GREEN> 3:  b9cb956<RESET><YELLOW> s/11/B/<RESET>
+	:<RED>3:  $(test_oid c3) <RESET><YELLOW>!<RESET><GREEN> 3:  $(test_oid m3)<RESET><YELLOW> s/11/B/<RESET>
 	:    <REVERSE><CYAN>@@<RESET> <RESET>file: A<RESET>
 	:      9<RESET>
 	:      10<RESET>
@@ -315,7 +422,7 @@ test_expect_success 'dual-coloring' '
 	:      12<RESET>
 	:      13<RESET>
 	:      14<RESET>
-	:<RED>4:  d966c5c <RESET><YELLOW>!<RESET><GREEN> 4:  8add5f1<RESET><YELLOW> s/12/B/<RESET>
+	:<RED>4:  $(test_oid c4) <RESET><YELLOW>!<RESET><GREEN> 4:  $(test_oid m4)<RESET><YELLOW> s/12/B/<RESET>
 	:    <REVERSE><CYAN>@@<RESET> <RESET>file<RESET>
 	:    <CYAN> @@ file: A<RESET>
 	:      9<RESET>

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 03/14] t3301: abstract away SHA-1-specific constants
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 01/14] t3201: abstract away SHA-1-specific constants brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 02/14] t3206: abstract away hash size constants brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 04/14] t3305: make hash size independent brian m. carlson
                     ` (10 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.  Move some invocations of test_commit around so
that we can compute the object IDs for these commits.

Compute several object IDs in the tests instead of using hard-coded
values so that the test works with any hash algorithm.  Since the actual
values are sorted by the object ID of the object being annotated, sort
the expected values accordingly as well.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3301-notes.sh | 140 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 90 insertions(+), 50 deletions(-)

diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 704bbc6541..d3fa298c6a 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -66,8 +66,9 @@ test_expect_success 'show notes entry with %N' '
 '
 
 test_expect_success 'create reflog entry' '
+	ref=$(git rev-parse --short refs/notes/commits) &&
 	cat <<-EOF >expect &&
-		a1d8fa6 refs/notes/commits@{0}: notes: Notes added by '\''git notes add'\''
+		$ref refs/notes/commits@{0}: notes: Notes added by '\''git notes add'\''
 	EOF
 	git reflog show refs/notes/commits >actual &&
 	test_cmp expect actual
@@ -134,8 +135,9 @@ test_expect_success 'can overwrite existing note with "git notes add -f"' '
 '
 
 test_expect_success 'show notes' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 7a4ca6ee52a974a66cbaa78e33214535dff1d691
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:14:13 2005 -0700
 
@@ -152,8 +154,9 @@ test_expect_success 'show notes' '
 test_expect_success 'show multi-line notes' '
 	test_commit 3rd &&
 	MSG="b3${LF}c3c3c3c3${LF}d3d3d3" git notes add &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-multiline <<-EOF &&
-		commit d07d62e5208f22eb5695e7eb47667dc8b9860290
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:15:13 2005 -0700
 
@@ -174,8 +177,9 @@ test_expect_success 'show -F notes' '
 	test_commit 4th &&
 	echo "xyzzy" >note5 &&
 	git notes add -F note5 &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-F <<-EOF &&
-		commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:16:13 2005 -0700
 
@@ -198,10 +202,13 @@ test_expect_success 'Re-adding -F notes without -f fails' '
 '
 
 test_expect_success 'git log --pretty=raw does not show notes' '
+	commit=$(git rev-parse HEAD) &&
+	tree=$(git rev-parse HEAD^{tree}) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11
-		tree 05ac65288c4c4b3b709a020ae94b2ece2f2201ae
-		parent d07d62e5208f22eb5695e7eb47667dc8b9860290
+		commit $commit
+		tree $tree
+		parent $parent
 		author A U Thor <author@example.com> 1112912173 -0700
 		committer C O Mitter <committer@example.com> 1112912173 -0700
 
@@ -291,8 +298,9 @@ test_expect_success 'git log --no-notes resets ref list' '
 test_expect_success 'show -m notes' '
 	test_commit 5th &&
 	git notes add -m spam -m "foo${LF}bar${LF}baz" &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-m <<-EOF &&
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -313,8 +321,9 @@ test_expect_success 'show -m notes' '
 
 test_expect_success 'remove note with add -f -F /dev/null' '
 	git notes add -f -F /dev/null &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-rm-F <<-EOF &&
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -356,14 +365,16 @@ test_expect_success 'create note with combination of -m and -F' '
 test_expect_success 'remove note with "git notes remove"' '
 	git notes remove HEAD^ &&
 	git notes remove &&
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect-rm-remove <<-EOF &&
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
 		${indent}5th
 
-		commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:16:13 2005 -0700
 
@@ -459,9 +470,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '
 '
 
 test_expect_success 'list notes with "git notes list"' '
-	cat >expect <<-EOF &&
-		c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 7a4ca6ee52a974a66cbaa78e33214535dff1d691
-		c18dc024e14f08d18d14eea0d747ff692d66d6a3 d07d62e5208f22eb5695e7eb47667dc8b9860290
+	commit_2=$(git rev-parse 2nd) &&
+	commit_3=$(git rev-parse 3rd) &&
+	sort -t" " -k2 >expect <<-EOF &&
+		$(git rev-parse refs/notes/commits:$commit_2) $commit_2
+		$(git rev-parse refs/notes/commits:$commit_3) $commit_3
 	EOF
 	git notes list >actual &&
 	test_cmp expect actual
@@ -474,7 +487,7 @@ test_expect_success 'list notes with "git notes"' '
 
 test_expect_success 'list specific note with "git notes list <object>"' '
 	cat >expect <<-EOF &&
-		c18dc024e14f08d18d14eea0d747ff692d66d6a3
+		$(git rev-parse refs/notes/commits:$commit_3)
 	EOF
 	git notes list HEAD^^ >actual &&
 	test_cmp expect actual
@@ -498,10 +511,11 @@ test_expect_success 'append to existing note with "git notes append"' '
 '
 
 test_expect_success '"git notes list" does not expand to "git notes list HEAD"' '
-	cat >expect_list <<-EOF &&
-		c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 7a4ca6ee52a974a66cbaa78e33214535dff1d691
-		4b6ad22357cc8a1296720574b8d2fbc22fab0671 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
-		c18dc024e14f08d18d14eea0d747ff692d66d6a3 d07d62e5208f22eb5695e7eb47667dc8b9860290
+	commit_5=$(git rev-parse 5th) &&
+	sort -t" " -k2 >expect_list <<-EOF &&
+		$(git rev-parse refs/notes/commits:$commit_2) $commit_2
+		$(git rev-parse refs/notes/commits:$commit_3) $commit_3
+		$(git rev-parse refs/notes/commits:$commit_5) $commit_5
 	EOF
 	git notes list >actual &&
 	test_cmp expect_list actual
@@ -531,8 +545,9 @@ test_expect_success 'appending empty string to non-existing note does not create
 test_expect_success 'create other note on a different notes ref (setup)' '
 	test_commit 6th &&
 	GIT_NOTES_REF="refs/notes/other" git notes add -m "other note" &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-not-other <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -569,8 +584,10 @@ test_expect_success 'Do not show note when core.notesRef is overridden' '
 '
 
 test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect-both <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -582,7 +599,7 @@ test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' '
 		Notes (other):
 		${indent}other note
 
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -616,8 +633,9 @@ test_expect_success 'notes.displayRef can be given more than once' '
 '
 
 test_expect_success 'notes.displayRef respects order' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-both-reversed <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -642,14 +660,16 @@ test_expect_success 'GIT_NOTES_DISPLAY_REF works' '
 '
 
 test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect-none <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
 		${indent}6th
 
-		commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:17:13 2005 -0700
 
@@ -666,8 +686,9 @@ test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' '
 '
 
 test_expect_success '--no-standard-notes' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect-commits <<-EOF &&
-		commit 2c125331118caba0ff8238b7f4958ac6e93fe39c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:18:13 2005 -0700
 
@@ -712,8 +733,10 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '
 '
 
 test_expect_success 'create note from other note with "git notes add -C"' '
+	test_commit 7th &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit fb01e0ca8c33b6cc0c6451dde747f97df567cb5c
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:19:13 2005 -0700
 
@@ -722,7 +745,6 @@ test_expect_success 'create note from other note with "git notes add -C"' '
 		Notes:
 		${indent}order test
 	EOF
-	test_commit 7th &&
 	git notes add -C $(git notes list HEAD^) &&
 	git log -1 >actual &&
 	test_cmp expect actual &&
@@ -744,8 +766,9 @@ test_expect_success 'create note from non-blob with "git notes add -C" fails' '
 '
 
 test_expect_success 'create note from blob with "git notes add -C" reuses blob id' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 9a4c31c7f722b5d517e92c64e932dd751e1413bf
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:20:13 2005 -0700
 
@@ -762,8 +785,10 @@ test_expect_success 'create note from blob with "git notes add -C" reuses blob i
 '
 
 test_expect_success 'create note from other note with "git notes add -c"' '
+	test_commit 9th &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 2e0db4bc649e174d667a1cde19e725cf897a5bd2
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:21:13 2005 -0700
 
@@ -772,7 +797,6 @@ test_expect_success 'create note from other note with "git notes add -c"' '
 		Notes:
 		${indent}yet another note
 	EOF
-	test_commit 9th &&
 	MSG="yet another note" git notes add -c $(git notes list HEAD^^) &&
 	git log -1 >actual &&
 	test_cmp expect actual
@@ -785,8 +809,9 @@ test_expect_success 'create note from non-existing note with "git notes add -c"
 '
 
 test_expect_success 'append to note from other note with "git notes append -C"' '
+	commit=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 2e0db4bc649e174d667a1cde19e725cf897a5bd2
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:21:13 2005 -0700
 
@@ -803,8 +828,9 @@ test_expect_success 'append to note from other note with "git notes append -C"'
 '
 
 test_expect_success 'create note from other note with "git notes append -c"' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 7c3b87ab368f81e11b1ea87b2ab99a71ccd25406
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:22:13 2005 -0700
 
@@ -819,8 +845,9 @@ test_expect_success 'create note from other note with "git notes append -c"' '
 '
 
 test_expect_success 'append to note from other note with "git notes append -c"' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 7c3b87ab368f81e11b1ea87b2ab99a71ccd25406
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:22:13 2005 -0700
 
@@ -837,8 +864,10 @@ test_expect_success 'append to note from other note with "git notes append -c"'
 '
 
 test_expect_success 'copy note with "git notes copy"' '
+	test_commit 11th &&
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit a446fff8777efdc6eb8f4b7c8a5ff699484df0d5
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:23:13 2005 -0700
 
@@ -849,7 +878,6 @@ test_expect_success 'copy note with "git notes copy"' '
 		${indent}
 		${indent}yet another note
 	EOF
-	test_commit 11th &&
 	git notes copy HEAD^ HEAD &&
 	git log -1 >actual &&
 	test_cmp expect actual &&
@@ -864,8 +892,9 @@ test_expect_success 'prevent overwrite with "git notes copy"' '
 '
 
 test_expect_success 'allow overwrite with "git notes copy -f"' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit a446fff8777efdc6eb8f4b7c8a5ff699484df0d5
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:23:13 2005 -0700
 
@@ -889,8 +918,10 @@ test_expect_success 'cannot copy note from object without notes' '
 '
 
 test_expect_success 'git notes copy --stdin' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit e871aa61182b1d95d0a6fb75445d891722863b6b
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:25:13 2005 -0700
 
@@ -901,7 +932,7 @@ test_expect_success 'git notes copy --stdin' '
 		${indent}
 		${indent}yet another note
 
-		commit 65e263ded02ae4e8839bc151095113737579dc12
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:24:13 2005 -0700
 
@@ -922,21 +953,23 @@ test_expect_success 'git notes copy --stdin' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (unconfigured)' '
+	test_commit 14th &&
+	test_commit 15th &&
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
 		${indent}15th
 
-		commit 07c85d77059393ed0154b8c96906547a59dfcddd
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:26:13 2005 -0700
 
 		${indent}14th
 	EOF
-	test_commit 14th &&
-	test_commit 15th &&
 	(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&
 	echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |
 	git notes copy --for-rewrite=foo &&
@@ -945,8 +978,10 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (enabled)' '
+	commit=$(git rev-parse HEAD) &&
+	parent=$(git rev-parse HEAD^) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -957,7 +992,7 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '
 		${indent}
 		${indent}yet another note
 
-		commit 07c85d77059393ed0154b8c96906547a59dfcddd
+		commit $parent
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:26:13 2005 -0700
 
@@ -986,8 +1021,9 @@ test_expect_success 'git notes copy --for-rewrite (disabled)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (overwrite)' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1015,8 +1051,9 @@ test_expect_success 'git notes copy --for-rewrite (ignore)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (append)' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1037,8 +1074,9 @@ test_expect_success 'git notes copy --for-rewrite (append)' '
 '
 
 test_expect_success 'git notes copy --for-rewrite (append two to one)' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1075,8 +1113,9 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '
 '
 
 test_expect_success 'GIT_NOTES_REWRITE_MODE works' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 
@@ -1095,8 +1134,9 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '
 '
 
 test_expect_success 'GIT_NOTES_REWRITE_REF works' '
+	commit=$(git rev-parse HEAD) &&
 	cat >expect <<-EOF &&
-		commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89
+		commit $commit
 		Author: A U Thor <author@example.com>
 		Date:   Thu Apr 7 15:27:13 2005 -0700
 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 04/14] t3305: make hash size independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (2 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 03/14] t3301: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 05/14] t3306: abstract away SHA-1-specific constants brian m. carlson
                     ` (9 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Instead of hard-coding 40-character shell patterns, use grep to
determine if all of the paths have either zero or one levels of fanout,
as appropriate.

Note that the final test is implicitly dependent on the hash algorithm.
Depending on the algorithm in use, the fanout may or may not completely
compress.  In its current state, this is not a problem, but it could be
if the hash algorithm changes again.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3305-notes-fanout.sh | 22 ++++++----------------
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh
index 54460beec4..831f83d211 100755
--- a/t/t3305-notes-fanout.sh
+++ b/t/t3305-notes-fanout.sh
@@ -35,15 +35,10 @@ test_expect_success 'many notes created with git-notes triggers fanout' '
 	git ls-tree -r --name-only refs/notes/commits |
 	while read path
 	do
-		case "$path" in
-		??/??????????????????????????????????????)
-			: true
-			;;
-		*)
+		echo $path | grep "^../[0-9a-f]*$" || {
 			echo "Invalid path \"$path\"" &&
-			return 1
-			;;
-		esac
+			return 1;
+		}
 	done
 '
 
@@ -77,15 +72,10 @@ test_expect_success 'deleting most notes triggers fanout consolidation' '
 	git ls-tree -r --name-only refs/notes/commits |
 	while read path
 	do
-		case "$path" in
-		????????????????????????????????????????)
-			: true
-			;;
-		*)
+		echo $path | grep -v "^../.*" || {
 			echo "Invalid path \"$path\"" &&
-			return 1
-			;;
-		esac
+			return 1;
+		}
 	done
 '
 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 05/14] t3306: abstract away SHA-1-specific constants
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (3 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 04/14] t3305: make hash size independent brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 06/14] t3404: " brian m. carlson
                     ` (8 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.  Convert some single-line heredocs into inline
uses of echo now that they can be expressed succinctly.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3306-notes-prune.sh | 45 ++++++++++++++++++++----------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh
index 61748088eb..8f4102ff9e 100755
--- a/t/t3306-notes-prune.sh
+++ b/t/t3306-notes-prune.sh
@@ -11,23 +11,26 @@ test_expect_success 'setup: create a few commits with notes' '
 	test_tick &&
 	git commit -m 1st &&
 	git notes add -m "Note #1" &&
+	first=$(git rev-parse HEAD) &&
 	: > file2 &&
 	git add file2 &&
 	test_tick &&
 	git commit -m 2nd &&
 	git notes add -m "Note #2" &&
+	second=$(git rev-parse HEAD) &&
 	: > file3 &&
 	git add file3 &&
 	test_tick &&
 	git commit -m 3rd &&
-	COMMIT_FILE=.git/objects/5e/e1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
+	third=$(git rev-parse HEAD) &&
+	COMMIT_FILE=$(echo $third | sed "s!^..!.git/objects/&/!") &&
 	test -f $COMMIT_FILE &&
 	test-tool chmtime =+0 $COMMIT_FILE &&
 	git notes add -m "Note #3"
 '
 
 cat > expect <<END_OF_LOG
-commit 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29
+commit $third
 Author: A U Thor <author@example.com>
 Date:   Thu Apr 7 15:15:13 2005 -0700
 
@@ -36,7 +39,7 @@ Date:   Thu Apr 7 15:15:13 2005 -0700
 Notes:
     Note #3
 
-commit 08341ad9e94faa089d60fd3f523affb25c6da189
+commit $second
 Author: A U Thor <author@example.com>
 Date:   Thu Apr 7 15:14:13 2005 -0700
 
@@ -45,7 +48,7 @@ Date:   Thu Apr 7 15:14:13 2005 -0700
 Notes:
     Note #2
 
-commit ab5f302035f2e7aaf04265f08b42034c23256e1f
+commit $first
 Author: A U Thor <author@example.com>
 Date:   Thu Apr 7 15:13:13 2005 -0700
 
@@ -70,16 +73,16 @@ test_expect_success 'remove some commits' '
 
 test_expect_success 'verify that commits are gone' '
 
-	test_must_fail git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f
+	test_must_fail git cat-file -p $third &&
+	git cat-file -p $second &&
+	git cat-file -p $first
 '
 
 test_expect_success 'verify that notes are still present' '
 
-	git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
+	git notes show $third &&
+	git notes show $second &&
+	git notes show $first
 '
 
 test_expect_success 'prune -n does not remove notes' '
@@ -90,13 +93,10 @@ test_expect_success 'prune -n does not remove notes' '
 	test_cmp expect actual
 '
 
-cat > expect <<EOF
-5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29
-EOF
 
 test_expect_success 'prune -n lists prunable notes' '
 
-
+	echo $third >expect &&
 	git notes prune -n > actual &&
 	test_cmp expect actual
 '
@@ -109,9 +109,9 @@ test_expect_success 'prune notes' '
 
 test_expect_success 'verify that notes are gone' '
 
-	test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
+	test_must_fail git notes show $third &&
+	git notes show $second &&
+	git notes show $first
 '
 
 test_expect_success 'remove some commits' '
@@ -121,21 +121,18 @@ test_expect_success 'remove some commits' '
 	git gc --prune=now
 '
 
-cat > expect <<EOF
-08341ad9e94faa089d60fd3f523affb25c6da189
-EOF
-
 test_expect_success 'prune -v notes' '
 
+	echo $second >expect &&
 	git notes prune -v > actual &&
 	test_cmp expect actual
 '
 
 test_expect_success 'verify that notes are gone' '
 
-	test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 &&
-	test_must_fail git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 &&
-	git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f
+	test_must_fail git notes show $third &&
+	test_must_fail git notes show $second &&
+	git notes show $first
 '
 
 test_done

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 06/14] t3404: abstract away SHA-1-specific constants
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (4 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 05/14] t3306: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 07/14] t3430: avoid hard-coded object IDs brian m. carlson
                     ` (7 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Adjust the test so that it computes variables for object IDs instead of
using hard-coded hashes.  Add a use of $EMPTY_TREE instead of a
hard-coded value.  Remove a comment about hard-coded hashes which is no
longer applicable.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3404-rebase-interactive.sh | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 461dd539ff..87ee69f78e 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -29,9 +29,6 @@ Initial setup:
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
-# WARNING: Modifications to the initial repository can change the SHA ID used
-# in the expect2 file for the 'stop on conflicting pick' test.
-
 test_expect_success 'setup' '
 	test_commit A file1 &&
 	test_commit B file1 &&
@@ -233,25 +230,28 @@ test_expect_success 'exchange two commits' '
 	set_fake_editor &&
 	FAKE_LINES="2 1" git rebase -i HEAD~2 &&
 	test H = $(git cat-file commit HEAD^ | sed -ne \$p) &&
-	test G = $(git cat-file commit HEAD | sed -ne \$p)
+	test G = $(git cat-file commit HEAD | sed -ne \$p) &&
+	blob1=$(git rev-parse --short HEAD^:file1) &&
+	blob2=$(git rev-parse --short HEAD:file1) &&
+	commit=$(git rev-parse --short HEAD)
 '
 
 test_expect_success 'stop on conflicting pick' '
-	cat >expect <<-\EOF &&
+	cat >expect <<-EOF &&
 	diff --git a/file1 b/file1
-	index f70f10e..fd79235 100644
+	index $blob1..$blob2 100644
 	--- a/file1
 	+++ b/file1
 	@@ -1 +1 @@
 	-A
 	+G
 	EOF
-	cat >expect2 <<-\EOF &&
+	cat >expect2 <<-EOF &&
 	<<<<<<< HEAD
 	D
 	=======
 	G
-	>>>>>>> 5d18e54... G
+	>>>>>>> $commit... G
 	EOF
 	git tag new-branch1 &&
 	set_fake_editor &&
@@ -1003,7 +1003,7 @@ test_expect_success 'rebase -i --root temporary sentinel commit' '
 	git checkout B &&
 	set_fake_editor &&
 	test_must_fail env FAKE_LINES="2" git rebase -i --root &&
-	git cat-file commit HEAD | grep "^tree 4b825dc642cb" &&
+	git cat-file commit HEAD | grep "^tree $EMPTY_TREE" &&
 	git rebase --abort
 '
 
@@ -1161,7 +1161,7 @@ test_expect_success 'rebase -i error on commits with \ in message' '
 	test_expect_code 1 grep  "	emp" error
 '
 
-test_expect_success 'short SHA-1 setup' '
+test_expect_success SHA1 'short SHA-1 setup' '
 	test_when_finished "git checkout master" &&
 	git checkout --orphan collide &&
 	git rm -rf . &&
@@ -1173,7 +1173,7 @@ test_expect_success 'short SHA-1 setup' '
 	)
 '
 
-test_expect_success 'short SHA-1 collide' '
+test_expect_success SHA1 'short SHA-1 collide' '
 	test_when_finished "reset_rebase && git checkout master" &&
 	git checkout collide &&
 	(

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 07/14] t3430: avoid hard-coded object IDs
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (5 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 06/14] t3404: " brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 08/14] t3506: make hash independent brian m. carlson
                     ` (6 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Compute the object IDs used in the todo list instead of hard-coding
them.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3430-rebase-merges.sh | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index 7b6c4847ad..c1ea2ee297 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -37,20 +37,27 @@ test_expect_success 'setup' '
 	test_commit A &&
 	git checkout -b first &&
 	test_commit B &&
+	b=$(git rev-parse --short HEAD) &&
 	git checkout master &&
 	test_commit C &&
+	c=$(git rev-parse --short HEAD) &&
 	test_commit D &&
+	d=$(git rev-parse --short HEAD) &&
 	git merge --no-commit B &&
 	test_tick &&
 	git commit -m E &&
 	git tag -m E E &&
+	e=$(git rev-parse --short HEAD) &&
 	git checkout -b second C &&
 	test_commit F &&
+	f=$(git rev-parse --short HEAD) &&
 	test_commit G &&
+	g=$(git rev-parse --short HEAD) &&
 	git checkout master &&
 	git merge --no-commit G &&
 	test_tick &&
 	git commit -m H &&
+	h=$(git rev-parse --short HEAD) &&
 	git tag -m H H &&
 	git checkout A &&
 	test_commit conflicting-G G.t
@@ -93,24 +100,24 @@ test_expect_success 'create completely different structure' '
 '
 
 test_expect_success 'generate correct todo list' '
-	cat >expect <<-\EOF &&
+	cat >expect <<-EOF &&
 	label onto
 
 	reset onto
-	pick d9df450 B
+	pick $b B
 	label E
 
 	reset onto
-	pick 5dee784 C
+	pick $c C
 	label branch-point
-	pick ca2c861 F
-	pick 088b00a G
+	pick $f F
+	pick $g G
 	label H
 
 	reset branch-point # C
-	pick 12bd07b D
-	merge -C 2051b56 E # E
-	merge -C 233d48a H # H
+	pick $d D
+	merge -C $e E # E
+	merge -C $h H # H
 
 	EOF
 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 08/14] t3506: make hash independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (6 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 07/14] t3430: avoid hard-coded object IDs brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 09/14] t3600: make hash size independent brian m. carlson
                     ` (5 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

This test uses a hard-coded object ID to ensure that the result of
cherry-pick --ff is correct.  Use test_oid to make this work for both
SHA-1 and SHA-256.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3506-cherry-pick-ff.sh | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh
index 127dd0082f..9d5adbc130 100755
--- a/t/t3506-cherry-pick-ff.sh
+++ b/t/t3506-cherry-pick-ff.sh
@@ -16,7 +16,11 @@ test_expect_success setup '
 	git add file1 &&
 	test_tick &&
 	git commit -m "second" &&
-	git tag second
+	git tag second &&
+	test_oid_cache <<-EOF
+	cp_ff sha1:1df192cd8bc58a2b275d842cede4d221ad9000d1
+	cp_ff sha256:e70d6b7fc064bddb516b8d512c9057094b96ce6ff08e12080acc4fe7f1d60a1d
+	EOF
 '
 
 test_expect_success 'cherry-pick using --ff fast forwards' '
@@ -102,7 +106,7 @@ test_expect_success 'cherry pick a root commit with --ff' '
 	git add file2 &&
 	git commit --amend -m "file2" &&
 	git cherry-pick --ff first &&
-	test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1"
+	test "$(git rev-parse --verify HEAD)" = "$(test_oid cp_ff)"
 '
 
 test_expect_success 'cherry-pick --ff on unborn branch' '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 09/14] t3600: make hash size independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (7 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 08/14] t3506: make hash independent brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 10/14] t3800: make hash-size independent brian m. carlson
                     ` (4 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Instead of hard-coding a fixed length invalid object ID in the test,
compute one using the lookup tables.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3600-rm.sh | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 66282a720e..8c8cca5bfb 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -240,12 +240,14 @@ test_expect_success 'refresh index before checking if it is up-to-date' '
 '
 
 test_expect_success 'choking "git rm" should not let it die with cruft' '
+	test_oid_init &&
 	git reset -q --hard &&
 	test_when_finished "rm -f .git/index.lock && git reset -q --hard" &&
 	i=0 &&
+	hash=$(test_oid deadbeef) &&
 	while test $i -lt 12000
 	do
-		echo "100644 1234567890123456789012345678901234567890 0	some-file-$i"
+		echo "100644 $hash 0	some-file-$i"
 		i=$(( $i + 1 ))
 	done | git update-index --index-info &&
 	git rm -n "some-file-*" | : &&

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 10/14] t3800: make hash-size independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (8 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 09/14] t3600: make hash size independent brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2020-11-23 12:01     ` [PATCH] mktag: don't check SHA-1 object length under SHA-256 Ævar Arnfjörð Bjarmason
  2019-08-26  1:43   ` [PATCH v2 11/14] t3903: abstract away SHA-1-specific constants brian m. carlson
                     ` (3 subsequent siblings)
  13 siblings, 1 reply; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Replace references to several hard-coded object IDs with a variable
referring to the generated commit.  Avoid matching on exact character
positions, which will be different depending on the hash in use.  In the
test for a valid object ID, use an obviously invalid one from the lookup
table.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3800-mktag.sh | 49 ++++++++++++++++++++++++------------------------
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 8eb47942e2..64dcc5ec28 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -23,6 +23,7 @@ check_verify_failure () {
 # first create a commit, so we have a valid object/type
 # for the tag.
 test_expect_success 'setup' '
+	test_oid_init &&
 	echo Hello >A &&
 	git update-index --add A &&
 	git commit -m "Initial commit" &&
@@ -69,28 +70,28 @@ check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
 #  4. type line label check
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 xxxx tag
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char47: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 
 ############################################################
 #  5. type line eol check
 
-echo "object 779e9b33986b1c2670fff52c5067603117b3e895" >tag.sig
+echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char48: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
 
 ############################################################
 #  6. tag line label check #1
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 type tag
 xxx mytag
 tagger . <> 0 +0000
@@ -98,37 +99,37 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char57: no "tag " found$'
+	'^error: char.*: no "tag " found$'
 
 ############################################################
 #  7. tag line label check #2
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 type taggggggggggggggggggggggggggggggg
 tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char87: no "tag " found$'
+	'^error: char.*: no "tag " found$'
 
 ############################################################
 #  8. type line type-name length check
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $head
 type taggggggggggggggggggggggggggggggg
 tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char53: type too long$'
+	'^error: char.*: type too long$'
 
 ############################################################
 #  9. verify object (SHA1/type) check
 
 cat >tag.sig <<EOF
-object 779e9b33986b1c2670fff52c5067603117b3e895
+object $(test_oid deadbeef)
 type tagggg
 tag mytag
 tagger . <> 0 +0000
@@ -150,7 +151,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char67: could not verify tag name$'
+	'^error: char.*: could not verify tag name$'
 
 ############################################################
 # 11. tagger line label check #1
@@ -164,7 +165,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char70: could not find "tagger "$'
+	'^error: char.*: could not find "tagger "$'
 
 ############################################################
 # 12. tagger line label check #2
@@ -179,7 +180,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char70: could not find "tagger "$'
+	'^error: char.*: could not find "tagger "$'
 
 ############################################################
 # 13. disallow missing tag author name
@@ -194,7 +195,7 @@ This is filler
 EOF
 
 check_verify_failure 'disallow missing tag author name' \
-	'^error: char77: missing tagger name$'
+	'^error: char.*: missing tagger name$'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -209,7 +210,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char77: malformed tagger field$'
+	'^error: char.*: malformed tagger field$'
 
 ############################################################
 # 15. allow empty tag email
@@ -238,7 +239,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 EOF
 
 check_verify_failure 'disallow spaces in tag email' \
-	'^error: char77: malformed tagger field$'
+	'^error: char.*: malformed tagger field$'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -252,7 +253,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char107: missing tag timestamp$'
+	'^error: char.*: missing tag timestamp$'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -266,7 +267,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char107: missing tag timestamp$'
+	'^error: char.*: missing tag timestamp$'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -280,7 +281,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char111: malformed tag timestamp$'
+	'^error: char.*: malformed tag timestamp$'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -294,7 +295,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char118: malformed tag timezone$'
+	'^error: char.*: malformed tag timezone$'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -308,7 +309,7 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char118: malformed tag timezone$'
+	'^error: char.*: malformed tag timezone$'
 
 ############################################################
 # 22. detect invalid tag timezone3
@@ -322,7 +323,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 EOF
 
 check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char118: malformed tag timezone$'
+	'^error: char.*: malformed tag timezone$'
 
 ############################################################
 # 23. detect invalid header entry
@@ -337,7 +338,7 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char124: trailing garbage in tag header$'
+	'^error: char.*: trailing garbage in tag header$'
 
 ############################################################
 # 24. create valid tag

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 11/14] t3903: abstract away SHA-1-specific constants
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (9 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 10/14] t3800: make hash-size independent brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 12/14] t4000: make hash size independent brian m. carlson
                     ` (2 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Abstract away the SHA-1-specific constants by sanitizing diff output to
remove the index lines, since it's clear from the assertions in question
that we are not interested in the specific object IDs.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t3903-stash.sh | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index b8e337893f..820b350aeb 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -7,6 +7,18 @@ test_description='Test git stash'
 
 . ./test-lib.sh
 
+diff_cmp () {
+	for i in "$1" "$2"
+	do
+		sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \
+		-e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \
+		-e 's/^index [0-9a-f]*,[0-9a-f]*\.\.[0-9a-f]*/index 1234567,7654321..89abcde/' \
+		"$i" >"$i.compare" || return 1
+	done &&
+	test_cmp "$1.compare" "$2.compare" &&
+	rm -f "$1.compare" "$2.compare"
+}
+
 test_expect_success 'stash some dirty working directory' '
 	echo 1 >file &&
 	git add file &&
@@ -36,7 +48,7 @@ EOF
 test_expect_success 'parents of stash' '
 	test $(git rev-parse stash^) = $(git rev-parse HEAD) &&
 	git diff stash^2..stash >output &&
-	test_cmp expect output
+	diff_cmp expect output
 '
 
 test_expect_success 'applying bogus stash does nothing' '
@@ -210,13 +222,13 @@ test_expect_success 'stash branch' '
 	test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
 	test $(git rev-parse HEAD) = $(git rev-parse master^) &&
 	git diff --cached >output &&
-	test_cmp expect output &&
+	diff_cmp expect output &&
 	git diff >output &&
-	test_cmp expect1 output &&
+	diff_cmp expect1 output &&
 	git add file &&
 	git commit -m alternate\ second &&
 	git diff master..stashbranch >output &&
-	test_cmp output expect2 &&
+	diff_cmp output expect2 &&
 	test 0 = $(git stash list | wc -l)
 '
 
@@ -577,7 +589,7 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' '
 	+bar
 	EOF
 	git stash show -p ${STASH_ID} >actual &&
-	test_cmp expected actual
+	diff_cmp expected actual
 '
 
 test_expect_success 'stash show - no stashes on stack, stash-like argument' '
@@ -609,7 +621,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' '
 	+foo
 	EOF
 	git stash show -p ${STASH_ID} >actual &&
-	test_cmp expected actual
+	diff_cmp expected actual
 '
 
 test_expect_success 'stash show --patience shows diff' '
@@ -627,7 +639,7 @@ test_expect_success 'stash show --patience shows diff' '
 	+foo
 	EOF
 	git stash show --patience ${STASH_ID} >actual &&
-	test_cmp expected actual
+	diff_cmp expected actual
 '
 
 test_expect_success 'drop: fail early if specified stash is not a stash ref' '
@@ -791,7 +803,7 @@ test_expect_success 'stash where working directory contains "HEAD" file' '
 	git diff-index --cached --quiet HEAD &&
 	test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" &&
 	git diff stash^..stash >output &&
-	test_cmp expect output
+	diff_cmp expect output
 '
 
 test_expect_success 'store called with invalid commit' '
@@ -847,7 +859,7 @@ test_expect_success 'stash list implies --first-parent -m' '
 	+working
 	EOF
 	git stash list --format=%gd -p >actual &&
-	test_cmp expect actual
+	diff_cmp expect actual
 '
 
 test_expect_success 'stash list --cc shows combined diff' '
@@ -864,7 +876,7 @@ test_expect_success 'stash list --cc shows combined diff' '
 	++working
 	EOF
 	git stash list --format=%gd -p --cc >actual &&
-	test_cmp expect actual
+	diff_cmp expect actual
 '
 
 test_expect_success 'stash is not confused by partial renames' '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 12/14] t4000: make hash size independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (10 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 11/14] t3903: abstract away SHA-1-specific constants brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 13/14] t4002: make hash independent brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 14/14] t4009: make hash size independent brian m. carlson
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Use $ZERO_OID instead of hard-coding a fixed size all-zeros object ID.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t4000-diff-format.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index 8de36b7d12..e5116a76a1 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -78,7 +78,7 @@ test_expect_success 'git diff-files --no-patch --patch shows the patch' '
 
 test_expect_success 'git diff-files --no-patch --patch-with-raw shows the patch and raw data' '
 	git diff-files --no-patch --patch-with-raw >actual &&
-	grep -q "^:100644 100755 .* 0000000000000000000000000000000000000000 M	path0\$" actual &&
+	grep -q "^:100644 100755 .* $ZERO_OID M	path0\$" actual &&
 	tail -n +4 actual >actual-patch &&
 	compare_diff_patch expected actual-patch
 '

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 13/14] t4002: make hash independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (11 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 12/14] t4000: make hash size independent brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  2019-08-26  1:43   ` [PATCH v2 14/14] t4009: make hash size independent brian m. carlson
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Factor out the hard-coded object IDs and use test_oid to provide values
for both SHA-1 and SHA-256.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t4002-diff-basic.sh | 367 +++++++++++++++++++++++++++++-------------
 1 file changed, 258 insertions(+), 109 deletions(-)

diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
index 3a6c21e825..cbcdd10464 100755
--- a/t/t4002-diff-basic.sh
+++ b/t/t4002-diff-basic.sh
@@ -7,123 +7,272 @@ test_description='Test diff raw-output.
 
 '
 . ./test-lib.sh
+
 . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh
 
-cat >.test-plain-OA <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A	AA
-:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A	AN
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 040000 0000000000000000000000000000000000000000 6d50f65d3bdab91c63444294d38f08aeff328e42 A	DF
-:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D	DM
-:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D	DN
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M	MM
-:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M	MN
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M	TT
-:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 5e5f22072bb39f6e12cf663a57cb634c76eefb49 M	Z
+test_oid_init
+
+test_oid_cache <<\EOF
+aa_1 sha1:ccba72ad3888a3520b39efcf780b9ee64167535d
+aa_1 sha256:9febfbf18197819b2735c45291f138525d2476d59470f98239647544586ba403
+
+aa_2 sha1:6aa2b5335b16431a0ef71e5c0a28be69183cf6a2
+aa_2 sha256:6eaa3437de83f145a4aaa6ba355303075ade547b128ec6a2cd00a81ff7ce7a56
+
+an_1 sha1:7e426fb079479fd67f6d81f984e4ec649a44bc25
+an_1 sha256:8f92a0bec99e399a38e3bd0e1bf19fbf121e0160efb29b857df79d439f1c4536
+
+dd_1 sha1:bcc68ef997017466d5c9094bcf7692295f588c9a
+dd_1 sha256:07e17428b00639b85485d2b01083d219e2f3e3ba8579e9ca44e9cc8dd554d952
+
+df_1 sha1:6d50f65d3bdab91c63444294d38f08aeff328e42
+df_1 sha256:e367cecc27e9bf5451b1c65828cb21938d36a5f8e39c1b03ad6509cc36bb8e9d
+
+df_2 sha1:71420ab81e254145d26d6fc0cddee64c1acd4787
+df_2 sha256:0f0a86d10347ff6921d03a3c954679f3f1d14fa3d5cd82f57b32c09755f3a47d
+
+dfd1 sha1:68a6d8b91da11045cf4aa3a5ab9f2a781c701249
+dfd1 sha256:f3bd3265b02b6978ce86490d8ad026c573639c974b3de1d9faf30d8d5a77d3d5
+
+dm_1 sha1:141c1f1642328e4bc46a7d801a71da392e66791e
+dm_1 sha256:c89f8656e7b94e21ee5fbaf0e2149bbf783c51edbe2ce110349cac13059ee7ed
+
+dm_2 sha1:3c4d8de5fbad08572bab8e10eef8dbb264cf0231
+dm_2 sha256:83a572e37e0c94086294dae2cecc43d9131afd6f6c906e495c78972230b54988
+
+dn_1 sha1:35abde1506ddf806572ff4d407bd06885d0f8ee9
+dn_1 sha256:775d5852582070e620be63327bfa515fab8f71c7ac3e4f0c3cd6267b4377ba28
+
+ll_2 sha1:1d41122ebdd7a640f29d3c9cc4f9d70094374762
+ll_2 sha256:7917b4948a883cfed0a77d3d5a625dc8577d6ddcc3c6c3bbc56c4d4226a2246d
+
+md_1 sha1:03f24c8c4700babccfd28b654e7e8eac402ad6cd
+md_1 sha256:fc9f30369b978595ad685ba11ca9a17de0af16d79cd4b629975f4f1590033902
+
+md_2 sha1:103d9f89b50b9aad03054b579be5e7aa665f2d57
+md_2 sha256:fc78ec75275628762fe520479a6b2398dec295ce7aabcb1d15e5963c7b4e9317
+
+mm_1 sha1:b258508afb7ceb449981bd9d63d2d3e971bf8d34
+mm_1 sha256:a4b7847d228e900e3000285e240c20fd96f9dd41ce1445305f6eada126d4a04a
+
+mm_2 sha1:b431b272d829ff3aa4d1a5085f4394ab4d3305b6
+mm_2 sha256:3f8b83ea36aacf689bcf1a1290a9a8ed341564d32682ea6f76fea9a979186782
+
+mm_3 sha1:19989d4559aae417fedee240ccf2ba315ea4dc2b
+mm_3 sha256:71b3bfc5747ac033fff9ea0ab39ee453a3af2969890e75d6ef547b87544e2681
+
+mn_1 sha1:bd084b0c27c7b6cc34f11d6d0509a29be3caf970
+mn_1 sha256:47a67450583d7a329eb01a7c4ba644945af72c0ed2c7c95eb5a00d6e46d4d483
+
+mn_2 sha1:a716d58de4a570e0038f5c307bd8db34daea021f
+mn_2 sha256:f95104c1ebe27acb84bac25a7be98c71f6b8d3054b21f357a5be0c524ad97e08
+
+nm_1 sha1:c8f25781e8f1792e3e40b74225e20553041b5226
+nm_1 sha256:09baddc7afaa62e62e152c23c9c3ab94bf15a3894031e227e9be7fe68e1f4e49
+
+nm_2 sha1:cdb9a8c3da571502ac30225e9c17beccb8387983
+nm_2 sha256:58b5227956ac2d2a08d0efa513c0ae37430948b16791ea3869a1308dbf05536d
+
+na_1 sha1:15885881ea69115351c09b38371f0348a3fb8c67
+na_1 sha256:18e4fdd1670cd7968ee23d35bfd29e5418d56fb190c840094c1c57ceee0aad8f
+
+nd_1 sha1:a4e179e4291e5536a5e1c82e091052772d2c5a93
+nd_1 sha256:07dac9b01d00956ea0c65bd993d7de4864aeef2ed3cbb1255d9f1d949fcd6df6
+
+ss_1 sha1:40c959f984c8b89a2b02520d17f00d717f024397
+ss_1 sha256:50fc1b5df74d9910db2f9270993484235f15b69b75b01bcfb53e059289d14af9
+
+ss_2 sha1:2ac547ae9614a00d1b28275de608131f7a0e259f
+ss_2 sha256:a90f02e6044f1497d13db587d22ab12f90150a7d1e084afcf96065fab35ae2bc
+
+tt_1 sha1:4ac13458899ab908ef3b1128fa378daefc88d356
+tt_1 sha256:c53113c7dd5060e86b5b251428bd058f6726f66273c6a24bff1c61a04f498dd3
+
+tt_2 sha1:4c86f9a85fbc5e6804ee2e17a797538fbe785bca
+tt_2 sha256:0775f2a296129a7cf2862b46bc0e88c14d593f2773a3e3fb1c5193db6f5a7e77
+
+tt_3 sha1:c4e4a12231b9fa79a0053cb6077fcb21bb5b135a
+tt_3 sha256:47860f93cdd211f96443e0560f21c57ab6c2f4b0ac27ff03651a352e53fe8484
+
+z__1 sha1:7d670fdcdb9929f6c7dac196ff78689cd1c566a1
+z__1 sha256:44d0f37aff5e51cfcfdd1134c93a6419bcca7b9964f792ffcd5f9b4fcba1ee63
+
+z__2 sha1:5e5f22072bb39f6e12cf663a57cb634c76eefb49
+z__2 sha256:d29de162113190fed104eb5f010820cef4e315f89b9326e8497f7219fb737894
+
+z__3 sha1:1ba523955d5160681af65cb776411f574c1e8155
+z__3 sha256:07422d772b07794ab4369a5648e617719f89c2d2212cbeab05d97214b6471636
+
+zaa1 sha1:8acb8e9750e3f644bf323fcf3d338849db106c77
+zaa1 sha256:e79b029282c8abec2d9f3f7faceaf2a1405e02d1f368e66450ae66cf5b68d1f4
+
+zaa2 sha1:6c0b99286d0bce551ac4a7b3dff8b706edff3715
+zaa2 sha256:c82bd78c3e69ea1796e6b1a7a3ba45bb106c50e819296475b862123d3f5cc5a0
+
+zan1 sha1:087494262084cefee7ed484d20c8dc0580791272
+zan1 sha256:4b159eb3804d05599023dd074f771d06d02870f4ab24a7165add8ac3d703b8d3
+
+zdd1 sha1:879007efae624d2b1307214b24a956f0a8d686a8
+zdd1 sha256:eecfdd4d8092dd0363fb6d4548b54c6afc8982c3ed9b34e393f1d6a921d8eaa3
+
+zdm1 sha1:9b541b2275c06e3a7b13f28badf5294e2ae63df4
+zdm1 sha256:ab136e88e19a843c4bf7713d2090d5a2186ba16a6a80dacc12eeddd256a8e556
+
+zdm2 sha1:d77371d15817fcaa57eeec27f770c505ba974ec1
+zdm2 sha256:1c1a5f57363f46a15d95ce8527b3c2c158d88d16853b4acbf81bd20fd2c89a46
+
+zdn1 sha1:beb5d38c55283d280685ea21a0e50cfcc0ca064a
+zdn1 sha256:0f0eca66183617b0aa5ad74b256540329f841470922ca6760263c996d825eb18
+
+zmd1 sha1:d41fda41b7ec4de46b43cb7ea42a45001ae393d5
+zmd1 sha256:1ed32d481852eddf31a0ce12652a0ad14bf5b7a842667b5dbb0b50f35bf1c80a
+
+zmd2 sha1:a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9
+zmd2 sha256:b238da211b404f8917df2d9c6f7030535e904b2186131007a3c292ec6902f933
+
+zmm1 sha1:4ca22bae2527d3d9e1676498a0fba3b355bd1278
+zmm1 sha256:072b1d85b5f34fabc99dfa46008c5418df68302d3e317430006f49b32d244226
+
+zmm2 sha1:61422ba9c2c873416061a88cd40a59a35b576474
+zmm2 sha256:81dd5d2b3c5cda16fef552256aed4e2ea0802a8450a08f308a92142112ff6dda
+
+zmm3 sha1:697aad7715a1e7306ca76290a3dd4208fbaeddfa
+zmm3 sha256:8b10fab49e9be3414aa5e9a93d0e46f9569053440138a7c19a5eb5536d8e95bf
+
+zmn1 sha1:b16d7b25b869f2beb124efa53467d8a1550ad694
+zmn1 sha256:609e4f75d1295e844c826feeba213acb0b6cfc609adfe8ff705b19e3829ae3e9
+
+zmn2 sha1:a5c544c21cfcb07eb80a4d89a5b7d1570002edfd
+zmn2 sha256:d6d03edf2dc1a3b267a8205de5f41a2ff4b03def8c7ae02052b543fb09d589fc
+
+zna1 sha1:d12979c22fff69c59ca9409e7a8fe3ee25eaee80
+zna1 sha256:b37b80e789e8ea32aa323f004628f02013f632124b0282c7fe00a127d3c64c3c
+
+znd1 sha1:a18393c636b98e9bd7296b8b437ea4992b72440c
+znd1 sha256:af92a22eee8c38410a0c9d2b5135a10aeb052cbc7cf675541ed9a67bfcaf7cf9
+
+znm1 sha1:3fdbe17fd013303a2e981e1ca1c6cd6e72789087
+znm1 sha256:f75aeaa0c11e76918e381c105f0752932c6150e941fec565d24fa31098a13dc1
+
+znm2 sha1:7e09d6a3a14bd630913e8c75693cea32157b606d
+znm2 sha256:938d73cfbaa1c902a84fb5b3afd9736aa0590367fb9bd59c6c4d072ce70fcd6d
+EOF
+
+cat >.test-plain-OA <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_1) A	AA
+:000000 100644 $(test_oid zero) $(test_oid an_1) A	AN
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 040000 $(test_oid zero) $(test_oid df_1) A	DF
+:100644 000000 $(test_oid dm_1) $(test_oid zero) D	DM
+:100644 000000 $(test_oid dn_1) $(test_oid zero) D	DN
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 100644 $(test_oid md_1) $(test_oid md_2) M	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_2) M	MM
+:100644 100644 $(test_oid mn_1) $(test_oid mn_2) M	MN
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_2) M	TT
+:040000 040000 $(test_oid z__1) $(test_oid z__2) M	Z
 EOF
 
-cat >.test-recursive-OA <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A	AA
-:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A	AN
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 100644 0000000000000000000000000000000000000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 A	DF/DF
-:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D	DM
-:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D	DN
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M	MM
-:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M	MN
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M	TT
-:000000 100644 0000000000000000000000000000000000000000 8acb8e9750e3f644bf323fcf3d338849db106c77 A	Z/AA
-:000000 100644 0000000000000000000000000000000000000000 087494262084cefee7ed484d20c8dc0580791272 A	Z/AN
-:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D	Z/DD
-:100644 000000 9b541b2275c06e3a7b13f28badf5294e2ae63df4 0000000000000000000000000000000000000000 D	Z/DM
-:100644 000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a 0000000000000000000000000000000000000000 D	Z/DN
-:100644 100644 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 M	Z/MD
-:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 61422ba9c2c873416061a88cd40a59a35b576474 M	Z/MM
-:100644 100644 b16d7b25b869f2beb124efa53467d8a1550ad694 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd M	Z/MN
+cat >.test-recursive-OA <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_1) A	AA
+:000000 100644 $(test_oid zero) $(test_oid an_1) A	AN
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 100644 $(test_oid zero) $(test_oid dfd1) A	DF/DF
+:100644 000000 $(test_oid dm_1) $(test_oid zero) D	DM
+:100644 000000 $(test_oid dn_1) $(test_oid zero) D	DN
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 100644 $(test_oid md_1) $(test_oid md_2) M	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_2) M	MM
+:100644 100644 $(test_oid mn_1) $(test_oid mn_2) M	MN
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_2) M	TT
+:000000 100644 $(test_oid zero) $(test_oid zaa1) A	Z/AA
+:000000 100644 $(test_oid zero) $(test_oid zan1) A	Z/AN
+:100644 000000 $(test_oid zdd1) $(test_oid zero) D	Z/DD
+:100644 000000 $(test_oid zdm1) $(test_oid zero) D	Z/DM
+:100644 000000 $(test_oid zdn1) $(test_oid zero) D	Z/DN
+:100644 100644 $(test_oid zmd1) $(test_oid zmd2) M	Z/MD
+:100644 100644 $(test_oid zmm1) $(test_oid zmm2) M	Z/MM
+:100644 100644 $(test_oid zmn1) $(test_oid zmn2) M	Z/MN
 EOF
-cat >.test-plain-OB <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A	AA
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M	DM
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 1ba523955d5160681af65cb776411f574c1e8155 M	Z
+cat >.test-plain-OB <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_2) A	AA
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:100644 100644 $(test_oid dm_1) $(test_oid dm_2) M	DM
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 000000 $(test_oid md_1) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_3) M	MM
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_3) M	TT
+:040000 040000 $(test_oid z__1) $(test_oid z__3) M	Z
 EOF
-cat >.test-recursive-OB <<\EOF
-:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A	AA
-:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D	DD
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M	DM
-:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A	LL
-:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M	SS
-:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:000000 100644 0000000000000000000000000000000000000000 6c0b99286d0bce551ac4a7b3dff8b706edff3715 A	Z/AA
-:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D	Z/DD
-:100644 100644 9b541b2275c06e3a7b13f28badf5294e2ae63df4 d77371d15817fcaa57eeec27f770c505ba974ec1 M	Z/DM
-:100644 000000 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 0000000000000000000000000000000000000000 D	Z/MD
-:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 697aad7715a1e7306ca76290a3dd4208fbaeddfa M	Z/MM
-:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A	Z/NA
-:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D	Z/ND
-:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M	Z/NM
+cat >.test-recursive-OB <<EOF
+:000000 100644 $(test_oid zero) $(test_oid aa_2) A	AA
+:100644 000000 $(test_oid dd_1) $(test_oid zero) D	DD
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:100644 100644 $(test_oid dm_1) $(test_oid dm_2) M	DM
+:000000 100644 $(test_oid zero) $(test_oid ll_2) A	LL
+:100644 000000 $(test_oid md_1) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_1) $(test_oid mm_3) M	MM
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M	SS
+:100644 100644 $(test_oid tt_1) $(test_oid tt_3) M	TT
+:000000 100644 $(test_oid zero) $(test_oid zaa2) A	Z/AA
+:100644 000000 $(test_oid zdd1) $(test_oid zero) D	Z/DD
+:100644 100644 $(test_oid zdm1) $(test_oid zdm2) M	Z/DM
+:100644 000000 $(test_oid zmd1) $(test_oid zero) D	Z/MD
+:100644 100644 $(test_oid zmm1) $(test_oid zmm3) M	Z/MM
+:000000 100644 $(test_oid zero) $(test_oid zna1) A	Z/NA
+:100644 000000 $(test_oid znd1) $(test_oid zero) D	Z/ND
+:100644 100644 $(test_oid znm1) $(test_oid znm2) M	Z/NM
 EOF
-cat >.test-plain-AB <<\EOF
-:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M	AA
-:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D	AN
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:040000 000000 6d50f65d3bdab91c63444294d38f08aeff328e42 0000000000000000000000000000000000000000 D	DF
-:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A	DM
-:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A	DN
-:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M	MN
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:040000 040000 5e5f22072bb39f6e12cf663a57cb634c76eefb49 1ba523955d5160681af65cb776411f574c1e8155 M	Z
+cat >.test-plain-AB <<EOF
+:100644 100644 $(test_oid aa_1) $(test_oid aa_2) M	AA
+:100644 000000 $(test_oid an_1) $(test_oid zero) D	AN
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:040000 000000 $(test_oid df_1) $(test_oid zero) D	DF
+:000000 100644 $(test_oid zero) $(test_oid dm_2) A	DM
+:000000 100644 $(test_oid zero) $(test_oid dn_1) A	DN
+:100644 000000 $(test_oid md_2) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_2) $(test_oid mm_3) M	MM
+:100644 100644 $(test_oid mn_2) $(test_oid mn_1) M	MN
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid tt_2) $(test_oid tt_3) M	TT
+:040000 040000 $(test_oid z__2) $(test_oid z__3) M	Z
 EOF
-cat >.test-recursive-AB <<\EOF
-:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M	AA
-:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D	AN
-:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A	DF
-:100644 000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 0000000000000000000000000000000000000000 D	DF/DF
-:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A	DM
-:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A	DN
-:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D	MD
-:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M	MM
-:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M	MN
-:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A	NA
-:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D	ND
-:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M	NM
-:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M	TT
-:100644 100644 8acb8e9750e3f644bf323fcf3d338849db106c77 6c0b99286d0bce551ac4a7b3dff8b706edff3715 M	Z/AA
-:100644 000000 087494262084cefee7ed484d20c8dc0580791272 0000000000000000000000000000000000000000 D	Z/AN
-:000000 100644 0000000000000000000000000000000000000000 d77371d15817fcaa57eeec27f770c505ba974ec1 A	Z/DM
-:000000 100644 0000000000000000000000000000000000000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a A	Z/DN
-:100644 000000 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 0000000000000000000000000000000000000000 D	Z/MD
-:100644 100644 61422ba9c2c873416061a88cd40a59a35b576474 697aad7715a1e7306ca76290a3dd4208fbaeddfa M	Z/MM
-:100644 100644 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd b16d7b25b869f2beb124efa53467d8a1550ad694 M	Z/MN
-:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A	Z/NA
-:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D	Z/ND
-:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M	Z/NM
+cat >.test-recursive-AB <<EOF
+:100644 100644 $(test_oid aa_1) $(test_oid aa_2) M	AA
+:100644 000000 $(test_oid an_1) $(test_oid zero) D	AN
+:000000 100644 $(test_oid zero) $(test_oid df_2) A	DF
+:100644 000000 $(test_oid dfd1) $(test_oid zero) D	DF/DF
+:000000 100644 $(test_oid zero) $(test_oid dm_2) A	DM
+:000000 100644 $(test_oid zero) $(test_oid dn_1) A	DN
+:100644 000000 $(test_oid md_2) $(test_oid zero) D	MD
+:100644 100644 $(test_oid mm_2) $(test_oid mm_3) M	MM
+:100644 100644 $(test_oid mn_2) $(test_oid mn_1) M	MN
+:000000 100644 $(test_oid zero) $(test_oid na_1) A	NA
+:100644 000000 $(test_oid nd_1) $(test_oid zero) D	ND
+:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M	NM
+:100644 100644 $(test_oid tt_2) $(test_oid tt_3) M	TT
+:100644 100644 $(test_oid zaa1) $(test_oid zaa2) M	Z/AA
+:100644 000000 $(test_oid zan1) $(test_oid zero) D	Z/AN
+:000000 100644 $(test_oid zero) $(test_oid zdm2) A	Z/DM
+:000000 100644 $(test_oid zero) $(test_oid zdn1) A	Z/DN
+:100644 000000 $(test_oid zmd2) $(test_oid zero) D	Z/MD
+:100644 100644 $(test_oid zmm2) $(test_oid zmm3) M	Z/MM
+:100644 100644 $(test_oid zmn2) $(test_oid zmn1) M	Z/MN
+:000000 100644 $(test_oid zero) $(test_oid zna1) A	Z/NA
+:100644 000000 $(test_oid znd1) $(test_oid zero) D	Z/ND
+:100644 100644 $(test_oid znm1) $(test_oid znm2) M	Z/NM
 EOF
 
 cmp_diff_files_output () {

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 14/14] t4009: make hash size independent
  2019-08-26  1:43 ` [PATCH v2 00/14] Hash-independent tests, part 5 brian m. carlson
                     ` (12 preceding siblings ...)
  2019-08-26  1:43   ` [PATCH v2 13/14] t4002: make hash independent brian m. carlson
@ 2019-08-26  1:43   ` brian m. carlson
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2019-08-26  1:43 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Eric Sunshine, Johannes Schindelin

Instead of hard-coding object IDs, compute them and use those in the
comparison.  Note that the comparison code ignores the actual object
IDs, but does check that they're the right size, so computing them is
the easiest way to ensure that they are.

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
---
 t/t4009-diff-rename-4.sh | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index 3641fd84d6..b63bdf031f 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -14,6 +14,7 @@ test_expect_success \
     'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING &&
      echo frotz >rezrov &&
     git update-index --add COPYING rezrov &&
+    orig=$(git hash-object COPYING) &&
     tree=$(git write-tree) &&
     echo $tree'
 
@@ -22,6 +23,8 @@ test_expect_success \
     'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 &&
     sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 &&
     rm -f COPYING &&
+    c1=$(git hash-object COPYING.1) &&
+    c2=$(git hash-object COPYING.2) &&
     git update-index --add --remove COPYING COPYING.?'
 
 # tree has COPYING and rezrov.  work tree has COPYING.1 and COPYING.2,
@@ -31,11 +34,11 @@ test_expect_success \
 
 git diff-index -z -C $tree >current
 
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
+cat >expected <<EOF
+:100644 100644 $orig $c1 C1234
 COPYING
 COPYING.1
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234
+:100644 100644 $orig $c2 R1234
 COPYING
 COPYING.2
 EOF
@@ -57,10 +60,10 @@ test_expect_success \
 # about rezrov.
 
 git diff-index -z -C $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M
+cat >expected <<EOF
+:100644 100644 $orig $c2 M
 COPYING
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
+:100644 100644 $orig $c1 C1234
 COPYING
 COPYING.1
 EOF
@@ -82,8 +85,8 @@ test_expect_success \
      git update-index --add --remove COPYING COPYING.1'
 
 git diff-index -z -C --find-copies-harder $tree >current
-cat >expected <<\EOF
-:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
+cat >expected <<EOF
+:100644 100644 $orig $c1 C1234
 COPYING
 COPYING.1
 EOF

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2019-08-26  1:43   ` [PATCH v2 10/14] t3800: make hash-size independent brian m. carlson
@ 2020-11-23 12:01     ` Ævar Arnfjörð Bjarmason
  2020-11-23 19:01       ` Junio C Hamano
  2020-11-23 21:34       ` Jeff King
  0 siblings, 2 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-23 12:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the hardcoded minimum tag length size to vary based on whether
we're operating in the SHA-1 or SHA-256 mode, and update the "mktag"
documentation, tests and code comments to reflect that this command
can take either SHA-1 or SHA-256 input.

Let's make the code more self-documenting by verbosely inlining what a
minimum tag looks like. The fixed-string strlen() will be optimized
away by any modern compiler. This also future-proofs us for any future
hash function transition.

Then change the tests amended in acb49d1cc8b (t3800: make hash-size
independent, 2019-08-18) even more for SHA-256. Some of the tests were
failing for the wrong reasons. E.g. yes <some sha-1 length garbage> is
an invalid SHA-1, but we should test <some sha256 length garbage> when
under SHA-256. For testing an invalid non-hexadecimal object ID let's
use ROT13.

For the "object line label check" test the "139e9b339..." SHA-1 didn't
exist, but what's actually being tested there is getting "xxxxxx"
instead of "object", so let's provide a valid SHA there
instead. There's no need to make or hardcode a nonexisting object ID.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt |  2 +-
 builtin/mktag.c             | 26 +++++++++++++-------
 t/t3800-mktag.sh            | 47 ++++++++++++++++++++++++++-----------
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index fa6a7561236..bbcc0a086bf 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -23,7 +23,7 @@ Tag Format
 A tag signature file, to be fed to this command's standard input,
 has a very simple fixed format: four lines of
 
-  object <sha1>
+  object <sha>
   type <typename>
   tag <tagname>
   tagger <tagger>
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4982d3a93ef..3fa17243e34 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -5,13 +5,15 @@
 
 /*
  * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
+ * of "object <sha>" + "type <typename>" + "tag <tagname>" +
  * "tagger <committer>", followed by a blank line, a free-form tag
  * message and a signature block that git itself doesn't care about,
  * but that can be verified with gpg or similar.
  *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
+ * The first four lines are guaranteed to be either 83 or 107 bytes;
+ * depending on whether we're referencing a SHA-1 or SHA-256 tag.
+ *
+ * "object <sha1>\n" is 48 or a 72 bytes, "type tag\n" at 9 bytes is the
  * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
  * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
  * the shortest possible tagger-line.
@@ -46,9 +48,17 @@ static int verify_tag(char *buffer, unsigned long size)
 	struct object_id oid;
 	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
 	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
+	int minimum_size =
+		/* Minimum possible input, see t/t3800-mktag.sh */
+		strlen("object ") + the_hash_algo->hexsz + strlen("\n") +
+		strlen("type tag\n") +
+		strlen("tag x\n") +
+		strlen("tagger . <> 0 +0000\n") +
+		strlen("\n");
+
+	if (size < minimum_size)
+		return error("got %"PRIuMAX" bytes of input, need at least %d bytes",
+			     size, minimum_size);
 
 	buffer[size] = 0;
 
@@ -58,7 +68,7 @@ static int verify_tag(char *buffer, unsigned long size)
 		return error("char%d: does not start with \"object \"", 0);
 
 	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
+		return error("char%d: expected object ID, got garbage", 7);
 
 	/* Verify type line */
 	type_line = p + 1;
@@ -166,7 +176,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	}
 
 	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
+	   "object <sha>\ntype\ntagger " */
 	if (verify_tag(buf.buf, buf.len) < 0)
 		die("invalid tag signature file");
 
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d696aa4e52e..93a19bb8df9 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -26,24 +26,42 @@ test_expect_success 'setup' '
 	echo Hello >A &&
 	git update-index --add A &&
 	git commit -m "Initial commit" &&
-	head=$(git rev-parse --verify HEAD)
+	head=$(git rev-parse --verify HEAD) &&
+
+	git tag -m"some tag" annotated &&
+	annotated=$(git rev-parse --verify annotated)
 '
 
 ############################################################
 #  1. length check
-
-cat >tag.sig <<EOF
-too short for a tag
-EOF
-
-check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+for objType in t ta tag
+do
+	cat >tag.sig <<-EOF
+	object $annotated
+	type $objType
+	tag x
+	tagger . <> 0 +0000
+
+	EOF
+	len=$(wc -c tag.sig)
+
+	if test $objType = "tag"
+	then
+		test_expect_success "Tag object length check $len passed" '
+			git mktag <tag.sig >.git/refs/tags/x 2>message &&
+			git rev-parse refs/tags/x
+		'
+	else
+		check_verify_failure "Tag object length check on length $len" \
+			'^error: got .* bytes of input, need at least'
+	fi
+done
 
 ############################################################
 #  2. object line label check
 
 cat >tag.sig <<EOF
-xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
+xxxxxx $head
 type tag
 tag mytag
 tagger . <> 0 +0000
@@ -53,17 +71,18 @@ EOF
 check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
 
 ############################################################
-#  3. object line SHA1 check
+#  3. object line SHA check
 
+invalid_sha=$(echo $head | tr A-Za-z N-ZA-Mn-za-m)
 cat >tag.sig <<EOF
-object zz9e9b33986b1c2670fff52c5067603117b3e895
+object $invalid_sha
 type tag
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line object check' '^error: char7: .*expected object ID, got garbage'
 
 ############################################################
 #  4. type line label check
@@ -125,7 +144,7 @@ check_verify_failure '"type" line type-name length check' \
 	'^error: char.*: type too long$'
 
 ############################################################
-#  9. verify object (SHA1/type) check
+#  9. verify object (SHA/type) check
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
@@ -135,7 +154,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure 'verify object (SHA1/type) check' \
+check_verify_failure 'verify object (SHA/type) check' \
 	'^error: char7: could not verify object.*$'
 
 ############################################################
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2020-11-23 12:01     ` [PATCH] mktag: don't check SHA-1 object length under SHA-256 Ævar Arnfjörð Bjarmason
@ 2020-11-23 19:01       ` Junio C Hamano
  2020-11-23 21:36         ` Jeff King
  2020-11-23 21:34       ` Jeff King
  1 sibling, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-11-23 19:01 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
> index fa6a7561236..bbcc0a086bf 100644
> --- a/Documentation/git-mktag.txt
> +++ b/Documentation/git-mktag.txt
> @@ -23,7 +23,7 @@ Tag Format
>  A tag signature file, to be fed to this command's standard input,
>  has a very simple fixed format: four lines of
>  
> -  object <sha1>
> +  object <sha>

Perhaps <hash>? or <objectname>.

> diff --git a/builtin/mktag.c b/builtin/mktag.c
> index 4982d3a93ef..3fa17243e34 100644
> --- a/builtin/mktag.c
> +++ b/builtin/mktag.c
> @@ -5,13 +5,15 @@
>  
>  /*
>   * A signature file has a very simple fixed format: four lines
> - * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
> + * of "object <sha>" + "type <typename>" + "tag <tagname>" +

Ditto.

>   * "tagger <committer>", followed by a blank line, a free-form tag
>   * message and a signature block that git itself doesn't care about,
>   * but that can be verified with gpg or similar.
>   *
> + * The first four lines are guaranteed to be either 83 or 107 bytes;
> + * depending on whether we're referencing a SHA-1 or SHA-256 tag.
> + *
> + * "object <sha1>\n" is 48 or a 72 bytes, "type tag\n" at 9 bytes is the

At least <sha> to be consistent with the above, or <hash>.

>   * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
>   * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
>   * the shortest possible tagger-line.
> @@ -46,9 +48,17 @@ static int verify_tag(char *buffer, unsigned long size)
>  	struct object_id oid;
>  	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
>  	size_t len;
> -
> -	if (size < 84)
> -		return error("wanna fool me ? you obviously got the size wrong !");
> +	int minimum_size =
> +		/* Minimum possible input, see t/t3800-mktag.sh */
> +		strlen("object ") + the_hash_algo->hexsz + strlen("\n") +
> +		strlen("type tag\n") +
> +		strlen("tag x\n") +
> +		strlen("tagger . <> 0 +0000\n") +
> +		strlen("\n");
> +
> +	if (size < minimum_size)
> +		return error("got %"PRIuMAX" bytes of input, need at least %d bytes",
> +			     size, minimum_size);

I agree with the patch that this message is not _("marked for
translation"), as it is output from a plumbing.

You need to cast "size" as "(uintmax_t)size" here, probably.  


> @@ -58,7 +68,7 @@ static int verify_tag(char *buffer, unsigned long size)
>  		return error("char%d: does not start with \"object \"", 0);
>  
>  	if (parse_oid_hex(object + 7, &oid, &p))
> -		return error("char%d: could not get SHA1 hash", 7);
> +		return error("char%d: expected object ID, got garbage", 7);

Here you say object ID, which is better than <hash> or <sha>.  Let's
be consistent (I'd say "object name" if I were choosing which to
use).

>  	/* Verify it for some basic sanity: it needs to start with
> -	   "object <sha1>\ntype\ntagger " */
> +	   "object <sha>\ntype\ntagger " */

Here it is <sha>.

> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index d696aa4e52e..93a19bb8df9 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -26,24 +26,42 @@ test_expect_success 'setup' '
>  	echo Hello >A &&
>  	git update-index --add A &&
>  	git commit -m "Initial commit" &&
> -	head=$(git rev-parse --verify HEAD)
> +	head=$(git rev-parse --verify HEAD) &&
> +
> +	git tag -m"some tag" annotated &&

A SP between -m and its argument, like four lines above?

> +	annotated=$(git rev-parse --verify annotated)
>  '
>  
>  ############################################################
>  #  1. length check
> +for objType in t ta tag

cute ;-)

> +do
> +	cat >tag.sig <<-EOF
> +	object $annotated
> +	type $objType
> +	tag x
> +	tagger . <> 0 +0000
> +
> +	EOF
> +	len=$(wc -c tag.sig)
> +
> +	if test $objType = "tag"
> +	then
> +		test_expect_success "Tag object length check $len passed" '

Here $len may see excess leading whitespace depending on what "wc
-c" on the platform does, but the only effect of that is a bit
uglier test title, so it would be oK.

> +			git mktag <tag.sig >.git/refs/tags/x 2>message &&

Do we use "message" in any way?  

Let's not write directly into filesystem; instead do

			tagobj=$(git mktag <tag.sig) &&
			git update-ref refs/tags/x $tagobj &&

or something like that.

> +			git rev-parse refs/tags/x
> +		'
> +	else
> +		check_verify_failure "Tag object length check on length $len" \
> +			'^error: got .* bytes of input, need at least'

OK.  This is not an issue with this patch, but I do not know why we
want a subshell in check_verify_failure.  May want to clean it up
but not in this patch.

> +	fi
> +done
>  
>  ############################################################
>  #  2. object line label check
>  
>  cat >tag.sig <<EOF
> -xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
> +xxxxxx $head
>  type tag
>  tag mytag
>  tagger . <> 0 +0000
> @@ -53,17 +71,18 @@ EOF
>  check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
>  
>  ############################################################
> -#  3. object line SHA1 check
> +#  3. object line SHA check

You say "object" or "object ID" to the tester below; let's use that
consistently instead of SHA.

> +invalid_sha=$(echo $head | tr A-Za-z N-ZA-Mn-za-m)
>  cat >tag.sig <<EOF
> -object zz9e9b33986b1c2670fff52c5067603117b3e895
> +object $invalid_sha
>  type tag
>  tag mytag
>  tagger . <> 0 +0000
>  
>  EOF
>  
> -check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
> +check_verify_failure '"object" line object check' '^error: char7: .*expected object ID, got garbage'
>  
>  ############################################################
>  #  4. type line label check
> @@ -125,7 +144,7 @@ check_verify_failure '"type" line type-name length check' \
>  	'^error: char.*: type too long$'
>  
>  ############################################################
> -#  9. verify object (SHA1/type) check
> +#  9. verify object (SHA/type) check
>  
>  cat >tag.sig <<EOF
>  object $(test_oid deadbeef)
> @@ -135,7 +154,7 @@ tagger . <> 0 +0000
>  
>  EOF
>  
> -check_verify_failure 'verify object (SHA1/type) check' \
> +check_verify_failure 'verify object (SHA/type) check' \
>  	'^error: char7: could not verify object.*$'
>  
>  ############################################################

Ditto.

Thanks.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2020-11-23 12:01     ` [PATCH] mktag: don't check SHA-1 object length under SHA-256 Ævar Arnfjörð Bjarmason
  2020-11-23 19:01       ` Junio C Hamano
@ 2020-11-23 21:34       ` Jeff King
  2020-11-24  1:07         ` brian m. carlson
                           ` (13 more replies)
  1 sibling, 14 replies; 185+ messages in thread
From: Jeff King @ 2020-11-23 21:34 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Mon, Nov 23, 2020 at 01:01:11PM +0100, Ævar Arnfjörð Bjarmason wrote:

> @@ -46,9 +48,17 @@ static int verify_tag(char *buffer, unsigned long size)
>  	struct object_id oid;
>  	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
>  	size_t len;
> -
> -	if (size < 84)
> -		return error("wanna fool me ? you obviously got the size wrong !");
> +	int minimum_size =
> +		/* Minimum possible input, see t/t3800-mktag.sh */
> +		strlen("object ") + the_hash_algo->hexsz + strlen("\n") +
> +		strlen("type tag\n") +
> +		strlen("tag x\n") +
> +		strlen("tagger . <> 0 +0000\n") +
> +		strlen("\n");

This is an obvious improvement, but I have to wonder whether this kind
of "minimum size" up-front check is really buying us much. We do a lot
of fixed-size memcmps in the rest of the function.

In the early bits, like:

  if (memcmp(type_line - 1, "\ntype ", 6))
          return error("char%d: could not find \"\\ntype \"", 47);

that is saving us from going off the edge of a too-small input (though
wow, that bare "47" is really horrific).

But later, we'll do this:

  if (memcmp(tagger_line, "tagger ", 7))
           return error("char%"PRIuMAX": could not find \"tagger \"",
                   (uintmax_t) (tagger_line - buffer));

We've already parsed "tag x" at this point, and "x" can be arbitrarily
long. Are we sure we have 7 bytes of the buffer left?

The buffer always has a trailing NUL in it, so it would never match but
memcmp() is allowed to look at the whole thing (e.g., it can start at
the end, or do quadword comparisons). And that usually wouldn't matter,
but may depending on how the strbuf grows, and whether our heap buffer
is near the end of the last allocate page. Try this:

  git init
  git commit --allow-empty -m foo
  {
    echo "object $(git rev-parse HEAD)"
    echo "type commit"
    perl -e 'print "tag "; print "a" x 4026; print "\n"'
  } | git mktag

which ASan will complain about, since the "tagger" memcmp reads past the
end of the buffer (I found 4026 by running that in a loop of 1..4096).

I think this whole thing would be better written to just parse
left-to-right within the buffer, using bits like skip_prefix() that rely
on us having a trailing NUL (which we always will, and there should not
be one inside the header section).

This is how fsck_tag() does it. In fact, it seems like we could just
reuse fsck_tag() here. It wants to pass an oid to report(), but it would
be OK to use null_oid here; ultimately it just ends up back in our
callback error_func().

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2020-11-23 19:01       ` Junio C Hamano
@ 2020-11-23 21:36         ` Jeff King
  2020-11-23 22:17           ` Junio C Hamano
  0 siblings, 1 reply; 185+ messages in thread
From: Jeff King @ 2020-11-23 21:36 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Ævar Arnfjörð Bjarmason, git, brian m . carlson,
	Eric Sunshine, Johannes Schindelin

On Mon, Nov 23, 2020 at 11:01:57AM -0800, Junio C Hamano wrote:

> > @@ -58,7 +68,7 @@ static int verify_tag(char *buffer, unsigned long size)
> >  		return error("char%d: does not start with \"object \"", 0);
> >  
> >  	if (parse_oid_hex(object + 7, &oid, &p))
> > -		return error("char%d: could not get SHA1 hash", 7);
> > +		return error("char%d: expected object ID, got garbage", 7);
> 
> Here you say object ID, which is better than <hash> or <sha>.  Let's
> be consistent (I'd say "object name" if I were choosing which to
> use).

It might just be me, but "object name" makes me think we'd take any name
(e.g., a refname that resolves to an object), whereas "object id" would
mean the object's hash specifically. And in this instance we only allow
the latter.

I agree very much with your other comments that if we are changing
these, we should get away from <sha> completely.

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2020-11-23 21:36         ` Jeff King
@ 2020-11-23 22:17           ` Junio C Hamano
  2020-11-24  0:47             ` Jeff King
  0 siblings, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-11-23 22:17 UTC (permalink / raw)
  To: Jeff King
  Cc: Ævar Arnfjörð Bjarmason, git, brian m . carlson,
	Eric Sunshine, Johannes Schindelin

Jeff King <peff@peff.net> writes:

> It might just be me, but "object name" makes me think we'd take any name
> (e.g., a refname that resolves to an object), whereas "object id" would
> mean the object's hash specifically. And in this instance we only allow
> the latter.

Yeah, but glossary-content is very much explicit about this.  "name"
is the full hexadecimal hash, "identifier" is a synonym for it.  And
"id" does not even appear to be defined.  We used to call "any name
that refers to an object" an "extended SHA-1", but I haven't seen
the phrase used for a long time on the list.

> I agree very much with your other comments that if we are changing
> these, we should get away from <sha> completely.

Yup.

I've always found it cumbersome that, when I want to mean a full hex
representation, I have to say "40-byte object name".  It is not even
technically correct these days with SHA-256.

We'd probably need to update the glossary to make sure we have ways
to refer to "a way, any way, to name an object" and to "the
hexadecimal representation of the full hash value that refers to an
object".  Here is my attempt to redefine "object ID" to be the
narrower one, while losing "usually a 40-character hex" from "object
name".  I am not sure if I like the result as a whole, but it
certainly is nice to have a word or phrase shorter than "full hex
object name" to refer to it.

Thanks.

 Documentation/glossary-content.txt | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git c/Documentation/glossary-content.txt w/Documentation/glossary-content.txt
index 090c888335..e2ab920911 100644
--- c/Documentation/glossary-content.txt
+++ w/Documentation/glossary-content.txt
@@ -262,13 +262,20 @@ This commit is referred to as a "merge commit", or sometimes just a
 	identified by its <<def_object_name,object name>>. The objects usually
 	live in `$GIT_DIR/objects/`.
 
+[[def_object_id]]object ID::
+	Synonym for <<def_object_identifier,object identifier>>.
+
 [[def_object_identifier]]object identifier::
-	Synonym for <<def_object_name,object name>>.
+	An <<def_object_name, object name>> written as an
+	unabbreviated hexadecimal representation of the hash value
+	that uniquely identifies an <<def_object,object>>.
+	Also colloquially called <<def_SHA1,SHA-1>>.
 
 [[def_object_name]]object name::
-	The unique identifier of an <<def_object,object>>.  The
-	object name is usually represented by a 40 character
-	hexadecimal string.  Also colloquially called <<def_SHA1,SHA-1>>.
+	A name that identifies an <<def_object,object>> uniquely,
+	which can be given in various ways, including but not
+	limited to, the object's full <<def_object_identifier,object
+	identifier>>, a <<def_ref,ref>> that refers to the object.
 
 [[def_object_type]]object type::
 	One of the identifiers "<<def_commit_object,commit>>",

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2020-11-23 22:17           ` Junio C Hamano
@ 2020-11-24  0:47             ` Jeff King
  0 siblings, 0 replies; 185+ messages in thread
From: Jeff King @ 2020-11-24  0:47 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Ævar Arnfjörð Bjarmason, git, brian m . carlson,
	Eric Sunshine, Johannes Schindelin

On Mon, Nov 23, 2020 at 02:17:32PM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > It might just be me, but "object name" makes me think we'd take any name
> > (e.g., a refname that resolves to an object), whereas "object id" would
> > mean the object's hash specifically. And in this instance we only allow
> > the latter.
> 
> Yeah, but glossary-content is very much explicit about this.  "name"
> is the full hexadecimal hash, "identifier" is a synonym for it.  And
> "id" does not even appear to be defined.  We used to call "any name
> that refers to an object" an "extended SHA-1", but I haven't seen
> the phrase used for a long time on the list.

OK, then my "it might just be me" is clearly just me. :)

I think the distinction I laid out earlier is nicer, but it may not be
worth the trouble of trying to _change_ nomenclature at this point.
Let's see what your glossary changes say...

> I've always found it cumbersome that, when I want to mean a full hex
> representation, I have to say "40-byte object name".  It is not even
> technically correct these days with SHA-256.

Yeah, that is both long and wrong. I'd maybe say "hex object id" in some
cases, which is slightly less cumbersome and extends to sha256. And
distinguishes it from a binary object id (though see below).

>  Documentation/glossary-content.txt | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git c/Documentation/glossary-content.txt w/Documentation/glossary-content.txt
> index 090c888335..e2ab920911 100644
> --- c/Documentation/glossary-content.txt
> +++ w/Documentation/glossary-content.txt
> @@ -262,13 +262,20 @@ This commit is referred to as a "merge commit", or sometimes just a
>  	identified by its <<def_object_name,object name>>. The objects usually
>  	live in `$GIT_DIR/objects/`.
>  
> +[[def_object_id]]object ID::
> +	Synonym for <<def_object_identifier,object identifier>>.
> +
>  [[def_object_identifier]]object identifier::
> -	Synonym for <<def_object_name,object name>>.
> +	An <<def_object_name, object name>> written as an
> +	unabbreviated hexadecimal representation of the hash value
> +	that uniquely identifies an <<def_object,object>>.
> +	Also colloquially called <<def_SHA1,SHA-1>>.

You might want to touch on "binary" here, too, with something like:

  This may also be used to refer to the binary representation of the
  hash value (e.g., as found within Git trees). Unless specified, this
  term typically implies the hexadecimal representation.

But maybe that is overkill. When we are talking about the command line
interface, stdin, etc, I can't think of a place where we'd take the
binary ("hash-object -t tree", but I don't really count that).

>  [[def_object_name]]object name::
> -	The unique identifier of an <<def_object,object>>.  The
> -	object name is usually represented by a 40 character
> -	hexadecimal string.  Also colloquially called <<def_SHA1,SHA-1>>.
> +	A name that identifies an <<def_object,object>> uniquely,
> +	which can be given in various ways, including but not
> +	limited to, the object's full <<def_object_identifier,object
> +	identifier>>, a <<def_ref,ref>> that refers to the object.

This all seems like an improvement to me, though the real question is
how often the term "object name" appears in the _other_ manpages to
refer to the more limited case.

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH] mktag: don't check SHA-1 object length under SHA-256
  2020-11-23 21:34       ` Jeff King
@ 2020-11-24  1:07         ` brian m. carlson
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                           ` (12 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: brian m. carlson @ 2020-11-24  1:07 UTC (permalink / raw)
  To: Jeff King
  Cc: Ævar Arnfjörð Bjarmason, git, Junio C Hamano,
	Eric Sunshine, Johannes Schindelin

[-- Attachment #1: Type: text/plain, Size: 952 bytes --]

On 2020-11-23 at 21:34:21, Jeff King wrote:
> This is how fsck_tag() does it. In fact, it seems like we could just
> reuse fsck_tag() here. It wants to pass an oid to report(), but it would
> be OK to use null_oid here; ultimately it just ends up back in our
> callback error_func().

I would very much appreciate getting rid of this custom code.  It was a
pain during the SHA-256 transition, and even with significant effort, it
appears I missed a few parts.  Also, while I'm for casual language, its
use here is going to be a little hard to understand for non-native
speakers.

Moreover, when we start mapping objects to write the SHA-1 values into
the loose object index (which is a series I'm slowly working on), most
of this custom code is going to have to disappear or be coalesced
anyway.  If we can use an existing, more robust function now, so much
the better.
-- 
brian m. carlson (he/him or they/them)
Houston, Texas, US

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 263 bytes --]

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 00/12] make "mktag" use fsck_tag()
  2020-11-23 21:34       ` Jeff King
  2020-11-24  1:07         ` brian m. carlson
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                             ` (10 more replies)
  2020-11-26  1:28         ` [RFC/PATCH 01/12] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
                           ` (11 subsequent siblings)
  13 siblings, 11 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This is a replacement for my earlier one-off SHA-1->SHA-256 cleanup
patch, on the basis of Jeff's comment that we should just be using
fsck_tag().

I was pretty much ready to send this as a non-RFC, but as seen in
12/12 fully duplicating the mktag logic in the context of using
fsck_tag() is a bit tricker than it looks. That breakage was only
revealed by a test I added while writing this.

The result is still nicer than the current code, but even then this
series breaks the tests mid-way through (in "improve verify_object()
test coverage"), but fixes them in 12/12.

I ran out of time to make this more sensible, but wanted to send an
RFC with the current state, and in case anyone else has any better
ideas for how to deal with 12/12. This could be applied as a non-RFC
by squashing 12/12 into the "use fsck instead of custom verify_tag"
change.

Ævar Arnfjörð Bjarmason (12):
  mktag: use default strbuf_read() hint
  mktag: reword write_object_file() error
  mktag: remove redundant braces in one-line body "if"
  mktag tests: don't needlessly use a subshell
  mktag tests: remove needless SHA-1 hardcoding
  mktag tests: improve verify_object() test coverage
  fsck: add new "extra" checks for "mktag"
  mktag: use fsck instead of custom verify_tag()
  mktag: remove now-unused verify_tag() code
  mktag doc: update to explain why to use this
  mktag docs: say <hash> not <sha1>
  mktag: bring back some of the verify_object() logic

 Documentation/git-hash-object.txt |   4 +
 Documentation/git-mktag.txt       |  31 ++++-
 builtin/mktag.c                   | 207 ++++++++++--------------------
 fsck.c                            |  32 ++++-
 fsck.h                            |   2 +
 t/t1006-cat-file.sh               |   2 +-
 t/t3800-mktag.sh                  | 103 ++++++++++-----
 7 files changed, 202 insertions(+), 179 deletions(-)

-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 01/12] mktag: use default strbuf_read() hint
  2020-11-23 21:34       ` Jeff King
  2020-11-24  1:07         ` brian m. carlson
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 02/12] mktag: reword write_object_file() error Ævar Arnfjörð Bjarmason
                           ` (10 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the hardcoded hint of 2^12 to 0. The default strbuf hint is
perfectly fine here, and the only reason we were hardcoding it is
because it survived migration from a pre-strbuf fixed-sized buffer.

See fd17f5b5f77 (Replace all read_fd use with strbuf_read, and get rid
of it., 2007-09-10) for that migration.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4982d3a93e..ff7ac8e0e5 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,7 +161,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 4096) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0) {
 		die_errno("could not read from stdin");
 	}
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 02/12] mktag: reword write_object_file() error
  2020-11-23 21:34       ` Jeff King
                           ` (2 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 01/12] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 03/12] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
                           ` (9 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the error message emitted when write_object_file() fails to
make more sense. At this point we're not writing a "tag file" (which
as an aside we never do, we just write to stdout). We are writing an
annotated tag object, let's say that instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index ff7ac8e0e5..603b55aca0 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -171,7 +171,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 		die("invalid tag signature file");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
-		die("unable to write tag file");
+		die("unable to write annotated tag object");
 
 	strbuf_release(&buf);
 	printf("%s\n", oid_to_hex(&result));
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 03/12] mktag: remove redundant braces in one-line body "if"
  2020-11-23 21:34       ` Jeff King
                           ` (3 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 02/12] mktag: reword write_object_file() error Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 04/12] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
                           ` (8 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This minor stylistic churn is usually something we'd avoid, but if we
don't do this then the file after changes in subsequent commits will
only have this minor style inconsistency, so let's change this while
we're at it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 603b55aca0..dc354828f7 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,9 +161,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 0) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
-	}
 
 	/* Verify it for some basic sanity: it needs to start with
 	   "object <sha1>\ntype\ntagger " */
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 04/12] mktag tests: don't needlessly use a subshell
  2020-11-23 21:34       ` Jeff King
                           ` (4 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 03/12] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 05/12] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
                           ` (7 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The use of a subshell dates back to e9b20943b77 (t/t3800: do not use a
temporary file to hold expected result., 2008-01-04). It's not needed
anymore, if it ever was.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d696aa4e52..0e411e3c45 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,7 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		( test_must_fail git mktag <tag.sig 2>message ) &&
+		test_must_fail git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 05/12] mktag tests: remove needless SHA-1 hardcoding
  2020-11-23 21:34       ` Jeff King
                           ` (5 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 04/12] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  7:49           ` Jeff King
  2020-11-26  1:28         ` [RFC/PATCH 06/12] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
                           ` (6 subsequent siblings)
  13 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the tests amended in acb49d1cc8b (t3800: make hash-size
independent, 2019-08-18) even more to make them independent of either
SHA-1 or SHA-256.

Some of these tests were failing for the wrong reasons. The first one
being modified here would fail because the line starts with "xxxxxx"
instead of "object", the rest of the line doesn't matter. Let's just
put a valid hash on the rest of the line anyway to narrow the test
down for just the s/object/xxxxxx/ case.

The second one being modified here would fail under
GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
invalid SHA-256, but we should really be testing <some sha-256 length
garbage> when under SHA-256.

This doesn't really matter since we should be able to trust other
parts of the code to validate things in the 0-9a-f range, but let's do
it for good measure.

There's a later test which tests an invalid SHA which looks like a
valid one, to stress the "We refuse to tag something we can't
verify[...]" logic in mktag.c.

But here we're testing for a SHA-length string which contains
characters outside of the /[0-9a-f]/i set. Let's just do that with a
ROT13 invocation.

We could get really unlucky and switch to a future hash function that
just happens to produce all [0-9] output for this particular input,
but that's very unlikely.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 0e411e3c45..b5013af2aa 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -43,7 +43,7 @@ check_verify_failure 'Tag object length check' \
 #  2. object line label check
 
 cat >tag.sig <<EOF
-xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
+xxxxxx $head
 type tag
 tag mytag
 tagger . <> 0 +0000
@@ -53,10 +53,11 @@ EOF
 check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
 
 ############################################################
-#  3. object line SHA1 check
+#  3. object line SHA check
 
+invalid_sha=$(echo $head | tr A-Za-z N-ZA-Mn-za-m)
 cat >tag.sig <<EOF
-object zz9e9b33986b1c2670fff52c5067603117b3e895
+object $invalid_sha
 type tag
 tag mytag
 tagger . <> 0 +0000
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 06/12] mktag tests: improve verify_object() test coverage
  2020-11-23 21:34       ` Jeff King
                           ` (6 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 05/12] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 07/12] fsck: add new "extra" checks for "mktag" Ævar Arnfjörð Bjarmason
                           ` (5 subsequent siblings)
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The verify_object() function in "mktag.c" is tasked with ensuring that
our tag refers to a valid object. The existing test for this might
fail because it was also testing that "type taggg" didn't refer to a
valid object type (it should be "type tag").

Let's split these tests up, so we're testing all combinations of a
non-existing object and in invalid "type" line.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index b5013af2aa..3801d3a285 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -128,6 +128,28 @@ check_verify_failure '"type" line type-name length check' \
 ############################################################
 #  9. verify object (SHA1/type) check
 
+cat >tag.sig <<EOF
+object $(test_oid deadbeef)
+type tag
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (SHA1/type) check' \
+	'^error: char7: could not verify object.*$'
+
+cat >tag.sig <<EOF
+object $head
+type tagggg
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (SHA1/type) check' \
+	'^fatal: invalid object type'
+
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
 type tagggg
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 07/12] fsck: add new "extra" checks for "mktag"
  2020-11-23 21:34       ` Jeff King
                           ` (7 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 06/12] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  8:02           ` Jeff King
  2020-11-26  1:28         ` [RFC/PATCH 08/12] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
                           ` (4 subsequent siblings)
  13 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Add optional "extra" checks to fsck, these are needed to eventually
replace the custom not-quite-fsck code in mktag.c.

The mktag checks differ from fsck_tag() in several ways, one of those
is that fsck doesn't know how to refuse an object with custom headers,
and isn't strict about header and body newline separation.

Teach it how to optionally report these. I thought the best way to do
that given the current structure of the code was to add a new "extra"
category in addition to error/warn/info. Under --strict the "info"
becomes a "warn" and "warn" becomes "error". Existing users of
fsck's (and others, e.g. index-pack) --strict option rely on this.

By adding an "extra" category and only reporting it based on a flag in
fsck_options callers can opt-in to these "extra" messages, which
they'll then need to deal with in their own "error_func".

No tests are being added for this new functionality, they're added in
a subsequent commit where we teach "mktag" to use this new validation
mode.

I'm not changing fsck_commit() to validate commit objects like this
either, we could do that, but unlike in the tag case that code
wouldn't be used anywhere. If someone wants to write a "mkcommit" they
which behaves like "mktag" they can borrow or refactor this logic for
use in fsck_commit().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 fsck.c | 32 +++++++++++++++++++++++++++++++-
 fsck.h |  2 ++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/fsck.c b/fsck.c
index f82e2fe9e3..3c25df2244 100644
--- a/fsck.c
+++ b/fsck.c
@@ -80,7 +80,10 @@ static struct oidset gitmodules_done = OIDSET_INIT;
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
-	FUNC(MISSING_TAGGER_ENTRY, INFO)
+	FUNC(MISSING_TAGGER_ENTRY, INFO) \
+	/* extra (only reported when requested) */ \
+	FUNC(EXTRA_HEADER_ENTRY, EXTRA) \
+	FUNC(EXTRA_HEADER_BODY_NEWLINE, EXTRA)
 
 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
 enum fsck_msg_id {
@@ -975,6 +978,33 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (options->extra && *buffer) {
+		if (!starts_with(buffer, "\n")) {
+			/*
+			 * The verify_headers() check will allow
+			 * e.g. "[...]tagger <tagger>\nsome
+			 * garbage\n\nmessage" to pass, thinking "some
+			 * garbage" could be a custom
+			 * header. E.g. "mktag" doesn't want any
+			 * unknown headers.
+			 */
+			ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+			if (ret)
+				goto done;
+		}
+		if (starts_with(buffer, "\n\n")) {
+			/*
+			 * Some callers such as "mktag" want to
+			 * disallow "[...]tagger
+			 * <tagger>\n\n\nmessage", only allowing a
+			 * single newline for separation.
+			 */
+			ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_BODY_NEWLINE, "invalid format - headers separated body by more than one newline");
+			if (ret)
+				goto done;
+		}
+	}
+
 done:
 	strbuf_release(&sb);
 	return ret;
diff --git a/fsck.h b/fsck.h
index 69cf715e79..110efc65fd 100644
--- a/fsck.h
+++ b/fsck.h
@@ -6,6 +6,7 @@
 #define FSCK_ERROR 1
 #define FSCK_WARN 2
 #define FSCK_IGNORE 3
+#define FSCK_EXTRA 4
 
 struct fsck_options;
 struct object;
@@ -40,6 +41,7 @@ struct fsck_options {
 	unsigned strict:1;
 	int *msg_type;
 	struct oidset skiplist;
+	unsigned extra:1;
 	kh_oid_map_t *object_names;
 };
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 08/12] mktag: use fsck instead of custom verify_tag()
  2020-11-23 21:34       ` Jeff King
                           ` (8 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 07/12] fsck: add new "extra" checks for "mktag" Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  8:17           ` Jeff King
  2020-11-26  1:28         ` [RFC/PATCH 09/12] mktag: remove now-unused verify_tag() code Ævar Arnfjörð Bjarmason
                           ` (3 subsequent siblings)
  13 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

TODO: This subtly breaks one check, see the last patch in this series.

Change the validation logic in "mktag" to use fsck's fsck_tag()
instead of its own custom parser. Curiously the logic for both dates
back to the same commit[1]. Let's unify them so we're not maintaining
two sets functions to verify that a tag is OK.

Moving to fsck_tag() required teaching it to optionally use some
validations that only the old mktag code could perform. That was done
in an earlier commit, the "extraHeaderEntry" and
"extraHeaderBodyNewline" tests being added here make use of that
logic.

There was other "mktag" validation logic that I think makes sense to
just remove. Namely:

 A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
    code disallowed values larger than 1400.

    Yes there's currently no timezone with a greater offset[2], but
    since we allow any number of non-offical timezones (e.g. +1234)
    passing this through seems fine. Git also won't break in the
    future if e.g. French Polynesia decides it needs to outdo the Line
    Islands when it comes to timezone extravagance.

 B. fsck allows missing author names such as "tagger <email>", mktag
    wouldn't, but would allow e.g. "tagger <email>" (but not "tagger
    <email>"). Now we allow all of these.

 C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
    allows it.

We didn't only lose obscure validation logic, we also gained some:

 D. fsck disallows zero-padded dates, but mktag didn't care. So
    e.g. the timestamp "0000000000 +0000" produces an error now. A
    test in "t1006-cat-file.sh" relied on this, it's been changed to
    use "hash-object" (without fsck) instead.

1. ec4465adb38 (Add "tag" objects that can be used to sign other
   objects., 2005-04-25)

2. https://en.wikipedia.org/wiki/List_of_UTC_time_offsets

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c     | 45 +++++++++++++++++++++++++---
 t/t1006-cat-file.sh |  2 +-
 t/t3800-mktag.sh    | 72 +++++++++++++++++++++++++++------------------
 3 files changed, 86 insertions(+), 33 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index dc354828f7..a1ae80702d 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -2,6 +2,7 @@
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
+#include "fsck.h"
 
 /*
  * A signature file has a very simple fixed format: four lines
@@ -47,6 +48,9 @@ static int verify_tag(char *buffer, unsigned long size)
 	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
 	size_t len;
 
+	/* verify_tag() will be removed in the next commit */
+	return 0;
+
 	if (size < 84)
 		return error("wanna fool me ? you obviously got the size wrong !");
 
@@ -153,10 +157,34 @@ static int verify_tag(char *buffer, unsigned long size)
 	return 0;
 }
 
+static int mktag_fsck_error_func(struct fsck_options *o,
+				 const struct object_id *oid,
+				 enum object_type object_type,
+				 int msg_type, const char *message)
+{
+	switch (msg_type) {
+	case FSCK_WARN:
+	case FSCK_ERROR:
+	case FSCK_EXTRA:
+		/*
+		 * We treat both warnings and errors as errors, things
+		 * like missing "tagger" lines are "only" warnings
+		 * under fsck, we've always considered them an error.
+		 */
+		fprintf_ln(stderr, "error: %s", message);
+		return 1;
+	default:
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		    msg_type);
+	}
+}
+
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
+	struct object obj;
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id result;
+	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
 
 	if (argc != 1)
 		usage("git mktag");
@@ -164,10 +192,19 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
+	/* verify_tag() will be removed in the next commit */
+	verify_tag("", 0);
+
+	/*
+	 * Fake up an object for fsck_object()
+	 */
+	obj.parsed = 1;
+	obj.type = OBJ_TAG;
+
+	fsck_options.extra = 1;
+	fsck_options.error_func = mktag_fsck_error_func;
+	if (fsck_object(&obj, buf.buf, buf.len, &fsck_options))
+		die("tag on stdin did not pass our strict fsck check");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write annotated tag object");
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2f501d2dc9..5d2dc99b74 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
 
 $tag_description"
 
-tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
 tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 3801d3a285..bc57ee85c9 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -37,7 +37,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+	'^error: missingObject:'
 
 ############################################################
 #  2. object line label check
@@ -50,7 +50,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
+check_verify_failure '"object" line label check' '^error: missingObject:'
 
 ############################################################
 #  3. object line SHA check
@@ -64,7 +64,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line check' '^error: badObjectSha1:'
 
 ############################################################
 #  4. type line label check
@@ -77,7 +77,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error: missingTypeEntry:'
 
 ############################################################
 #  5. type line eol check
@@ -85,7 +85,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error: unterminatedHeader:'
 
 ############################################################
 #  6. tag line label check #1
@@ -99,7 +99,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char.*: no "tag " found$'
+	'^error: missingTagEntry:'
 
 ############################################################
 #  7. tag line label check #2
@@ -111,7 +111,7 @@ tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char.*: no "tag " found$'
+	'^error: badType:'
 
 ############################################################
 #  8. type line type-name length check
@@ -123,7 +123,7 @@ tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char.*: type too long$'
+	'^error: badType:'
 
 ############################################################
 #  9. verify object (SHA1/type) check
@@ -159,7 +159,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA1/type) check' \
-	'^error: char7: could not verify object.*$'
+	'^error: badType:'
 
 ############################################################
 # 10. verify tag-name check
@@ -173,7 +173,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char.*: could not verify tag name$'
+	'^error: badTagName:'
 
 ############################################################
 # 11. tagger line label check #1
@@ -187,7 +187,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char.*: could not find "tagger "$'
+	'^error: missingTaggerEntry:'
 
 ############################################################
 # 12. tagger line label check #2
@@ -202,10 +202,10 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char.*: could not find "tagger "$'
+	'^error: missingTaggerEntry:'
 
 ############################################################
-# 13. disallow missing tag author name
+# 13. allow missing tag author name like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -216,8 +216,9 @@ tagger  <> 0 +0000
 This is filler
 EOF
 
-check_verify_failure 'disallow missing tag author name' \
-	'^error: char.*: missing tagger name$'
+test_expect_success 'allow missing tag author name' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -232,7 +233,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char.*: malformed tagger field$'
+	'^error: badEmail:'
 
 ############################################################
 # 15. allow empty tag email
@@ -250,7 +251,7 @@ test_expect_success \
     'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
-# 16. disallow spaces in tag email
+# 16. allow spaces in tag email like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -260,8 +261,9 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 
 EOF
 
-check_verify_failure 'disallow spaces in tag email' \
-	'^error: char.*: malformed tagger field$'
+test_expect_success 'allow spaces in tag email like fsck' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -275,7 +277,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char.*: missing tag timestamp$'
+	'^error: badDate:'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -289,7 +291,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char.*: missing tag timestamp$'
+	'^error: badDate:'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -303,7 +305,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char.*: malformed tag timestamp$'
+	'^error: badDate:'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -317,7 +319,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char.*: malformed tag timezone$'
+	'^error: badTimezone:'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -331,10 +333,10 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char.*: malformed tag timezone$'
+	'^error: badTimezone:'
 
 ############################################################
-# 22. detect invalid tag timezone3
+# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
 
 cat >tag.sig <<EOF
 object $head
@@ -344,8 +346,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 
 EOF
 
-check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char.*: malformed tag timezone$'
+test_expect_success 'allow invalid tag timezone' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 23. detect invalid header entry
@@ -360,7 +363,20 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char.*: trailing garbage in tag header$'
+	'^error: extraHeaderEntry:'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+
+this line should be one line up
+EOF
+
+check_verify_failure 'detect invalid header entry' \
+	'^error: extraHeaderBodyNewline:'
 
 ############################################################
 # 24. create valid tag
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 09/12] mktag: remove now-unused verify_tag() code
  2020-11-23 21:34       ` Jeff King
                           ` (9 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 08/12] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  8:20           ` Jeff King
  2020-11-26  1:28         ` [RFC/PATCH 10/12] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
                           ` (2 subsequent siblings)
  13 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The preceding commit removed the use of the verify_tag() function, but
didn't remove this code to keep the diff smaller. Let's remove this
unused code now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 157 ------------------------------------------------
 1 file changed, 157 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index a1ae80702d..e9a0954dcb 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -1,162 +1,8 @@
 #include "builtin.h"
 #include "tag.h"
-#include "replace-object.h"
 #include "object-store.h"
 #include "fsck.h"
 
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
-{
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
-
-	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
-		free(buffer);
-	}
-	return ret;
-}
-
-static int verify_tag(char *buffer, unsigned long size)
-{
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	/* verify_tag() will be removed in the next commit */
-	return 0;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
-}
-
 static int mktag_fsck_error_func(struct fsck_options *o,
 				 const struct object_id *oid,
 				 enum object_type object_type,
@@ -192,9 +38,6 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* verify_tag() will be removed in the next commit */
-	verify_tag("", 0);
-
 	/*
 	 * Fake up an object for fsck_object()
 	 */
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 10/12] mktag doc: update to explain why to use this
  2020-11-23 21:34       ` Jeff King
                           ` (10 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 09/12] mktag: remove now-unused verify_tag() code Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 11/12] mktag docs: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 12/12] mktag: bring back some of the verify_object() logic Ævar Arnfjörð Bjarmason
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the mktag documentation to compare itself to the similar
"hash-object -t tag" command. Before this someone reading the
documentation wouldn't have much of an idea what the difference
was.

Let's make it clear that it's to do with slightly different fsck
validation logic, and cross-link the "mktag" and "hash-object"
documentation to aid discover-ability.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-hash-object.txt |  4 ++++
 Documentation/git-mktag.txt       | 29 +++++++++++++++++++++++++----
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index df9e2c58bd..c535661ced 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -58,6 +58,10 @@ OPTIONS
 	stress-testing Git itself or reproducing characteristics of corrupt or
 	bogus objects encountered in the wild.
 
+SEE ALSO
+--------
+linkgit:git-mktag[1]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index fa6a756123..11ce8e4bb4 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -3,7 +3,7 @@ git-mktag(1)
 
 NAME
 ----
-git-mktag - Creates a tag object
+git-mktag - Creates a tag object with extra validation
 
 
 SYNOPSIS
@@ -13,10 +13,20 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Reads a tag contents on standard input and creates a tag object
-that can also be used to sign other objects.
 
-The output is the new tag's <object> identifier.
+Reads a tag contents on standard input and creates a tag object. The
+output is the new tag's <object> identifier.
+
+This command accepts a subset of what linkgit:git-hash-object[1] would
+accept with `-t tag --stdin`. I.e. both of these work:
+
+    git mktag <my-tag
+    git hash-object -t tag --stdin <my-tag
+
+The difference between the two is that mktag does the equivalent of a
+linkgit:git-fsck(1) check on its input, and furthermore disallows some
+thing linkgit:git-hash-object[1] would pass, e.g. extra headers in the
+object before the message.
 
 Tag Format
 ----------
@@ -34,6 +44,17 @@ exists, is separated by a blank line from the header.  The
 message part may contain a signature that Git itself doesn't
 care about, but that can be verified with gpg.
 
+HISTORY
+-------
+
+In versions of Git before v2.30.0 the "mktag" command's validation
+logic was subtly different than that of linkgit:git-fsck[1]. It is now
+a strict superset of linkgit:git-fsck[1]'s validation logic.
+
+SEE ALSO
+--------
+linkgit:git-hash-object[1],
+
 GIT
 ---
 Part of the linkgit:git[1] suite
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 11/12] mktag docs: say <hash> not <sha1>
  2020-11-23 21:34       ` Jeff King
                           ` (11 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 10/12] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  1:28         ` [RFC/PATCH 12/12] mktag: bring back some of the verify_object() logic Ævar Arnfjörð Bjarmason
  13 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the "mktag" documentation to refer to the input hash as just
"hash", not "sha1". This command has supported SHA-256 for a while
now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 11ce8e4bb4..3ba15072df 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -33,7 +33,7 @@ Tag Format
 A tag signature file, to be fed to this command's standard input,
 has a very simple fixed format: four lines of
 
-  object <sha1>
+  object <hash>
   type <typename>
   tag <tagname>
   tagger <tagger>
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [RFC/PATCH 12/12] mktag: bring back some of the verify_object() logic
  2020-11-23 21:34       ` Jeff King
                           ` (12 preceding siblings ...)
  2020-11-26  1:28         ` [RFC/PATCH 11/12] mktag docs: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
@ 2020-11-26  1:28         ` Ævar Arnfjörð Bjarmason
  2020-11-26  8:32           ` Jeff King
  13 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26  1:28 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

When working on this series I saw too late that I'd removed the mktag
check for validating the object the tag points to. The fsck_tag() code
doesn't do this because it's meant for the context of fsck, where
we're validating reachability anyway.

We'd need to either refactor fsck_tag() so that it can pass us back
its "tagged_oid" and the "type_from_string_gently()" value it throws
away to get rid of the re-parsing of stdin here, or just duplicate the
logic as I'm doing here.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c  | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 t/t3800-mktag.sh |  4 ++--
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index e9a0954dcb..f1f1cf04ff 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "tag.h"
+#include "replace-object.h"
 #include "object-store.h"
 #include "fsck.h"
 
@@ -25,6 +26,50 @@ static int mktag_fsck_error_func(struct fsck_options *o,
 	}
 }
 
+static int verify_object_in_tag(const char *stdin)
+{
+	struct object_id oid;
+	char *eol;
+	const char *p;
+	int expected_type_id;
+	const char *expected_type;
+	int ret = -1;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+	const struct object_id *repl;
+
+	if (!skip_prefix(stdin, "object ", &stdin))
+		goto bug;
+	if (parse_oid_hex(stdin, &oid, &p) || *p != '\n')
+		goto bug;
+	stdin = p + 1;
+	if (!skip_prefix(stdin, "type ", &stdin))
+		goto bug;
+	eol = strchr(stdin, '\n');
+	expected_type_id = type_from_string_gently(stdin, eol - stdin, 1);
+	if (expected_type_id < 0)
+		goto bug;
+	expected_type = type_name(expected_type_id);
+
+	buffer = read_object_file(&oid, &type, &size);
+	repl = lookup_replace_object(the_repository, &oid);
+
+	if (buffer) {
+		if (type == type_from_string(expected_type)) {
+			ret = check_object_signature(the_repository, repl,
+						     buffer, size,
+						     expected_type);
+		}
+		free(buffer);
+	}
+	goto ok;
+bug:
+	BUG("fsck_object() should have ensured a sane tag format already!");
+ok:
+	return ret;
+}
+
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct object obj;
@@ -49,6 +94,9 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (fsck_object(&obj, buf.buf, buf.len, &fsck_options))
 		die("tag on stdin did not pass our strict fsck check");
 
+	if (verify_object_in_tag(buf.buf))
+		die("tag on stdin did not refer to a valid object");
+
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write annotated tag object");
 
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index bc57ee85c9..74cd2eb141 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -137,7 +137,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA1/type) check' \
-	'^error: char7: could not verify object.*$'
+	'^fatal: tag on stdin did not refer to a valid object'
 
 cat >tag.sig <<EOF
 object $head
@@ -148,7 +148,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA1/type) check' \
-	'^fatal: invalid object type'
+	'^error: badType:'
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 05/12] mktag tests: remove needless SHA-1 hardcoding
  2020-11-26  1:28         ` [RFC/PATCH 05/12] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2020-11-26  7:49           ` Jeff King
  0 siblings, 0 replies; 185+ messages in thread
From: Jeff King @ 2020-11-26  7:49 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Thu, Nov 26, 2020 at 02:28:47AM +0100, Ævar Arnfjörð Bjarmason wrote:

> But here we're testing for a SHA-length string which contains
> characters outside of the /[0-9a-f]/i set. Let's just do that with a
> ROT13 invocation.
> 
> We could get really unlucky and switch to a future hash function that
> just happens to produce all [0-9] output for this particular input,
> but that's very unlikely.

Maybe s/[0-9a-f]/z/ would be both simpler and more robust?

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 07/12] fsck: add new "extra" checks for "mktag"
  2020-11-26  1:28         ` [RFC/PATCH 07/12] fsck: add new "extra" checks for "mktag" Ævar Arnfjörð Bjarmason
@ 2020-11-26  8:02           ` Jeff King
  2020-11-26 12:43             ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 185+ messages in thread
From: Jeff King @ 2020-11-26  8:02 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Thu, Nov 26, 2020 at 02:28:49AM +0100, Ævar Arnfjörð Bjarmason wrote:

> Add optional "extra" checks to fsck, these are needed to eventually
> replace the custom not-quite-fsck code in mktag.c.
> 
> The mktag checks differ from fsck_tag() in several ways, one of those
> is that fsck doesn't know how to refuse an object with custom headers,
> and isn't strict about header and body newline separation.
> 
> Teach it how to optionally report these. I thought the best way to do
> that given the current structure of the code was to add a new "extra"
> category in addition to error/warn/info.

Hmm, this new severity (and the extra options bit) feels a bit
backwards. We are already passing the information on what we find to the
report() callback. It seems like that is the place that should be
deciding what is important and what is not.

Unfortunately the defaults are somewhat backwards here. We'd have to
teach the fsck callbacks to ignore these harmless entries, rather than
teaching the mktag caller that they need to be respected.

So probably the extra bit in options to say "do these extra tag checks"
is the least-bad thing. But then why do we need to put them in their own
EXTRA section? The only caller that wants them would treat them as
errors.

I'm slightly on the fence on whether mktag really needs to enforce the
"unknown header" thing at all. Sure, we don't encourage them, but it's a
plumbing tool one could use to experiment with new headers. I guess the
downside is that a typo'd header would not be caught.

> Under --strict the "info"
> becomes a "warn" and "warn" becomes "error". Existing users of
> fsck's (and others, e.g. index-pack) --strict option rely on this.

Yeah, this is a weirdness I think we should eventually fix (along with
re-prioritizing some of the existing checks). I'm wary of doing anything
that further cements that somewhat broken world-view (keep in mind that
"index-pack --strict" is not "do fsck more strictly" but "do fsck at
all").

> I'm not changing fsck_commit() to validate commit objects like this
> either, we could do that, but unlike in the tag case that code
> wouldn't be used anywhere. If someone wants to write a "mkcommit" they
> which behaves like "mktag" they can borrow or refactor this logic for
> use in fsck_commit().

Seems reasonable.

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 08/12] mktag: use fsck instead of custom verify_tag()
  2020-11-26  1:28         ` [RFC/PATCH 08/12] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-11-26  8:17           ` Jeff King
  2020-11-26 12:46             ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 185+ messages in thread
From: Jeff King @ 2020-11-26  8:17 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Thu, Nov 26, 2020 at 02:28:50AM +0100, Ævar Arnfjörð Bjarmason wrote:

> There was other "mktag" validation logic that I think makes sense to
> just remove. Namely:
> 
>  A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
>     code disallowed values larger than 1400.
> 
>     Yes there's currently no timezone with a greater offset[2], but
>     since we allow any number of non-offical timezones (e.g. +1234)
>     passing this through seems fine. Git also won't break in the
>     future if e.g. French Polynesia decides it needs to outdo the Line
>     Islands when it comes to timezone extravagance.

Yeah, I think this is a good choice to loosen.

>  B. fsck allows missing author names such as "tagger <email>", mktag
>     wouldn't, but would allow e.g. "tagger <email>" (but not "tagger
>     <email>"). Now we allow all of these.

Likewise, though I am confused. Should the second "tagger <email>" in
that paragraph have something else in it?

>  C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
>     allows it.

Possibly something we'd want to tighten in fsck, but I think keeping
them in alignment is a good idea for now.

> We didn't only lose obscure validation logic, we also gained some:
> 
>  D. fsck disallows zero-padded dates, but mktag didn't care. So
>     e.g. the timestamp "0000000000 +0000" produces an error now. A
>     test in "t1006-cat-file.sh" relied on this, it's been changed to
>     use "hash-object" (without fsck) instead.

Seems reasonable.

> +	/* verify_tag() will be removed in the next commit */
> +	verify_tag("", 0);
> +
> +	/*
> +	 * Fake up an object for fsck_object()
> +	 */
> +	obj.parsed = 1;
> +	obj.type = OBJ_TAG;

I don't love this "fake object struct on the stack" thing. I can't think
of anything that would break outright, but it may be the only place
where that struct isn't coming from the usual pool, and representing the
common part of a larger object. Two definite gotchas, though:

  - if the type is OBJ_TAG, then it may get cast to a "struct tag" by
    other code, which could look past the end of the struct. I think
    that fsck_object() doesn't do this, but it could (and it definitely
    used to)

  - you don't initialize the other fields. We'll definitely pass
    &obj->oid in the fsck code, and even back to our report() callback,
    even though it's full of garbage. In practice this is OK because our
    custom report() won't look at them, but it seems awfully fragile.

I recently genericized the type-specific fsck_* functions so that they
just need an oid, and not an object struct. I think I didn't do
fsck_object() just because it didn't have any callers where it mattered.
So I think it would make sense here to either:

  - make fsck_tag() specifically available outside of fsck.c, so could
    call it directly

  - convert fsck_object() to take an oid rather than an object struct.
    It only uses the object itself to check for NULL-ness. Looking at
    the callers, they all have non-NULL objects already. So I think that
    check can't be triggered.

>  check_verify_failure 'Tag object length check' \
> -	'^error: .*size wrong.*$'
> +	'^error: missingObject:'

We may want to enhance the "error:" here to make it clear we're talking
about a format error in the tag input. Maybe:

  error: tag input does not pass fsck: missingObject: ...

or something.

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 09/12] mktag: remove now-unused verify_tag() code
  2020-11-26  1:28         ` [RFC/PATCH 09/12] mktag: remove now-unused verify_tag() code Ævar Arnfjörð Bjarmason
@ 2020-11-26  8:20           ` Jeff King
  0 siblings, 0 replies; 185+ messages in thread
From: Jeff King @ 2020-11-26  8:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Thu, Nov 26, 2020 at 02:28:51AM +0100, Ævar Arnfjörð Bjarmason wrote:

> The preceding commit removed the use of the verify_tag() function, but
> didn't remove this code to keep the diff smaller. Let's remove this
> unused code now.

I do appreciate keeping diffs readable, but IMHO this is making things
more confusing, because you had to add a new dummy call to verify_tag()
in the previous commit in order to keep the compiler from complaining
about the unused static function (I'm actually surprised that it doesn't
complain about the immediate "return 0" in that function, which makes
the rest of the function unambiguously unreachable).

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 12/12] mktag: bring back some of the verify_object() logic
  2020-11-26  1:28         ` [RFC/PATCH 12/12] mktag: bring back some of the verify_object() logic Ævar Arnfjörð Bjarmason
@ 2020-11-26  8:32           ` Jeff King
  0 siblings, 0 replies; 185+ messages in thread
From: Jeff King @ 2020-11-26  8:32 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Thu, Nov 26, 2020 at 02:28:54AM +0100, Ævar Arnfjörð Bjarmason wrote:

> When working on this series I saw too late that I'd removed the mktag
> check for validating the object the tag points to. The fsck_tag() code
> doesn't do this because it's meant for the context of fsck, where
> we're validating reachability anyway.
> 
> We'd need to either refactor fsck_tag() so that it can pass us back
> its "tagged_oid" and the "type_from_string_gently()" value it throws
> away to get rid of the re-parsing of stdin here, or just duplicate the
> logic as I'm doing here.

We have yet another tag parser (because of course there's more): the one
in parse_tag_buffer() that we use for reading tags. I think your new
function here could just be:

  enum object_type real_type;
  struct tag t; /* yuck! another fake object */

  memset(&t, 0, sizeof(t));
  if (parse_tag_buffer(r, &t, buf, len) < 0)
	die("unable to parse");

  real_type = oid_object_info(r, &t->tagged->oid, NULL);
  if (real_type < 0)
	die("tagged object does not exist");
  if (real_type != t->tagged->type)
	die("tagged object's type does not match tag type field");

I almost wonder if we could simply rely on parse_tag_buffer() instead of
fsck_tag(), but it is not nearly as picky about finding potential
problems (its goal is the opposite: to return something usable if it's
at all possible to do so).

The "yuck" above isn't great. We could use pretend_object_file() for
that, though it's a bit heavy-weight (it computes the actual oid!). And
also it's a weird one-off that we've talked about getting rid of.

-Peff

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 07/12] fsck: add new "extra" checks for "mktag"
  2020-11-26  8:02           ` Jeff King
@ 2020-11-26 12:43             ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 12:43 UTC (permalink / raw)
  To: Jeff King
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin


On Thu, Nov 26 2020, Jeff King wrote:

> On Thu, Nov 26, 2020 at 02:28:49AM +0100, Ævar Arnfjörð Bjarmason wrote:
>
>> Add optional "extra" checks to fsck, these are needed to eventually
>> replace the custom not-quite-fsck code in mktag.c.
>> 
>> The mktag checks differ from fsck_tag() in several ways, one of those
>> is that fsck doesn't know how to refuse an object with custom headers,
>> and isn't strict about header and body newline separation.
>> 
>> Teach it how to optionally report these. I thought the best way to do
>> that given the current structure of the code was to add a new "extra"
>> category in addition to error/warn/info.
>
> Hmm, this new severity (and the extra options bit) feels a bit
> backwards. We are already passing the information on what we find to the
> report() callback. It seems like that is the place that should be
> deciding what is important and what is not.
>
> Unfortunately the defaults are somewhat backwards here. We'd have to
> teach the fsck callbacks to ignore these harmless entries, rather than
> teaching the mktag caller that they need to be respected.
>
> So probably the extra bit in options to say "do these extra tag checks"
> is the least-bad thing. But then why do we need to put them in their own
> EXTRA section? The only caller that wants them would treat them as
> errors.

Right, it'll be hidden behind options->extra, so I could just make them
ERROR. I guess I was thinking it would be confusing to stick stuff in
the middle of ERROR that wasn't on by default, e.g. I've sometimes
skimmed that macro definition and saw "ah, bad parent sha1 is an error",
as in transfer.fsckObjects would reject it.

So I'm slightly on the fence about keeping it as it is, what do you
think?

> I'm slightly on the fence on whether mktag really needs to enforce the
> "unknown header" thing at all. Sure, we don't encourage them, but it's a
> plumbing tool one could use to experiment with new headers. I guess the
> downside is that a typo'd header would not be caught.

The problem is that since verify_headers() in fsck.c wants to allow it,
there's no way for it to distinguish a fat-fingerd "didn't separate the
body from the headers" v.s. actually wanting a custom header in some
cases.

>> Under --strict the "info"
>> becomes a "warn" and "warn" becomes "error". Existing users of
>> fsck's (and others, e.g. index-pack) --strict option rely on this.
>
> Yeah, this is a weirdness I think we should eventually fix (along with
> re-prioritizing some of the existing checks). I'm wary of doing anything
> that further cements that somewhat broken world-view (keep in mind that
> "index-pack --strict" is not "do fsck more strictly" but "do fsck at
> all").

*nod*, will note that.

>> I'm not changing fsck_commit() to validate commit objects like this
>> either, we could do that, but unlike in the tag case that code
>> wouldn't be used anywhere. If someone wants to write a "mkcommit" they
>> which behaves like "mktag" they can borrow or refactor this logic for
>> use in fsck_commit().
>
> Seems reasonable.
>
> -Peff


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [RFC/PATCH 08/12] mktag: use fsck instead of custom verify_tag()
  2020-11-26  8:17           ` Jeff King
@ 2020-11-26 12:46             ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 12:46 UTC (permalink / raw)
  To: Jeff King
  Cc: git, Junio C Hamano, brian m . carlson, Eric Sunshine,
	Johannes Schindelin


On Thu, Nov 26 2020, Jeff King wrote:

> On Thu, Nov 26, 2020 at 02:28:50AM +0100, Ævar Arnfjörð Bjarmason wrote:
>
>> There was other "mktag" validation logic that I think makes sense to
>> just remove. Namely:
>> 
>>  A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
>>     code disallowed values larger than 1400.
>> 
>>     Yes there's currently no timezone with a greater offset[2], but
>>     since we allow any number of non-offical timezones (e.g. +1234)
>>     passing this through seems fine. Git also won't break in the
>>     future if e.g. French Polynesia decides it needs to outdo the Line
>>     Islands when it comes to timezone extravagance.
>
> Yeah, I think this is a good choice to loosen.
>
>>  B. fsck allows missing author names such as "tagger <email>", mktag
>>     wouldn't, but would allow e.g. "tagger <email>" (but not "tagger
>>     <email>"). Now we allow all of these.
>
> Likewise, though I am confused. Should the second "tagger <email>" in
> that paragraph have something else in it?

There should be 1-2 and 3 spaces there, don't know why that didn't make
it. Will fix.

>>  C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
>>     allows it.
>
> Possibly something we'd want to tighten in fsck, but I think keeping
> them in alignment is a good idea for now.
>
>> We didn't only lose obscure validation logic, we also gained some:
>> 
>>  D. fsck disallows zero-padded dates, but mktag didn't care. So
>>     e.g. the timestamp "0000000000 +0000" produces an error now. A
>>     test in "t1006-cat-file.sh" relied on this, it's been changed to
>>     use "hash-object" (without fsck) instead.
>
> Seems reasonable.
>
>> +	/* verify_tag() will be removed in the next commit */
>> +	verify_tag("", 0);
>> +
>> +	/*
>> +	 * Fake up an object for fsck_object()
>> +	 */
>> +	obj.parsed = 1;
>> +	obj.type = OBJ_TAG;
>
> I don't love this "fake object struct on the stack" thing. I can't think
> of anything that would break outright, but it may be the only place
> where that struct isn't coming from the usual pool, and representing the
> common part of a larger object. Two definite gotchas, though:
>
>   - if the type is OBJ_TAG, then it may get cast to a "struct tag" by
>     other code, which could look past the end of the struct. I think
>     that fsck_object() doesn't do this, but it could (and it definitely
>     used to)
>
>   - you don't initialize the other fields. We'll definitely pass
>     &obj->oid in the fsck code, and even back to our report() callback,
>     even though it's full of garbage. In practice this is OK because our
>     custom report() won't look at them, but it seems awfully fragile.
>
> I recently genericized the type-specific fsck_* functions so that they
> just need an oid, and not an object struct. I think I didn't do
> fsck_object() just because it didn't have any callers where it mattered.
> So I think it would make sense here to either:
>
>   - make fsck_tag() specifically available outside of fsck.c, so could
>     call it directly
>
>   - convert fsck_object() to take an oid rather than an object struct.
>     It only uses the object itself to check for NULL-ness. Looking at
>     the callers, they all have non-NULL objects already. So I think that
>     check can't be triggered.
>
>>  check_verify_failure 'Tag object length check' \
>> -	'^error: .*size wrong.*$'
>> +	'^error: missingObject:'

When I started out hacking on this I just made fsck_tag() a non-static
function. The faking up obj only got added because I needed to call
fsck_object().

Between this and your comment to 12/12 I wonder if the least bad thing
isn't just to split up fsck_tag() into fsck_tag() and
fsck_tag_standalone(), so I can call the latter with a "populate the
object and type" argument, and fsck.c will just NULL those two
parameters since it doesn't care.

Gets rid of the obj faking, and gets rid of the custom parser in
mktag.c. It'll only need to do the object lookup at that point, and even
then since I've added everything else to fsck.c I might as well make
that another custom ERROR/EXTRA, i.e. have it learn to do the lookup
itself.

> We may want to enhance the "error:" here to make it clear we're talking
> about a format error in the tag input. Maybe:
>
>   error: tag input does not pass fsck: missingObject: ...
>
> or something.

*nod*

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 00/10] make "mktag" use fsck_tag()
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 10:08             ` Ævar Arnfjörð Bjarmason
                               ` (11 more replies)
  2020-11-26 22:22           ` [PATCH v2 01/10] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
                             ` (9 subsequent siblings)
  10 siblings, 12 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Now a non-RFC. I went for the approach I suggested in
<87r1ognv4b.fsf@evledraar.gmail.com> of just having fsck_tag() able to
optionally tell us about its parsed tag/type, thus avoiding any need
for a custom parser in mktag.c. Hopefully I've addressed the rest of
the feedback, range-diff below.

Ævar Arnfjörð Bjarmason (10):
  mktag doc: say <hash> not <sha1>
  mktag: use default strbuf_read() hint
  mktag: reword write_object_file() error
  mktag: remove redundant braces in one-line body "if"
  mktag tests: don't needlessly use a subshell
  mktag tests: remove needless SHA-1 hardcoding
  mktag tests: improve verify_object() test coverage
  fsck: add new "extra" checks for "mktag"
  mktag: use fsck instead of custom verify_tag()
  mktag doc: update to explain why to use this

 Documentation/git-hash-object.txt |   4 +
 Documentation/git-mktag.txt       |  31 ++++-
 builtin/mktag.c                   | 202 ++++++++----------------------
 fsck.c                            |  47 ++++++-
 fsck.h                            |  11 ++
 t/t1006-cat-file.sh               |   2 +-
 t/t3800-mktag.sh                  | 117 ++++++++++++-----
 7 files changed, 222 insertions(+), 192 deletions(-)

Range-diff:
11:  a7a6524b2a !  1:  f46abb37df mktag docs: say <hash> not <sha1>
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    mktag docs: say <hash> not <sha1>
    +    mktag doc: say <hash> not <sha1>
     
         Change the "mktag" documentation to refer to the input hash as just
         "hash", not "sha1". This command has supported SHA-256 for a while
 1:  f6d9482c5b =  2:  1b4d9a5330 mktag: use default strbuf_read() hint
 2:  49be8dbdd3 =  3:  83f4af6013 mktag: reword write_object_file() error
 3:  868d424e65 =  4:  bca1484ed9 mktag: remove redundant braces in one-line body "if"
 4:  e57969ce5d =  5:  ac7c4097c9 mktag tests: don't needlessly use a subshell
 5:  8cf5d95b1e !  6:  5e076659e4 mktag tests: remove needless SHA-1 hardcoding
    @@ Commit message
     
         Some of these tests were failing for the wrong reasons. The first one
         being modified here would fail because the line starts with "xxxxxx"
    -    instead of "object", the rest of the line doesn't matter. Let's just
    -    put a valid hash on the rest of the line anyway to narrow the test
    -    down for just the s/object/xxxxxx/ case.
    +    instead of "object", the rest of the line doesn't matter.
    +
    +    Let's just put a valid hash on the rest of the line anyway to narrow
    +    the test down for just the s/object/xxxxxx/ case.
     
         The second one being modified here would fail under
         GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
    @@ Commit message
         garbage> when under SHA-256.
     
         This doesn't really matter since we should be able to trust other
    -    parts of the code to validate things in the 0-9a-f range, but let's do
    -    it for good measure.
    +    parts of the code to validate things in the 0-9a-f range, but let's
    +    keep it for good measure.
     
         There's a later test which tests an invalid SHA which looks like a
         valid one, to stress the "We refuse to tag something we can't
         verify[...]" logic in mktag.c.
     
         But here we're testing for a SHA-length string which contains
    -    characters outside of the /[0-9a-f]/i set. Let's just do that with a
    -    ROT13 invocation.
    -
    -    We could get really unlucky and switch to a future hash function that
    -    just happens to produce all [0-9] output for this particular input,
    -    but that's very unlikely.
    +    characters outside of the /[0-9a-f]/i set.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ t/t3800-mktag.sh: EOF
     -#  3. object line SHA1 check
     +#  3. object line SHA check
      
    -+invalid_sha=$(echo $head | tr A-Za-z N-ZA-Mn-za-m)
      cat >tag.sig <<EOF
     -object zz9e9b33986b1c2670fff52c5067603117b3e895
    -+object $invalid_sha
    ++object $(echo $head | tr 0-9a-f z)
      type tag
      tag mytag
      tagger . <> 0 +0000
 6:  2899f9cda5 <  -:  ---------- mktag tests: improve verify_object() test coverage
 -:  ---------- >  7:  a048c3e640 mktag tests: improve verify_object() test coverage
 7:  70d1d877aa =  8:  dab44d3235 fsck: add new "extra" checks for "mktag"
 8:  d37d684135 !  9:  8ff853caee mktag: use fsck instead of custom verify_tag()
    @@ Metadata
      ## Commit message ##
         mktag: use fsck instead of custom verify_tag()
     
    -    TODO: This subtly breaks one check, see the last patch in this series.
    -
         Change the validation logic in "mktag" to use fsck's fsck_tag()
         instead of its own custom parser. Curiously the logic for both dates
         back to the same commit[1]. Let's unify them so we're not maintaining
    @@ Commit message
             Islands when it comes to timezone extravagance.
     
          B. fsck allows missing author names such as "tagger <email>", mktag
    -        wouldn't, but would allow e.g. "tagger <email>" (but not "tagger
    -        <email>"). Now we allow all of these.
    +        wouldn't, but would allow e.g. "tagger [2 spaces] <email>" (but
    +        not "tagger [1 space] <email>"). Now we allow all of these.
     
          C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
             allows it.
    @@ builtin/mktag.c
      #include "object-store.h"
     +#include "fsck.h"
      
    - /*
    -  * A signature file has a very simple fixed format: four lines
    -@@ builtin/mktag.c: static int verify_tag(char *buffer, unsigned long size)
    - 	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
    - 	size_t len;
    - 
    -+	/* verify_tag() will be removed in the next commit */
    -+	return 0;
    -+
    - 	if (size < 84)
    - 		return error("wanna fool me ? you obviously got the size wrong !");
    - 
    -@@ builtin/mktag.c: static int verify_tag(char *buffer, unsigned long size)
    - 	return 0;
    - }
    - 
    +-/*
    +- * A signature file has a very simple fixed format: four lines
    +- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
    +- * "tagger <committer>", followed by a blank line, a free-form tag
    +- * message and a signature block that git itself doesn't care about,
    +- * but that can be verified with gpg or similar.
    +- *
    +- * The first four lines are guaranteed to be at least 83 bytes:
    +- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
    +- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
    +- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
    +- * the shortest possible tagger-line.
    +- */
    +-
    +-/*
    +- * We refuse to tag something we can't verify. Just because.
    +- */
    +-static int verify_object(const struct object_id *oid, const char *expected_type)
     +static int mktag_fsck_error_func(struct fsck_options *o,
     +				 const struct object_id *oid,
     +				 enum object_type object_type,
     +				 int msg_type, const char *message)
    -+{
    + {
    +-	int ret = -1;
    +-	enum object_type type;
    +-	unsigned long size;
    +-	void *buffer = read_object_file(oid, &type, &size);
    +-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
    +-
    +-	if (buffer) {
    +-		if (type == type_from_string(expected_type)) {
    +-			ret = check_object_signature(the_repository, repl,
    +-						     buffer, size,
    +-						     expected_type);
    +-		}
    +-		free(buffer);
     +	switch (msg_type) {
     +	case FSCK_WARN:
     +	case FSCK_ERROR:
    @@ builtin/mktag.c: static int verify_tag(char *buffer, unsigned long size)
     +		 * like missing "tagger" lines are "only" warnings
     +		 * under fsck, we've always considered them an error.
     +		 */
    -+		fprintf_ln(stderr, "error: %s", message);
    ++		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
     +		return 1;
     +	default:
     +		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
     +		    msg_type);
    -+	}
    -+}
    + 	}
    +-	return ret;
    + }
    + 
    +-static int verify_tag(char *buffer, unsigned long size)
    ++static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
    + {
    +-	int typelen;
    +-	char type[20];
    +-	struct object_id oid;
    +-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
    +-	size_t len;
    +-
    +-	if (size < 84)
    +-		return error("wanna fool me ? you obviously got the size wrong !");
    +-
    +-	buffer[size] = 0;
    +-
    +-	/* Verify object line */
    +-	object = buffer;
    +-	if (memcmp(object, "object ", 7))
    +-		return error("char%d: does not start with \"object \"", 0);
    +-
    +-	if (parse_oid_hex(object + 7, &oid, &p))
    +-		return error("char%d: could not get SHA1 hash", 7);
    +-
    +-	/* Verify type line */
    +-	type_line = p + 1;
    +-	if (memcmp(type_line - 1, "\ntype ", 6))
    +-		return error("char%d: could not find \"\\ntype \"", 47);
    +-
    +-	/* Verify tag-line */
    +-	tag_line = strchr(type_line, '\n');
    +-	if (!tag_line)
    +-		return error("char%"PRIuMAX": could not find next \"\\n\"",
    +-				(uintmax_t) (type_line - buffer));
    +-	tag_line++;
    +-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
    +-		return error("char%"PRIuMAX": no \"tag \" found",
    +-				(uintmax_t) (tag_line - buffer));
    +-
    +-	/* Get the actual type */
    +-	typelen = tag_line - type_line - strlen("type \n");
    +-	if (typelen >= sizeof(type))
    +-		return error("char%"PRIuMAX": type too long",
    +-				(uintmax_t) (type_line+5 - buffer));
    +-
    +-	memcpy(type, type_line+5, typelen);
    +-	type[typelen] = 0;
    +-
    +-	/* Verify that the object matches */
    +-	if (verify_object(&oid, type))
    +-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
    +-
    +-	/* Verify the tag-name: we don't allow control characters or spaces in it */
    +-	tag_line += 4;
    +-	for (;;) {
    +-		unsigned char c = *tag_line++;
    +-		if (c == '\n')
    +-			break;
    +-		if (c > ' ')
    +-			continue;
    +-		return error("char%"PRIuMAX": could not verify tag name",
    +-				(uintmax_t) (tag_line - buffer));
    +-	}
    +-
    +-	/* Verify the tagger line */
    +-	tagger_line = tag_line;
    +-
    +-	if (memcmp(tagger_line, "tagger ", 7))
    +-		return error("char%"PRIuMAX": could not find \"tagger \"",
    +-			(uintmax_t) (tagger_line - buffer));
    +-
    +-	/*
    +-	 * Check for correct form for name and email
    +-	 * i.e. " <" followed by "> " on _this_ line
    +-	 * No angle brackets within the name or email address fields.
    +-	 * No spaces within the email address field.
    +-	 */
    +-	tagger_line += 7;
    +-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
    +-		strpbrk(tagger_line, "<>\n") != lb+1 ||
    +-		strpbrk(lb+2, "><\n ") != rb)
    +-		return error("char%"PRIuMAX": malformed tagger field",
    +-			(uintmax_t) (tagger_line - buffer));
    +-
    +-	/* Check for author name, at least one character, space is acceptable */
    +-	if (lb == tagger_line)
    +-		return error("char%"PRIuMAX": missing tagger name",
    +-			(uintmax_t) (tagger_line - buffer));
    +-
    +-	/* timestamp, 1 or more digits followed by space */
    +-	tagger_line = rb + 2;
    +-	if (!(len = strspn(tagger_line, "0123456789")))
    +-		return error("char%"PRIuMAX": missing tag timestamp",
    +-			(uintmax_t) (tagger_line - buffer));
    +-	tagger_line += len;
    +-	if (*tagger_line != ' ')
    +-		return error("char%"PRIuMAX": malformed tag timestamp",
    +-			(uintmax_t) (tagger_line - buffer));
    +-	tagger_line++;
    +-
    +-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
    +-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
    +-	      strspn(tagger_line+1, "0123456789") == 4 &&
    +-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
    +-		return error("char%"PRIuMAX": malformed tag timezone",
    +-			(uintmax_t) (tagger_line - buffer));
    +-	tagger_line += 6;
    +-
    +-	/* Verify the blank line separating the header from the body */
    +-	if (*tagger_line != '\n')
    +-		return error("char%"PRIuMAX": trailing garbage in tag header",
    +-			(uintmax_t) (tagger_line - buffer));
    ++	int ret;
    ++	enum object_type type;
    ++	unsigned long size;
    ++	void *buffer;
    ++	const struct object_id *repl;
    ++
    ++	buffer = read_object_file(tagged_oid, &type, &size);
    ++	if (!buffer)
    ++		die("could not read tagged object '%s'\n",
    ++		    oid_to_hex(tagged_oid));
    ++	if (type != *tagged_type)
    ++		die("object '%s' tagged as '%s', but is a '%s' type\n",
    ++		    oid_to_hex(tagged_oid),
    ++		    type_name(*tagged_type), type_name(type));
     +
    ++	repl = lookup_replace_object(the_repository, tagged_oid);
    ++	ret = check_object_signature(the_repository, repl,
    ++				     buffer, size, type_name(*tagged_type));
    ++	free(buffer);
    + 
    +-	/* The actual stuff afterwards we don't care about.. */
    +-	return 0;
    ++	return ret;
    + }
    + 
      int cmd_mktag(int argc, const char **argv, const char *prefix)
      {
    -+	struct object obj;
      	struct strbuf buf = STRBUF_INIT;
    - 	struct object_id result;
     +	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
    ++	struct object_id tagged_oid;
    ++	int tagged_type;
    + 	struct object_id result;
      
      	if (argc != 1)
    - 		usage("git mktag");
     @@ builtin/mktag.c: int cmd_mktag(int argc, const char **argv, const char *prefix)
      	if (strbuf_read(&buf, 0, 0) < 0)
      		die_errno("could not read from stdin");
    @@ builtin/mktag.c: int cmd_mktag(int argc, const char **argv, const char *prefix)
     -	   "object <sha1>\ntype\ntagger " */
     -	if (verify_tag(buf.buf, buf.len) < 0)
     -		die("invalid tag signature file");
    -+	/* verify_tag() will be removed in the next commit */
    -+	verify_tag("", 0);
    -+
    -+	/*
    -+	 * Fake up an object for fsck_object()
    -+	 */
    -+	obj.parsed = 1;
    -+	obj.type = OBJ_TAG;
    -+
     +	fsck_options.extra = 1;
     +	fsck_options.error_func = mktag_fsck_error_func;
    -+	if (fsck_object(&obj, buf.buf, buf.len, &fsck_options))
    ++	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
    ++				&tagged_oid, &tagged_type))
     +		die("tag on stdin did not pass our strict fsck check");
    ++
    ++	if (verify_object_in_tag(&tagged_oid, &tagged_type))
    ++		die("tag on stdin did not refer to a valid object");
      
      	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
      		die("unable to write annotated tag object");
     
    + ## fsck.c ##
    +@@ fsck.c: static int fsck_tag(const struct object_id *oid, const char *buffer,
    + 		    unsigned long size, struct fsck_options *options)
    + {
    + 	struct object_id tagged_oid;
    ++	int tagged_type;
    ++	return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
    ++				   &tagged_type);
    ++}
    ++
    ++int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
    ++			unsigned long size, struct fsck_options *options,
    ++			struct object_id *tagged_oid,
    ++			int *tagged_type)
    ++{
    + 	int ret = 0;
    + 	char *eol;
    + 	struct strbuf sb = STRBUF_INIT;
    +@@ fsck.c: static int fsck_tag(const struct object_id *oid, const char *buffer,
    + 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
    + 		goto done;
    + 	}
    +-	if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
    ++	if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
    + 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
    + 		if (ret)
    + 			goto done;
    +@@ fsck.c: static int fsck_tag(const struct object_id *oid, const char *buffer,
    + 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
    + 		goto done;
    + 	}
    +-	if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
    ++	*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
    ++	if (*tagged_type < 0)
    + 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
    + 	if (ret)
    + 		goto done;
    +
    + ## fsck.h ##
    +@@ fsck.h: int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
    + int fsck_object(struct object *obj, void *data, unsigned long size,
    + 	struct fsck_options *options);
    + 
    ++/*
    ++ * fsck a tag, and pass info about it back to the caller. This is
    ++ * exposed fsck_object() internals for git-mktag(1).
    ++ */
    ++int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
    ++			unsigned long size, struct fsck_options *options,
    ++			struct object_id *tagged_oid,
    ++			int *tag_type);
    ++
    + /*
    +  * Some fsck checks are context-dependent, and may end up queued; run this
    +  * after completing all fsck_object() calls in order to resolve any remaining
    +
      ## t/t1006-cat-file.sh ##
     @@ t/t1006-cat-file.sh: tag_content="$tag_header_without_timestamp 0000000000 +0000
      
    @@ t/t3800-mktag.sh: too short for a tag
      
      check_verify_failure 'Tag object length check' \
     -	'^error: .*size wrong.*$'
    -+	'^error: missingObject:'
    ++	'^error:.* missingObject:'
      
      ############################################################
      #  2. object line label check
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
     -check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
    -+check_verify_failure '"object" line label check' '^error: missingObject:'
    ++check_verify_failure '"object" line label check' '^error:.* missingObject:'
      
      ############################################################
      #  3. object line SHA check
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
     -check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
    -+check_verify_failure '"object" line check' '^error: badObjectSha1:'
    ++check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
      
      ############################################################
      #  4. type line label check
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
     -check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
    -+check_verify_failure '"type" line label check' '^error: missingTypeEntry:'
    ++check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
      
      ############################################################
      #  5. type line eol check
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line label check' '^error: char.*
      printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
      
     -check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
    -+check_verify_failure '"type" line eol check' '^error: unterminatedHeader:'
    ++check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
      
      ############################################################
      #  6. tag line label check #1
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      
      check_verify_failure '"tag" line label check #1' \
     -	'^error: char.*: no "tag " found$'
    -+	'^error: missingTagEntry:'
    ++	'^error:.* missingTagEntry:'
      
      ############################################################
      #  7. tag line label check #2
    @@ t/t3800-mktag.sh: tag
      
      check_verify_failure '"tag" line label check #2' \
     -	'^error: char.*: no "tag " found$'
    -+	'^error: badType:'
    ++	'^error:.* badType:'
      
      ############################################################
      #  8. type line type-name length check
    @@ t/t3800-mktag.sh: tag mytag
      
      check_verify_failure '"type" line type-name length check' \
     -	'^error: char.*: type too long$'
    -+	'^error: badType:'
    ++	'^error:.* badType:'
      
      ############################################################
    - #  9. verify object (SHA1/type) check
    + #  9. verify object (SHA/type) check
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (SHA1/type) check' \
    + check_verify_failure 'verify object (SHA/type) check -- correct type, nonexisting object' \
     -	'^error: char7: could not verify object.*$'
    -+	'^error: badType:'
    ++	'^fatal: could not read tagged object'
    + 
    + cat >tag.sig <<EOF
    + object $head
    +@@ t/t3800-mktag.sh: tagger . <> 0 +0000
    + EOF
    + 
    + check_verify_failure 'verify object (SHA/type) check -- made-up type, nonexisting object' \
    +-	'^fatal: invalid object type'
    ++	'^error:.* badType:'
    + 
    + cat >tag.sig <<EOF
    + object $(test_oid deadbeef)
    +@@ t/t3800-mktag.sh: tagger . <> 0 +0000
    + EOF
    + 
    + check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
    +-	'^error: char7: could not verify object.*$'
    ++	'^error:.* badType:'
    + 
    + cat >tag.sig <<EOF
    + object $head
    +@@ t/t3800-mktag.sh: tagger . <> 0 +0000
    + EOF
    + 
    + check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
    +-	'^error: char7: could not verify object'
    ++	'^fatal: object.*tagged as.*tree.*but is.*commit'
      
      ############################################################
      # 10. verify tag-name check
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      
      check_verify_failure 'verify tag-name check' \
     -	'^error: char.*: could not verify tag name$'
    -+	'^error: badTagName:'
    ++	'^error:.* badTagName:'
      
      ############################################################
      # 11. tagger line label check #1
    @@ t/t3800-mktag.sh: This is filler
      
      check_verify_failure '"tagger" line label check #1' \
     -	'^error: char.*: could not find "tagger "$'
    -+	'^error: missingTaggerEntry:'
    ++	'^error:.* missingTaggerEntry:'
      
      ############################################################
      # 12. tagger line label check #2
    @@ t/t3800-mktag.sh: This is filler
      
      check_verify_failure '"tagger" line label check #2' \
     -	'^error: char.*: could not find "tagger "$'
    -+	'^error: missingTaggerEntry:'
    ++	'^error:.* missingTaggerEntry:'
      
      ############################################################
     -# 13. disallow missing tag author name
    @@ t/t3800-mktag.sh: tagger T A Gger <
      
      check_verify_failure 'disallow malformed tagger' \
     -	'^error: char.*: malformed tagger field$'
    -+	'^error: badEmail:'
    ++	'^error:.* badEmail:'
      
      ############################################################
      # 15. allow empty tag email
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com>__
      
      check_verify_failure 'disallow missing tag timestamp' \
     -	'^error: char.*: missing tag timestamp$'
    -+	'^error: badDate:'
    ++	'^error:.* badDate:'
      
      ############################################################
      # 18. detect invalid tag timestamp1
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
      
      check_verify_failure 'detect invalid tag timestamp1' \
     -	'^error: char.*: missing tag timestamp$'
    -+	'^error: badDate:'
    ++	'^error:.* badDate:'
      
      ############################################################
      # 19. detect invalid tag timestamp2
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
      
      check_verify_failure 'detect invalid tag timestamp2' \
     -	'^error: char.*: malformed tag timestamp$'
    -+	'^error: badDate:'
    ++	'^error:.* badDate:'
      
      ############################################################
      # 20. detect invalid tag timezone1
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 GMT
      
      check_verify_failure 'detect invalid tag timezone1' \
     -	'^error: char.*: malformed tag timezone$'
    -+	'^error: badTimezone:'
    ++	'^error:.* badTimezone:'
      
      ############################################################
      # 21. detect invalid tag timezone2
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 +  30
      
      check_verify_failure 'detect invalid tag timezone2' \
     -	'^error: char.*: malformed tag timezone$'
    -+	'^error: badTimezone:'
    ++	'^error:.* badTimezone:'
      
      ############################################################
     -# 22. detect invalid tag timezone3
    @@ t/t3800-mktag.sh: this line should not be here
      
      check_verify_failure 'detect invalid header entry' \
     -	'^error: char.*: trailing garbage in tag header$'
    -+	'^error: extraHeaderEntry:'
    ++	'^error:.* extraHeaderEntry:'
     +
     +cat >tag.sig <<EOF
     +object $head
    @@ t/t3800-mktag.sh: this line should not be here
     +EOF
     +
     +check_verify_failure 'detect invalid header entry' \
    -+	'^error: extraHeaderBodyNewline:'
    ++	'^error:.* extraHeaderBodyNewline:'
      
      ############################################################
      # 24. create valid tag
 9:  403820698b <  -:  ---------- mktag: remove now-unused verify_tag() code
10:  78a4877450 = 10:  e38feefd3f mktag doc: update to explain why to use this
12:  0e840246a8 <  -:  ---------- mktag: bring back some of the verify_object() logic
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 01/10] mktag doc: say <hash> not <sha1>
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:17             ` Junio C Hamano
  2020-11-26 22:22           ` [PATCH v2 02/10] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
                             ` (8 subsequent siblings)
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the "mktag" documentation to refer to the input hash as just
"hash", not "sha1". This command has supported SHA-256 for a while
now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index fa6a756123..a158428eb9 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -23,7 +23,7 @@ Tag Format
 A tag signature file, to be fed to this command's standard input,
 has a very simple fixed format: four lines of
 
-  object <sha1>
+  object <hash>
   type <typename>
   tag <tagname>
   tagger <tagger>
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 02/10] mktag: use default strbuf_read() hint
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 01/10] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:19             ` Junio C Hamano
  2020-11-26 22:22           ` [PATCH v2 03/10] mktag: reword write_object_file() error Ævar Arnfjörð Bjarmason
                             ` (7 subsequent siblings)
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the hardcoded hint of 2^12 to 0. The default strbuf hint is
perfectly fine here, and the only reason we were hardcoding it is
because it survived migration from a pre-strbuf fixed-sized buffer.

See fd17f5b5f77 (Replace all read_fd use with strbuf_read, and get rid
of it., 2007-09-10) for that migration.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4982d3a93e..ff7ac8e0e5 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,7 +161,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 4096) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0) {
 		die_errno("could not read from stdin");
 	}
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 03/10] mktag: reword write_object_file() error
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (2 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 02/10] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:20             ` Junio C Hamano
  2020-11-26 22:22           ` [PATCH v2 04/10] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
                             ` (6 subsequent siblings)
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the error message emitted when write_object_file() fails to
make more sense. At this point we're not writing a "tag file" (which
as an aside we never do, we just write to stdout). We are writing an
annotated tag object, let's say that instead.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index ff7ac8e0e5..603b55aca0 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -171,7 +171,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 		die("invalid tag signature file");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
-		die("unable to write tag file");
+		die("unable to write annotated tag object");
 
 	strbuf_release(&buf);
 	printf("%s\n", oid_to_hex(&result));
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 04/10] mktag: remove redundant braces in one-line body "if"
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (3 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 03/10] mktag: reword write_object_file() error Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 05/10] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
                             ` (5 subsequent siblings)
  10 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This minor stylistic churn is usually something we'd avoid, but if we
don't do this then the file after changes in subsequent commits will
only have this minor style inconsistency, so let's change this while
we're at it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 603b55aca0..dc354828f7 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,9 +161,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 0) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
-	}
 
 	/* Verify it for some basic sanity: it needs to start with
 	   "object <sha1>\ntype\ntagger " */
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 05/10] mktag tests: don't needlessly use a subshell
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (4 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 04/10] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 06/10] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
                             ` (4 subsequent siblings)
  10 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The use of a subshell dates back to e9b20943b77 (t/t3800: do not use a
temporary file to hold expected result., 2008-01-04). It's not needed
anymore, if it ever was.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d696aa4e52..0e411e3c45 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,7 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		( test_must_fail git mktag <tag.sig 2>message ) &&
+		test_must_fail git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 06/10] mktag tests: remove needless SHA-1 hardcoding
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (5 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 05/10] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:24             ` Junio C Hamano
  2020-11-26 22:22           ` [PATCH v2 07/10] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
                             ` (3 subsequent siblings)
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the tests amended in acb49d1cc8b (t3800: make hash-size
independent, 2019-08-18) even more to make them independent of either
SHA-1 or SHA-256.

Some of these tests were failing for the wrong reasons. The first one
being modified here would fail because the line starts with "xxxxxx"
instead of "object", the rest of the line doesn't matter.

Let's just put a valid hash on the rest of the line anyway to narrow
the test down for just the s/object/xxxxxx/ case.

The second one being modified here would fail under
GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
invalid SHA-256, but we should really be testing <some sha-256 length
garbage> when under SHA-256.

This doesn't really matter since we should be able to trust other
parts of the code to validate things in the 0-9a-f range, but let's
keep it for good measure.

There's a later test which tests an invalid SHA which looks like a
valid one, to stress the "We refuse to tag something we can't
verify[...]" logic in mktag.c.

But here we're testing for a SHA-length string which contains
characters outside of the /[0-9a-f]/i set.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 0e411e3c45..e9d7799537 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -43,7 +43,7 @@ check_verify_failure 'Tag object length check' \
 #  2. object line label check
 
 cat >tag.sig <<EOF
-xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
+xxxxxx $head
 type tag
 tag mytag
 tagger . <> 0 +0000
@@ -53,10 +53,10 @@ EOF
 check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
 
 ############################################################
-#  3. object line SHA1 check
+#  3. object line SHA check
 
 cat >tag.sig <<EOF
-object zz9e9b33986b1c2670fff52c5067603117b3e895
+object $(echo $head | tr 0-9a-f z)
 type tag
 tag mytag
 tagger . <> 0 +0000
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 07/10] mktag tests: improve verify_object() test coverage
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (6 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 06/10] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 08/10] fsck: add new "extra" checks for "mktag" Ævar Arnfjörð Bjarmason
                             ` (2 subsequent siblings)
  10 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The verify_object() function in "mktag.c" is tasked with ensuring that
our tag refers to a valid object.

The existing test for this might fail because it was also testing that
"type taggg" didn't refer to a valid object type (it should be "type
tag"), or because we referred to a valid object but got the type
wrong.

Let's split these tests up, so we're testing all combinations of a
non-existing object and in invalid/wrong "type" lines.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e9d7799537..a6a67b6f27 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -125,19 +125,52 @@ check_verify_failure '"type" line type-name length check' \
 	'^error: char.*: type too long$'
 
 ############################################################
-#  9. verify object (SHA1/type) check
+#  9. verify object (SHA/type) check
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
+type tag
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (SHA/type) check -- correct type, nonexisting object' \
+	'^error: char7: could not verify object.*$'
+
+cat >tag.sig <<EOF
+object $head
 type tagggg
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure 'verify object (SHA1/type) check' \
+check_verify_failure 'verify object (SHA/type) check -- made-up type, nonexisting object' \
+	'^fatal: invalid object type'
+
+cat >tag.sig <<EOF
+object $(test_oid deadbeef)
+type tagggg
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
 	'^error: char7: could not verify object.*$'
 
+cat >tag.sig <<EOF
+object $head
+type tree
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
+	'^error: char7: could not verify object'
+
 ############################################################
 # 10. verify tag-name check
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 08/10] fsck: add new "extra" checks for "mktag"
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (7 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 07/10] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:33             ` Junio C Hamano
  2020-11-26 22:22           ` [PATCH v2 09/10] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
  2020-11-26 22:22           ` [PATCH v2 10/10] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Add optional "extra" checks to fsck, these are needed to eventually
replace the custom not-quite-fsck code in mktag.c.

The mktag checks differ from fsck_tag() in several ways, one of those
is that fsck doesn't know how to refuse an object with custom headers,
and isn't strict about header and body newline separation.

Teach it how to optionally report these. I thought the best way to do
that given the current structure of the code was to add a new "extra"
category in addition to error/warn/info. Under --strict the "info"
becomes a "warn" and "warn" becomes "error". Existing users of
fsck's (and others, e.g. index-pack) --strict option rely on this.

By adding an "extra" category and only reporting it based on a flag in
fsck_options callers can opt-in to these "extra" messages, which
they'll then need to deal with in their own "error_func".

No tests are being added for this new functionality, they're added in
a subsequent commit where we teach "mktag" to use this new validation
mode.

I'm not changing fsck_commit() to validate commit objects like this
either, we could do that, but unlike in the tag case that code
wouldn't be used anywhere. If someone wants to write a "mkcommit" they
which behaves like "mktag" they can borrow or refactor this logic for
use in fsck_commit().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 fsck.c | 32 +++++++++++++++++++++++++++++++-
 fsck.h |  2 ++
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/fsck.c b/fsck.c
index f82e2fe9e3..3c25df2244 100644
--- a/fsck.c
+++ b/fsck.c
@@ -80,7 +80,10 @@ static struct oidset gitmodules_done = OIDSET_INIT;
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
-	FUNC(MISSING_TAGGER_ENTRY, INFO)
+	FUNC(MISSING_TAGGER_ENTRY, INFO) \
+	/* extra (only reported when requested) */ \
+	FUNC(EXTRA_HEADER_ENTRY, EXTRA) \
+	FUNC(EXTRA_HEADER_BODY_NEWLINE, EXTRA)
 
 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
 enum fsck_msg_id {
@@ -975,6 +978,33 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (options->extra && *buffer) {
+		if (!starts_with(buffer, "\n")) {
+			/*
+			 * The verify_headers() check will allow
+			 * e.g. "[...]tagger <tagger>\nsome
+			 * garbage\n\nmessage" to pass, thinking "some
+			 * garbage" could be a custom
+			 * header. E.g. "mktag" doesn't want any
+			 * unknown headers.
+			 */
+			ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+			if (ret)
+				goto done;
+		}
+		if (starts_with(buffer, "\n\n")) {
+			/*
+			 * Some callers such as "mktag" want to
+			 * disallow "[...]tagger
+			 * <tagger>\n\n\nmessage", only allowing a
+			 * single newline for separation.
+			 */
+			ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_BODY_NEWLINE, "invalid format - headers separated body by more than one newline");
+			if (ret)
+				goto done;
+		}
+	}
+
 done:
 	strbuf_release(&sb);
 	return ret;
diff --git a/fsck.h b/fsck.h
index 69cf715e79..110efc65fd 100644
--- a/fsck.h
+++ b/fsck.h
@@ -6,6 +6,7 @@
 #define FSCK_ERROR 1
 #define FSCK_WARN 2
 #define FSCK_IGNORE 3
+#define FSCK_EXTRA 4
 
 struct fsck_options;
 struct object;
@@ -40,6 +41,7 @@ struct fsck_options {
 	unsigned strict:1;
 	int *msg_type;
 	struct oidset skiplist;
+	unsigned extra:1;
 	kh_oid_map_t *object_names;
 };
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 09/10] mktag: use fsck instead of custom verify_tag()
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (8 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 08/10] fsck: add new "extra" checks for "mktag" Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:47             ` Junio C Hamano
  2020-11-26 22:22           ` [PATCH v2 10/10] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the validation logic in "mktag" to use fsck's fsck_tag()
instead of its own custom parser. Curiously the logic for both dates
back to the same commit[1]. Let's unify them so we're not maintaining
two sets functions to verify that a tag is OK.

Moving to fsck_tag() required teaching it to optionally use some
validations that only the old mktag code could perform. That was done
in an earlier commit, the "extraHeaderEntry" and
"extraHeaderBodyNewline" tests being added here make use of that
logic.

There was other "mktag" validation logic that I think makes sense to
just remove. Namely:

 A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
    code disallowed values larger than 1400.

    Yes there's currently no timezone with a greater offset[2], but
    since we allow any number of non-offical timezones (e.g. +1234)
    passing this through seems fine. Git also won't break in the
    future if e.g. French Polynesia decides it needs to outdo the Line
    Islands when it comes to timezone extravagance.

 B. fsck allows missing author names such as "tagger <email>", mktag
    wouldn't, but would allow e.g. "tagger [2 spaces] <email>" (but
    not "tagger [1 space] <email>"). Now we allow all of these.

 C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
    allows it.

We didn't only lose obscure validation logic, we also gained some:

 D. fsck disallows zero-padded dates, but mktag didn't care. So
    e.g. the timestamp "0000000000 +0000" produces an error now. A
    test in "t1006-cat-file.sh" relied on this, it's been changed to
    use "hash-object" (without fsck) instead.

1. ec4465adb38 (Add "tag" objects that can be used to sign other
   objects., 2005-04-25)

2. https://en.wikipedia.org/wiki/List_of_UTC_time_offsets

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c     | 197 ++++++++++++--------------------------------
 fsck.c              |  15 +++-
 fsck.h              |   9 ++
 t/t1006-cat-file.sh |   2 +-
 t/t3800-mktag.sh    |  78 +++++++++++-------
 5 files changed, 121 insertions(+), 180 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index dc354828f7..54b0d75ff7 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -2,160 +2,61 @@
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
+#include "fsck.h"
 
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
+static int mktag_fsck_error_func(struct fsck_options *o,
+				 const struct object_id *oid,
+				 enum object_type object_type,
+				 int msg_type, const char *message)
 {
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
-
-	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
-		free(buffer);
+	switch (msg_type) {
+	case FSCK_WARN:
+	case FSCK_ERROR:
+	case FSCK_EXTRA:
+		/*
+		 * We treat both warnings and errors as errors, things
+		 * like missing "tagger" lines are "only" warnings
+		 * under fsck, we've always considered them an error.
+		 */
+		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
+		return 1;
+	default:
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		    msg_type);
 	}
-	return ret;
 }
 
-static int verify_tag(char *buffer, unsigned long size)
+static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 {
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
+	int ret;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+	const struct object_id *repl;
+
+	buffer = read_object_file(tagged_oid, &type, &size);
+	if (!buffer)
+		die("could not read tagged object '%s'\n",
+		    oid_to_hex(tagged_oid));
+	if (type != *tagged_type)
+		die("object '%s' tagged as '%s', but is a '%s' type\n",
+		    oid_to_hex(tagged_oid),
+		    type_name(*tagged_type), type_name(type));
+
+	repl = lookup_replace_object(the_repository, tagged_oid);
+	ret = check_object_signature(the_repository, repl,
+				     buffer, size, type_name(*tagged_type));
+	free(buffer);
 
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
+	return ret;
 }
 
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
+	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+	struct object_id tagged_oid;
+	int tagged_type;
 	struct object_id result;
 
 	if (argc != 1)
@@ -164,10 +65,14 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
+	fsck_options.extra = 1;
+	fsck_options.error_func = mktag_fsck_error_func;
+	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
+				&tagged_oid, &tagged_type))
+		die("tag on stdin did not pass our strict fsck check");
+
+	if (verify_object_in_tag(&tagged_oid, &tagged_type))
+		die("tag on stdin did not refer to a valid object");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write annotated tag object");
diff --git a/fsck.c b/fsck.c
index 3c25df2244..97da3a13c6 100644
--- a/fsck.c
+++ b/fsck.c
@@ -914,6 +914,16 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		    unsigned long size, struct fsck_options *options)
 {
 	struct object_id tagged_oid;
+	int tagged_type;
+	return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
+				   &tagged_type);
+}
+
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tagged_type)
+{
 	int ret = 0;
 	char *eol;
 	struct strbuf sb = STRBUF_INIT;
@@ -927,7 +937,7 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
 		goto done;
 	}
-	if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
+	if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
 		if (ret)
 			goto done;
@@ -943,7 +953,8 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
 		goto done;
 	}
-	if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
+	*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
+	if (*tagged_type < 0)
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
 	if (ret)
 		goto done;
diff --git a/fsck.h b/fsck.h
index 110efc65fd..cf43046146 100644
--- a/fsck.h
+++ b/fsck.h
@@ -64,6 +64,15 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
 int fsck_object(struct object *obj, void *data, unsigned long size,
 	struct fsck_options *options);
 
+/*
+ * fsck a tag, and pass info about it back to the caller. This is
+ * exposed fsck_object() internals for git-mktag(1).
+ */
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tag_type);
+
 /*
  * Some fsck checks are context-dependent, and may end up queued; run this
  * after completing all fsck_object() calls in order to resolve any remaining
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2f501d2dc9..5d2dc99b74 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
 
 $tag_description"
 
-tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
 tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index a6a67b6f27..352235353f 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -37,7 +37,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+	'^error:.* missingObject:'
 
 ############################################################
 #  2. object line label check
@@ -50,7 +50,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
+check_verify_failure '"object" line label check' '^error:.* missingObject:'
 
 ############################################################
 #  3. object line SHA check
@@ -63,7 +63,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
 
 ############################################################
 #  4. type line label check
@@ -76,7 +76,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
 
 ############################################################
 #  5. type line eol check
@@ -84,7 +84,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
 
 ############################################################
 #  6. tag line label check #1
@@ -98,7 +98,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* missingTagEntry:'
 
 ############################################################
 #  7. tag line label check #2
@@ -110,7 +110,7 @@ tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* badType:'
 
 ############################################################
 #  8. type line type-name length check
@@ -122,7 +122,7 @@ tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char.*: type too long$'
+	'^error:.* badType:'
 
 ############################################################
 #  9. verify object (SHA/type) check
@@ -136,7 +136,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA/type) check -- correct type, nonexisting object' \
-	'^error: char7: could not verify object.*$'
+	'^fatal: could not read tagged object'
 
 cat >tag.sig <<EOF
 object $head
@@ -147,7 +147,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA/type) check -- made-up type, nonexisting object' \
-	'^fatal: invalid object type'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
@@ -158,7 +158,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object.*$'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $head
@@ -169,7 +169,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object'
+	'^fatal: object.*tagged as.*tree.*but is.*commit'
 
 ############################################################
 # 10. verify tag-name check
@@ -183,7 +183,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char.*: could not verify tag name$'
+	'^error:.* badTagName:'
 
 ############################################################
 # 11. tagger line label check #1
@@ -197,7 +197,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
 # 12. tagger line label check #2
@@ -212,10 +212,10 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
-# 13. disallow missing tag author name
+# 13. allow missing tag author name like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -226,8 +226,9 @@ tagger  <> 0 +0000
 This is filler
 EOF
 
-check_verify_failure 'disallow missing tag author name' \
-	'^error: char.*: missing tagger name$'
+test_expect_success 'allow missing tag author name' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -242,7 +243,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char.*: malformed tagger field$'
+	'^error:.* badEmail:'
 
 ############################################################
 # 15. allow empty tag email
@@ -260,7 +261,7 @@ test_expect_success \
     'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
-# 16. disallow spaces in tag email
+# 16. allow spaces in tag email like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -270,8 +271,9 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 
 EOF
 
-check_verify_failure 'disallow spaces in tag email' \
-	'^error: char.*: malformed tagger field$'
+test_expect_success 'allow spaces in tag email like fsck' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -285,7 +287,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -299,7 +301,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -313,7 +315,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char.*: malformed tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -327,7 +329,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -341,10 +343,10 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
-# 22. detect invalid tag timezone3
+# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
 
 cat >tag.sig <<EOF
 object $head
@@ -354,8 +356,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 
 EOF
 
-check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char.*: malformed tag timezone$'
+test_expect_success 'allow invalid tag timezone' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 23. detect invalid header entry
@@ -370,7 +373,20 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char.*: trailing garbage in tag header$'
+	'^error:.* extraHeaderEntry:'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+
+this line should be one line up
+EOF
+
+check_verify_failure 'detect invalid header entry' \
+	'^error:.* extraHeaderBodyNewline:'
 
 ############################################################
 # 24. create valid tag
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v2 10/10] mktag doc: update to explain why to use this
  2020-11-26  1:28         ` [RFC/PATCH 00/12] make "mktag" use fsck_tag() Ævar Arnfjörð Bjarmason
                             ` (9 preceding siblings ...)
  2020-11-26 22:22           ` [PATCH v2 09/10] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-11-26 22:22           ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:59             ` Junio C Hamano
  10 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-11-26 22:22 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the mktag documentation to compare itself to the similar
"hash-object -t tag" command. Before this someone reading the
documentation wouldn't have much of an idea what the difference
was.

Let's make it clear that it's to do with slightly different fsck
validation logic, and cross-link the "mktag" and "hash-object"
documentation to aid discover-ability.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-hash-object.txt |  4 ++++
 Documentation/git-mktag.txt       | 29 +++++++++++++++++++++++++----
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index df9e2c58bd..c535661ced 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -58,6 +58,10 @@ OPTIONS
 	stress-testing Git itself or reproducing characteristics of corrupt or
 	bogus objects encountered in the wild.
 
+SEE ALSO
+--------
+linkgit:git-mktag[1]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index a158428eb9..3ba15072df 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -3,7 +3,7 @@ git-mktag(1)
 
 NAME
 ----
-git-mktag - Creates a tag object
+git-mktag - Creates a tag object with extra validation
 
 
 SYNOPSIS
@@ -13,10 +13,20 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Reads a tag contents on standard input and creates a tag object
-that can also be used to sign other objects.
 
-The output is the new tag's <object> identifier.
+Reads a tag contents on standard input and creates a tag object. The
+output is the new tag's <object> identifier.
+
+This command accepts a subset of what linkgit:git-hash-object[1] would
+accept with `-t tag --stdin`. I.e. both of these work:
+
+    git mktag <my-tag
+    git hash-object -t tag --stdin <my-tag
+
+The difference between the two is that mktag does the equivalent of a
+linkgit:git-fsck(1) check on its input, and furthermore disallows some
+thing linkgit:git-hash-object[1] would pass, e.g. extra headers in the
+object before the message.
 
 Tag Format
 ----------
@@ -34,6 +44,17 @@ exists, is separated by a blank line from the header.  The
 message part may contain a signature that Git itself doesn't
 care about, but that can be verified with gpg.
 
+HISTORY
+-------
+
+In versions of Git before v2.30.0 the "mktag" command's validation
+logic was subtly different than that of linkgit:git-fsck[1]. It is now
+a strict superset of linkgit:git-fsck[1]'s validation logic.
+
+SEE ALSO
+--------
+linkgit:git-hash-object[1],
+
 GIT
 ---
 Part of the linkgit:git[1] suite
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 00/10] make "mktag" use fsck_tag()
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
@ 2020-12-01 10:08             ` Ævar Arnfjörð Bjarmason
  2020-12-01 20:01               ` Junio C Hamano
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                               ` (10 subsequent siblings)
  11 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-01 10:08 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason


On Thu, Nov 26 2020, Ævar Arnfjörð Bjarmason wrote:

> Now a non-RFC. I went for the approach I suggested in
> <87r1ognv4b.fsf@evledraar.gmail.com> of just having fsck_tag() able to
> optionally tell us about its parsed tag/type, thus avoiding any need
> for a custom parser in mktag.c. Hopefully I've addressed the rest of
> the feedback, range-diff below.

Ping @ Jeff & brian: you said you wanted this in one shape or another,
so mind seeing if the v2 looks good to you?:)

Junio didn't pick it up for the "What's Cooking" sent out recently,
hopefully some reviewer ACK/NACK will help move it forward. Thanks!

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 00/10] make "mktag" use fsck_tag()
  2020-12-01 10:08             ` Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:01               ` Junio C Hamano
  2020-12-02 22:20                 ` Junio C Hamano
  0 siblings, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:01 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:

> On Thu, Nov 26 2020, Ævar Arnfjörð Bjarmason wrote:
>
>> Now a non-RFC. I went for the approach I suggested in
>> <87r1ognv4b.fsf@evledraar.gmail.com> of just having fsck_tag() able to
>> optionally tell us about its parsed tag/type, thus avoiding any need
>> for a custom parser in mktag.c. Hopefully I've addressed the rest of
>> the feedback, range-diff below.
>
> Ping @ Jeff & brian: you said you wanted this in one shape or another,
> so mind seeing if the v2 looks good to you?:)
>
> Junio didn't pick it up for the "What's Cooking" sent out recently,
> hopefully some reviewer ACK/NACK will help move it forward. Thanks!

True.  I don't want to queue too many topics on 'seen', only to end
up with a pile of patches that haven't been reviewed adequately and
cannot move forward.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 01/10] mktag doc: say <hash> not <sha1>
  2020-11-26 22:22           ` [PATCH v2 01/10] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:17             ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:17 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change the "mktag" documentation to refer to the input hash as just
> "hash", not "sha1". This command has supported SHA-256 for a while
> now.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---

I think saying <hash> instead of <sha> is a very good idea---it won't
tie us to the SHA family of hashes, including SHA-256, forever.

>  Documentation/git-mktag.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
> index fa6a756123..a158428eb9 100644
> --- a/Documentation/git-mktag.txt
> +++ b/Documentation/git-mktag.txt
> @@ -23,7 +23,7 @@ Tag Format
>  A tag signature file, to be fed to this command's standard input,
>  has a very simple fixed format: four lines of
>  
> -  object <sha1>
> +  object <hash>
>    type <typename>
>    tag <tagname>
>    tagger <tagger>

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 02/10] mktag: use default strbuf_read() hint
  2020-11-26 22:22           ` [PATCH v2 02/10] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:19             ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:19 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change the hardcoded hint of 2^12 to 0. The default strbuf hint is
> perfectly fine here, and the only reason we were hardcoding it is
> because it survived migration from a pre-strbuf fixed-sized buffer.
>
> See fd17f5b5f77 (Replace all read_fd use with strbuf_read, and get rid
> of it., 2007-09-10) for that migration.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/mktag.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/builtin/mktag.c b/builtin/mktag.c
> index 4982d3a93e..ff7ac8e0e5 100644
> --- a/builtin/mktag.c
> +++ b/builtin/mktag.c
> @@ -161,7 +161,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)

In the lines beyond the pre-context there is a comment that mentions
<sha1>, but I think it is sensible not to clean it up with this
patch, as it will go away with the main "use fsck machinery" step.

>  	if (argc != 1)
>  		usage("git mktag");
>  
> -	if (strbuf_read(&buf, 0, 4096) < 0) {
> +	if (strbuf_read(&buf, 0, 0) < 0) {
>  		die_errno("could not read from stdin");
>  	}

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 03/10] mktag: reword write_object_file() error
  2020-11-26 22:22           ` [PATCH v2 03/10] mktag: reword write_object_file() error Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:20             ` Junio C Hamano
  2020-12-01 20:49               ` Junio C Hamano
  0 siblings, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change the error message emitted when write_object_file() fails to
> make more sense. At this point we're not writing a "tag file" (which
> as an aside we never do, we just write to stdout). We are writing an
> annotated tag object, let's say that instead.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  builtin/mktag.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/builtin/mktag.c b/builtin/mktag.c
> index ff7ac8e0e5..603b55aca0 100644
> --- a/builtin/mktag.c
> +++ b/builtin/mktag.c
> @@ -171,7 +171,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
>  		die("invalid tag signature file");
>  
>  	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
> -		die("unable to write tag file");
> +		die("unable to write annotated tag object");

"write an annotated tag object"?

It is not just this call to die(), but we'd eventually want to _(l10n/i18n)
these messages.  Perhaps in a separate step but on all messages fed
to die/error/warn in this file.

>  
>  	strbuf_release(&buf);
>  	printf("%s\n", oid_to_hex(&result));

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 06/10] mktag tests: remove needless SHA-1 hardcoding
  2020-11-26 22:22           ` [PATCH v2 06/10] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:24             ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:24 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change the tests amended in acb49d1cc8b (t3800: make hash-size
> independent, 2019-08-18) even more to make them independent of either
> SHA-1 or SHA-256.
>
> Some of these tests were failing for the wrong reasons. The first one
> being modified here would fail because the line starts with "xxxxxx"
> instead of "object", the rest of the line doesn't matter.
>
> Let's just put a valid hash on the rest of the line anyway to narrow
> the test down for just the s/object/xxxxxx/ case.
>
> The second one being modified here would fail under
> GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
> invalid SHA-256, but we should really be testing <some sha-256 length
> garbage> when under SHA-256.
>
> This doesn't really matter since we should be able to trust other
> parts of the code to validate things in the 0-9a-f range, but let's
> keep it for good measure.
>
> There's a later test which tests an invalid SHA which looks like a
> valid one, to stress the "We refuse to tag something we can't
> verify[...]" logic in mktag.c.
>
> But here we're testing for a SHA-length string which contains
> characters outside of the /[0-9a-f]/i set.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t3800-mktag.sh | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index 0e411e3c45..e9d7799537 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -43,7 +43,7 @@ check_verify_failure 'Tag object length check' \
>  #  2. object line label check
>  
>  cat >tag.sig <<EOF
> -xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
> +xxxxxx $head
>  type tag
>  tag mytag
>  tagger . <> 0 +0000

These steps to prepare the input and the expected output outside the
test_expect_* block look too old-fashioned but they are consistently
so, so let's let them pass, at least inside this series.

> @@ -53,10 +53,10 @@ EOF
>  check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
>  
>  ############################################################
> -#  3. object line SHA1 check
> +#  3. object line SHA check

Shouldn't we say hash instead of SHA for consistency?

>  
>  cat >tag.sig <<EOF
> -object zz9e9b33986b1c2670fff52c5067603117b3e895
> +object $(echo $head | tr 0-9a-f z)
>  type tag
>  tag mytag
>  tagger . <> 0 +0000

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 08/10] fsck: add new "extra" checks for "mktag"
  2020-11-26 22:22           ` [PATCH v2 08/10] fsck: add new "extra" checks for "mktag" Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:33             ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:33 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Add optional "extra" checks to fsck, these are needed to eventually
> replace the custom not-quite-fsck code in mktag.c.
>
> The mktag checks differ from fsck_tag() in several ways, one of those
> is that fsck doesn't know how to refuse an object with custom headers,
> and isn't strict about header and body newline separation.

You say "there must be only one blank line between the header and
the body", but viewing from the way we parse header and body, I
think that such a rule actually forbids a leading blank line in the
body and steps into checking whitespace errors---makes readers
wonder if we should be also detecting trailing whitespaces on lines,
etc.

Is there actually such a check enforced in the original?  Or is this
a new rule that appeared out of thin air?  We'd have to inspect the
lines deleted from builtin/mktag.c in the next step, I gues.

> By adding an "extra" category and only reporting it based on a flag in
> fsck_options callers can opt-in to these "extra" messages, which
> they'll then need to deal with in their own "error_func".

Makes sense.


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 09/10] mktag: use fsck instead of custom verify_tag()
  2020-11-26 22:22           ` [PATCH v2 09/10] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:47             ` Junio C Hamano
  2020-12-01 22:28               ` Junio C Hamano
  0 siblings, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:47 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change the validation logic in "mktag" to use fsck's fsck_tag()
> instead of its own custom parser. Curiously the logic for both dates
> back to the same commit[1]. Let's unify them so we're not maintaining
> two sets functions to verify that a tag is OK.
>
> Moving to fsck_tag() required teaching it to optionally use some
> validations that only the old mktag code could perform. That was done
> in an earlier commit, the "extraHeaderEntry" and
> "extraHeaderBodyNewline" tests being added here make use of that
> logic.
>
> There was other "mktag" validation logic that I think makes sense to
> just remove. Namely:

I may not agree with the specifics in this list, but I agree that
the validation should be consistent between mktag and fsck.

> +	switch (msg_type) {
> +	case FSCK_WARN:
> +	case FSCK_ERROR:
> +	case FSCK_EXTRA:
> +		/*
> +		 * We treat both warnings and errors as errors, things
> +		 * like missing "tagger" lines are "only" warnings
> +		 * under fsck, we've always considered them an error.
> +		 */

This is a good comment and design decision.  

As far as I am concerned, the only reason we warn on a missing
tagger line without erroring out is because very early versions of
Git did allow creating such tag objects, and there are annotated
tags in the wild that lack the tagger line.

> +		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
> +		return 1;
> +	default:
> +		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
> +		    msg_type);
>  	}
> -	return ret;
>  }
>  
> -static int verify_tag(char *buffer, unsigned long size)
> ...
> -	/* timezone, 5 digits [+-]hhmm, max. 1400 */
> -	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
> -	      strspn(tagger_line+1, "0123456789") == 4 &&
> -	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
> -		return error("char%"PRIuMAX": malformed tag timezone",
> -			(uintmax_t) (tagger_line - buffer));
> -	tagger_line += 6;
> -
> -	/* Verify the blank line separating the header from the body */
> -	if (*tagger_line != '\n')
> -		return error("char%"PRIuMAX": trailing garbage in tag header",
> -			(uintmax_t) (tagger_line - buffer));
>  
> -	/* The actual stuff afterwards we don't care about.. */
> -	return 0;

I do not see the "we do not want more than one blank line after the
header" in the original, which was one thing I was looking for after
seeing what 08/10 did.

> +	fsck_options.extra = 1;
> +	fsck_options.error_func = mktag_fsck_error_func;

I wonder if we really need the new .extra bit member in the
fsck_options.  Wouldn't it be sufficient to instead teach
fsck_error_func() that the extra level is a non-event?


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 03/10] mktag: reword write_object_file() error
  2020-12-01 20:20             ` Junio C Hamano
@ 2020-12-01 20:49               ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:49 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Junio C Hamano <gitster@pobox.com> writes:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> Change the error message emitted when write_object_file() fails to
>> make more sense. At this point we're not writing a "tag file" (which
>> as an aside we never do, we just write to stdout). We are writing an
>> annotated tag object, let's say that instead.
>>
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> ---
>>  builtin/mktag.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/builtin/mktag.c b/builtin/mktag.c
>> index ff7ac8e0e5..603b55aca0 100644
>> --- a/builtin/mktag.c
>> +++ b/builtin/mktag.c
>> @@ -171,7 +171,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
>>  		die("invalid tag signature file");
>>  
>>  	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
>> -		die("unable to write tag file");
>> +		die("unable to write annotated tag object");
>
> "write an annotated tag object"?

Actually, there is no such thing as an "unannotated tag object".
Perhaps _("unable to create a tag object")?

>
> It is not just this call to die(), but we'd eventually want to _(l10n/i18n)
> these messages.  Perhaps in a separate step but on all messages fed
> to die/error/warn in this file.
>
>>  
>>  	strbuf_release(&buf);
>>  	printf("%s\n", oid_to_hex(&result));

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 10/10] mktag doc: update to explain why to use this
  2020-11-26 22:22           ` [PATCH v2 10/10] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
@ 2020-12-01 20:59             ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 20:59 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> +Reads a tag contents on standard input and creates a tag object. The
> +output is the new tag's <object> identifier.
> +
> +This command accepts a subset of what linkgit:git-hash-object[1] would
> +accept with `-t tag --stdin`. I.e. both of these work:
> +
> +    git mktag <my-tag
> +    git hash-object -t tag --stdin <my-tag

It's misleading to say "both of these work", I am afraid.  If the
former works, the latter would.  That is what "accepts a subset"
means, no?

> +The difference between the two is that mktag does the equivalent of a
> +linkgit:git-fsck(1) check on its input, and furthermore disallows some
> +thing linkgit:git-hash-object[1] would pass, e.g. extra headers in the
> +object before the message.

Good description.

> @@ -34,6 +44,17 @@ exists, is separated by a blank line from the header.  The
>  message part may contain a signature that Git itself doesn't
>  care about, but that can be verified with gpg.
>  
> +HISTORY
> +-------
> +
> +In versions of Git before v2.30.0 the "mktag" command's validation

Hardcoding v2.30.0 here feels problematic.  If the series cooks in
'next' while 2.30 gets released, it has to be kicked out of 'next'
to update this line before it gets allowed in 'next'.

> +logic was subtly different than that of linkgit:git-fsck[1]. It is now
> +a strict superset of linkgit:git-fsck[1]'s validation logic.

It may be a better direction to go to drop this section.

Also, I somehow have a feeling that we'd rather want to loosen the
"no other headers allowed" in the longer run to be consistent with
what "fsck" does.

I also wonder if we want to teach "commit-tree" to also run fsck
check like this new version of mktag does.  It is outside the scope
of this "mktag" series, of course.

Thanks.

> +SEE ALSO
> +--------
> +linkgit:git-hash-object[1],
> +
>  GIT
>  ---
>  Part of the linkgit:git[1] suite

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 09/10] mktag: use fsck instead of custom verify_tag()
  2020-12-01 20:47             ` Junio C Hamano
@ 2020-12-01 22:28               ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-01 22:28 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Junio C Hamano <gitster@pobox.com> writes:

> I do not see the "we do not want more than one blank line after the
> header" in the original, which was one thing I was looking for after
> seeing what 08/10 did.
>
>> +	fsck_options.extra = 1;
>> +	fsck_options.error_func = mktag_fsck_error_func;

Hmph, recent "released" versions of Git seems to be fine when

--- >8 ------ >8 ------ >8 ------ >8 ------ >8 ---
object 72ffeb997eaf999f6938b2a7e0d9a75dcceaa311
type commit
tag tester
tagger Junio C Hamano <gitster@pobox.com> 1606860947 -0800


a message after a blank
--- 8< ------ 8< ------ 8< ------ 8< ------ 8< ---

is fed to their "git mktag".  If I am not mistaken, we definitely
want to drop the EXTRA_HEADER_BODY_NEWLINE check from 08/10, even
though EXTRA_HEADER_ENTRY may be something we want to retain at
least for some releases for backward compatibility.




^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 00/10] make "mktag" use fsck_tag()
  2020-12-01 20:01               ` Junio C Hamano
@ 2020-12-02 22:20                 ` Junio C Hamano
  2020-12-03 16:38                   ` Ævar Arnfjörð Bjarmason
  0 siblings, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-12-02 22:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Junio C Hamano <gitster@pobox.com> writes:

> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>
>> On Thu, Nov 26 2020, Ævar Arnfjörð Bjarmason wrote:
>>
>>> Now a non-RFC. I went for the approach I suggested in
>>> <87r1ognv4b.fsf@evledraar.gmail.com> of just having fsck_tag() able to
>>> optionally tell us about its parsed tag/type, thus avoiding any need
>>> for a custom parser in mktag.c. Hopefully I've addressed the rest of
>>> the feedback, range-diff below.
>>
>> Ping @ Jeff & brian: you said you wanted this in one shape or another,
>> so mind seeing if the v2 looks good to you?:)
>>
>> Junio didn't pick it up for the "What's Cooking" sent out recently,
>> hopefully some reviewer ACK/NACK will help move it forward. Thanks!
>
> True.  I don't want to queue too many topics on 'seen', only to end
> up with a pile of patches that haven't been reviewed adequately and
> cannot move forward.

So, now I've seen all of them.

There were some minor things in the earlier part I commented on, and
if I am not mistaken, a new check, "body must not begin with a blank
line", should not be added at all, which would affect 08/10.

I am not sure how much longer we want to retain the .extra level of
checks that are more strict than those of fsck.  If we decide that
it is not worth it to forbid new object headers, we may be able to
lose 08/10 altogether.

Other than the above, the series mostly looked well done.

Thanks.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v2 00/10] make "mktag" use fsck_tag()
  2020-12-02 22:20                 ` Junio C Hamano
@ 2020-12-03 16:38                   ` Ævar Arnfjörð Bjarmason
  0 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-03 16:38 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin


On Wed, Dec 02 2020, Junio C Hamano wrote:

> Junio C Hamano <gitster@pobox.com> writes:
>
>> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
>>
>>> On Thu, Nov 26 2020, Ævar Arnfjörð Bjarmason wrote:
>>>
>>>> Now a non-RFC. I went for the approach I suggested in
>>>> <87r1ognv4b.fsf@evledraar.gmail.com> of just having fsck_tag() able to
>>>> optionally tell us about its parsed tag/type, thus avoiding any need
>>>> for a custom parser in mktag.c. Hopefully I've addressed the rest of
>>>> the feedback, range-diff below.
>>>
>>> Ping @ Jeff & brian: you said you wanted this in one shape or another,
>>> so mind seeing if the v2 looks good to you?:)
>>>
>>> Junio didn't pick it up for the "What's Cooking" sent out recently,
>>> hopefully some reviewer ACK/NACK will help move it forward. Thanks!
>>
>> True.  I don't want to queue too many topics on 'seen', only to end
>> up with a pile of patches that haven't been reviewed adequately and
>> cannot move forward.
>
> So, now I've seen all of them.
>
> There were some minor things in the earlier part I commented on, and
> if I am not mistaken, a new check, "body must not begin with a blank
> line", should not be added at all, which would affect 08/10.
>
> I am not sure how much longer we want to retain the .extra level of
> checks that are more strict than those of fsck.  If we decide that
> it is not worth it to forbid new object headers, we may be able to
> lose 08/10 altogether.
>
> Other than the above, the series mostly looked well done.

Hi. Just a quick note to say thanks for all the feedback, and that I
don't have a v3 ready now, but will submit one soon-ish.

FWIW the header-body newline thing wasn't something I was trying to
sneak in, I went wrong in my testing somewhere and thought it was a bug
under mktag. Will test for that, remove that check or whatever as
appropriate. Thanks for the review.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 00/10] make "mktag" use fsck_tag()
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
  2020-12-01 10:08             ` Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 22:30               ` Junio C Hamano
                                 ` (21 more replies)
  2020-12-09 20:01             ` [PATCH v3 01/10] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
                               ` (9 subsequent siblings)
  11 siblings, 22 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This version should address all the comments Junio made on v2. Changes:

 * The whole "extra" fsck option is gone, I just didn't realize I
   could set the new check to "ignore", and then manually promote it.

 * Ejected "mktag: reword write_object_file() error". It was the same
   phrasing as "git tag" uses, let's just keep it.

 * Clarifications in docs/commit messages

 * There's 2 extra patches at the end now which take the first steps
   into making "git mktag" more of a normal builtin. It reads fsck.*
   config variables, so you can turn off that "no extra headers" check
   through the normal fsck.<msg-id>=ignore config.

   It should also be moved to getopts, and we could make it support
   --no-strict to have the same idea of error/warning as fsck itself,
   but that's #leftoverbits, along with moving it to i18n.

   It would be nice to have patches 1-8 merged down if they're deemed
   ready, and if 9-10 aren't deemed wanted just discard them. I think
   it makes sense though...

Ævar Arnfjörð Bjarmason (10):
  mktag doc: say <hash> not <sha1>
  mktag: use default strbuf_read() hint
  mktag: remove redundant braces in one-line body "if"
  mktag tests: don't needlessly use a subshell
  mktag tests: remove needless SHA-1 hardcoding
  mktag tests: improve verify_object() test coverage
  mktag: use fsck instead of custom verify_tag()
  mktag doc: update to explain why to use this
  fsck: make fsck_config() re-usable
  mktag: allow turning off fsck.extraHeaderEntry

 Documentation/git-hash-object.txt |   4 +
 Documentation/git-mktag.txt       |  34 ++++-
 builtin/fsck.c                    |  20 +--
 builtin/mktag.c                   | 204 +++++++++---------------------
 fsck.c                            |  57 ++++++++-
 fsck.h                            |  16 +++
 t/t1006-cat-file.sh               |   2 +-
 t/t3800-mktag.sh                  | 132 ++++++++++++++-----
 8 files changed, 261 insertions(+), 208 deletions(-)

Range-diff:
 1:  f46abb37df9 =  1:  aee3f52a478 mktag doc: say <hash> not <sha1>
 2:  1b4d9a53302 =  2:  6e98557709a mktag: use default strbuf_read() hint
 3:  83f4af6013e <  -:  ----------- mktag: reword write_object_file() error
 4:  bca1484ed96 =  3:  8e5fe08f155 mktag: remove redundant braces in one-line body "if"
 5:  ac7c4097c90 =  4:  1f06b9c0cf9 mktag tests: don't needlessly use a subshell
 6:  5e076659e45 !  5:  5d1cb73ca35 mktag tests: remove needless SHA-1 hardcoding
    @@ t/t3800-mktag.sh: EOF
      
      ############################################################
     -#  3. object line SHA1 check
    -+#  3. object line SHA check
    ++#  3. object line hash check
      
      cat >tag.sig <<EOF
     -object zz9e9b33986b1c2670fff52c5067603117b3e895
 7:  a048c3e6401 !  6:  cf86f4ca37d mktag tests: improve verify_object() test coverage
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
      
      ############################################################
     -#  9. verify object (SHA1/type) check
    -+#  9. verify object (SHA/type) check
    ++#  9. verify object (hash/type) check
      
      cat >tag.sig <<EOF
      object $(test_oid deadbeef)
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
     +
     +EOF
     +
    -+check_verify_failure 'verify object (SHA/type) check -- correct type, nonexisting object' \
    ++check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
     +	'^error: char7: could not verify object.*$'
     +
     +cat >tag.sig <<EOF
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
      EOF
      
     -check_verify_failure 'verify object (SHA1/type) check' \
    -+check_verify_failure 'verify object (SHA/type) check -- made-up type, nonexisting object' \
    ++check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
     +	'^fatal: invalid object type'
     +
     +cat >tag.sig <<EOF
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
     +
     +EOF
     +
    -+check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
    ++check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
      	'^error: char7: could not verify object.*$'
      
     +cat >tag.sig <<EOF
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
     +
     +EOF
     +
    -+check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
    ++check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
     +	'^error: char7: could not verify object'
     +
      ############################################################
 8:  dab44d32359 <  -:  ----------- fsck: add new "extra" checks for "mktag"
 9:  8ff853caeea !  7:  5812ee53c97 mktag: use fsck instead of custom verify_tag()
    @@ Commit message
         back to the same commit[1]. Let's unify them so we're not maintaining
         two sets functions to verify that a tag is OK.
     
    -    Moving to fsck_tag() required teaching it to optionally use some
    -    validations that only the old mktag code could perform. That was done
    -    in an earlier commit, the "extraHeaderEntry" and
    -    "extraHeaderBodyNewline" tests being added here make use of that
    -    logic.
    +    The behavior of fsck_tag() and the old "mktag" code being removed here
    +    is different in few aspects.
     
    -    There was other "mktag" validation logic that I think makes sense to
    -    just remove. Namely:
    +    I think it makes sense to remove some of those checks, namely:
     
          A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
             code disallowed values larger than 1400.
    @@ Commit message
          C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
             allows it.
     
    -    We didn't only lose obscure validation logic, we also gained some:
    +    In some ways fsck_tag() is stricter than "mktag" was, namely:
     
          D. fsck disallows zero-padded dates, but mktag didn't care. So
             e.g. the timestamp "0000000000 +0000" produces an error now. A
             test in "t1006-cat-file.sh" relied on this, it's been changed to
             use "hash-object" (without fsck) instead.
     
    +    There was one check I deemed worth keeping by porting it over to
    +    fsck_tag():
    +
    +     E. "mktag" did not allow any custom headers, and by extension (as an
    +        empty commit is allowed) also forbade an extra stray trailing
    +        newline after the headers it knew about.
    +
    +        Add a new check in the "ignore" category to fsck and use it. This
    +        somewhat abuses the facility added in efaba7cc77f (fsck:
    +        optionally ignore specific fsck issues completely, 2015-06-22).
    +
    +        This is somewhat of hack, but probably the least invasive change
    +        we can make here. The fsck command will shuffle these categories
    +        around, e.g. under --strict the "info" becomes a "warn" and "warn"
    +        becomes "error". Existing users of fsck's (and others,
    +        e.g. index-pack) --strict option rely on this.
    +
    +        So we need to put something into a category that'll be ignored by
    +        all existing users of the API. Pretending that
    +        fsck.extraHeaderEntry=error ("ignore" by default) was set serves
    +        to do this for us.
    +
         1. ec4465adb38 (Add "tag" objects that can be used to sign other
            objects., 2005-04-25)
     
    @@ builtin/mktag.c
     +	switch (msg_type) {
     +	case FSCK_WARN:
     +	case FSCK_ERROR:
    -+	case FSCK_EXTRA:
     +		/*
     +		 * We treat both warnings and errors as errors, things
     +		 * like missing "tagger" lines are "only" warnings
    @@ builtin/mktag.c: int cmd_mktag(int argc, const char **argv, const char *prefix)
     -	   "object <sha1>\ntype\ntagger " */
     -	if (verify_tag(buf.buf, buf.len) < 0)
     -		die("invalid tag signature file");
    -+	fsck_options.extra = 1;
     +	fsck_options.error_func = mktag_fsck_error_func;
    ++	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
     +	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
     +				&tagged_oid, &tagged_type))
     +		die("tag on stdin did not pass our strict fsck check");
    @@ builtin/mktag.c: int cmd_mktag(int argc, const char **argv, const char *prefix)
     +		die("tag on stdin did not refer to a valid object");
      
      	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
    - 		die("unable to write annotated tag object");
    + 		die("unable to write tag file");
     
      ## fsck.c ##
    +@@ fsck.c: static struct oidset gitmodules_done = OIDSET_INIT;
    + 	/* infos (reported as warnings, but ignored by default) */ \
    + 	FUNC(GITMODULES_PARSE, INFO) \
    + 	FUNC(BAD_TAG_NAME, INFO) \
    +-	FUNC(MISSING_TAGGER_ENTRY, INFO)
    ++	FUNC(MISSING_TAGGER_ENTRY, INFO) \
    ++	/* ignored (elevated when requested) */ \
    ++	FUNC(EXTRA_HEADER_ENTRY, IGNORE)
    + 
    + #define MSG_ID(id, msg_type) FSCK_MSG_##id,
    + enum fsck_msg_id {
     @@ fsck.c: static int fsck_tag(const struct object_id *oid, const char *buffer,
      		    unsigned long size, struct fsck_options *options)
      {
    @@ fsck.c: static int fsck_tag(const struct object_id *oid, const char *buffer,
      		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
      	if (ret)
      		goto done;
    +@@ fsck.c: static int fsck_tag(const struct object_id *oid, const char *buffer,
    + 	else
    + 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
    + 
    ++	if (!starts_with(buffer, "\n")) {
    ++		/*
    ++		 * The verify_headers() check will allow
    ++		 * e.g. "[...]tagger <tagger>\nsome
    ++		 * garbage\n\nmessage" to pass, thinking "some
    ++		 * garbage" could be a custom header. E.g. "mktag"
    ++		 * doesn't want any unknown headers.
    ++		 */
    ++		ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
    ++		if (ret)
    ++			goto done;
    ++	}
    ++
    + done:
    + 	strbuf_release(&sb);
    + 	return ret;
     
      ## fsck.h ##
     @@ fsck.h: int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     +check_verify_failure '"object" line label check' '^error:.* missingObject:'
      
      ############################################################
    - #  3. object line SHA check
    + #  3. object line hash check
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      
      EOF
    @@ t/t3800-mktag.sh: tag mytag
     +	'^error:.* badType:'
      
      ############################################################
    - #  9. verify object (SHA/type) check
    + #  9. verify object (hash/type) check
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (SHA/type) check -- correct type, nonexisting object' \
    + check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
     -	'^error: char7: could not verify object.*$'
     +	'^fatal: could not read tagged object'
      
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (SHA/type) check -- made-up type, nonexisting object' \
    + check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
     -	'^fatal: invalid object type'
     +	'^error:.* badType:'
      
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
    + check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
     -	'^error: char7: could not verify object.*$'
     +	'^error:.* badType:'
      
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (SHA/type) check -- incorrect type, valid object' \
    + check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
     -	'^error: char7: could not verify object'
     +	'^fatal: object.*tagged as.*tree.*but is.*commit'
      
    @@ t/t3800-mktag.sh: this line should not be here
     +tagger T A Gger <tagger@example.com> 1206478233 -0500
     +
     +
    -+this line should be one line up
    ++this line comes after an extra newline
     +EOF
     +
    -+check_verify_failure 'detect invalid header entry' \
    -+	'^error:.* extraHeaderBodyNewline:'
    ++test_expect_success \
    ++    'allow extra newlines at start of body' \
    ++    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
      
      ############################################################
      # 24. create valid tag
10:  e38feefd3f8 !  8:  fa04664f7f1 mktag doc: update to explain why to use this
    @@ Documentation/git-mktag.txt: SYNOPSIS
     +Reads a tag contents on standard input and creates a tag object. The
     +output is the new tag's <object> identifier.
     +
    -+This command accepts a subset of what linkgit:git-hash-object[1] would
    -+accept with `-t tag --stdin`. I.e. both of these work:
    ++This command is mostly equivalent to linkgit:git-hash-object[1]
    ++invoked with `-t tag -w --stdin`. I.e. both of these will create and
    ++write a tag found in `my-tag`:
     +
     +    git mktag <my-tag
    -+    git hash-object -t tag --stdin <my-tag
    ++    git hash-object -t tag -w --stdin <my-tag
     +
    -+The difference between the two is that mktag does the equivalent of a
    -+linkgit:git-fsck(1) check on its input, and furthermore disallows some
    -+thing linkgit:git-hash-object[1] would pass, e.g. extra headers in the
    -+object before the message.
    ++The difference is that mktag will die before writing the tag if the
    ++tag doesn't pass a linkgit:git-fsck[1] check.
    ++
    ++The "fsck" check done mktag is is stricter than what
    ++linkgit:git-fsck[1] would run by default in that all `fsck.<msg-id>`
    ++messages are promoted from warnings to errors (so e.g. a missing
    ++"tagger" line is an error). Extra headers in the object are also an
    ++error under mktag, but ignored by linkgit:git-fsck[1].
      
      Tag Format
      ----------
    @@ Documentation/git-mktag.txt: exists, is separated by a blank line from the heade
      message part may contain a signature that Git itself doesn't
      care about, but that can be verified with gpg.
      
    -+HISTORY
    -+-------
    -+
    -+In versions of Git before v2.30.0 the "mktag" command's validation
    -+logic was subtly different than that of linkgit:git-fsck[1]. It is now
    -+a strict superset of linkgit:git-fsck[1]'s validation logic.
    -+
     +SEE ALSO
     +--------
     +linkgit:git-hash-object[1],
 -:  ----------- >  9:  30eff9170fb fsck: make fsck_config() re-usable
 -:  ----------- > 10:  11139ec2b8d mktag: allow turning off fsck.extraHeaderEntry
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 01/10] mktag doc: say <hash> not <sha1>
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
  2020-12-01 10:08             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 02/10] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
                               ` (8 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the "mktag" documentation to refer to the input hash as just
"hash", not "sha1". This command has supported SHA-256 for a while
now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index fa6a7561236..a158428eb9f 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -23,7 +23,7 @@ Tag Format
 A tag signature file, to be fed to this command's standard input,
 has a very simple fixed format: four lines of
 
-  object <sha1>
+  object <hash>
   type <typename>
   tag <tagname>
   tagger <tagger>
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 02/10] mktag: use default strbuf_read() hint
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (2 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 01/10] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 03/10] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
                               ` (7 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the hardcoded hint of 2^12 to 0. The default strbuf hint is
perfectly fine here, and the only reason we were hardcoding it is
because it survived migration from a pre-strbuf fixed-sized buffer.

See fd17f5b5f77 (Replace all read_fd use with strbuf_read, and get rid
of it., 2007-09-10) for that migration.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4982d3a93ef..ff7ac8e0e5d 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,7 +161,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 4096) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0) {
 		die_errno("could not read from stdin");
 	}
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 03/10] mktag: remove redundant braces in one-line body "if"
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (3 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 02/10] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 04/10] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
                               ` (6 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This minor stylistic churn is usually something we'd avoid, but if we
don't do this then the file after changes in subsequent commits will
only have this minor style inconsistency, so let's change this while
we're at it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index ff7ac8e0e5d..97ca5f28b1b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,9 +161,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 0) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
-	}
 
 	/* Verify it for some basic sanity: it needs to start with
 	   "object <sha1>\ntype\ntagger " */
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 04/10] mktag tests: don't needlessly use a subshell
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (4 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 03/10] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 05/10] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
                               ` (5 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The use of a subshell dates back to e9b20943b77 (t/t3800: do not use a
temporary file to hold expected result., 2008-01-04). It's not needed
anymore, if it ever was.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d696aa4e52e..0e411e3c45f 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,7 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		( test_must_fail git mktag <tag.sig 2>message ) &&
+		test_must_fail git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 05/10] mktag tests: remove needless SHA-1 hardcoding
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (5 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 04/10] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 06/10] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
                               ` (4 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the tests amended in acb49d1cc8b (t3800: make hash-size
independent, 2019-08-18) even more to make them independent of either
SHA-1 or SHA-256.

Some of these tests were failing for the wrong reasons. The first one
being modified here would fail because the line starts with "xxxxxx"
instead of "object", the rest of the line doesn't matter.

Let's just put a valid hash on the rest of the line anyway to narrow
the test down for just the s/object/xxxxxx/ case.

The second one being modified here would fail under
GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
invalid SHA-256, but we should really be testing <some sha-256 length
garbage> when under SHA-256.

This doesn't really matter since we should be able to trust other
parts of the code to validate things in the 0-9a-f range, but let's
keep it for good measure.

There's a later test which tests an invalid SHA which looks like a
valid one, to stress the "We refuse to tag something we can't
verify[...]" logic in mktag.c.

But here we're testing for a SHA-length string which contains
characters outside of the /[0-9a-f]/i set.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 0e411e3c45f..a22a0954d5e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -43,7 +43,7 @@ check_verify_failure 'Tag object length check' \
 #  2. object line label check
 
 cat >tag.sig <<EOF
-xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
+xxxxxx $head
 type tag
 tag mytag
 tagger . <> 0 +0000
@@ -53,10 +53,10 @@ EOF
 check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
 
 ############################################################
-#  3. object line SHA1 check
+#  3. object line hash check
 
 cat >tag.sig <<EOF
-object zz9e9b33986b1c2670fff52c5067603117b3e895
+object $(echo $head | tr 0-9a-f z)
 type tag
 tag mytag
 tagger . <> 0 +0000
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 06/10] mktag tests: improve verify_object() test coverage
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (6 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 05/10] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 07/10] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
                               ` (3 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The verify_object() function in "mktag.c" is tasked with ensuring that
our tag refers to a valid object.

The existing test for this might fail because it was also testing that
"type taggg" didn't refer to a valid object type (it should be "type
tag"), or because we referred to a valid object but got the type
wrong.

Let's split these tests up, so we're testing all combinations of a
non-existing object and in invalid/wrong "type" lines.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index a22a0954d5e..9ae1b0bb0af 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -125,19 +125,52 @@ check_verify_failure '"type" line type-name length check' \
 	'^error: char.*: type too long$'
 
 ############################################################
-#  9. verify object (SHA1/type) check
+#  9. verify object (hash/type) check
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
+type tag
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
+	'^error: char7: could not verify object.*$'
+
+cat >tag.sig <<EOF
+object $head
 type tagggg
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure 'verify object (SHA1/type) check' \
+check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
+	'^fatal: invalid object type'
+
+cat >tag.sig <<EOF
+object $(test_oid deadbeef)
+type tagggg
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
 	'^error: char7: could not verify object.*$'
 
+cat >tag.sig <<EOF
+object $head
+type tree
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
+	'^error: char7: could not verify object'
+
 ############################################################
 # 10. verify tag-name check
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 07/10] mktag: use fsck instead of custom verify_tag()
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (7 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 06/10] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 08/10] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
                               ` (2 subsequent siblings)
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the validation logic in "mktag" to use fsck's fsck_tag()
instead of its own custom parser. Curiously the logic for both dates
back to the same commit[1]. Let's unify them so we're not maintaining
two sets functions to verify that a tag is OK.

The behavior of fsck_tag() and the old "mktag" code being removed here
is different in few aspects.

I think it makes sense to remove some of those checks, namely:

 A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
    code disallowed values larger than 1400.

    Yes there's currently no timezone with a greater offset[2], but
    since we allow any number of non-offical timezones (e.g. +1234)
    passing this through seems fine. Git also won't break in the
    future if e.g. French Polynesia decides it needs to outdo the Line
    Islands when it comes to timezone extravagance.

 B. fsck allows missing author names such as "tagger <email>", mktag
    wouldn't, but would allow e.g. "tagger [2 spaces] <email>" (but
    not "tagger [1 space] <email>"). Now we allow all of these.

 C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
    allows it.

In some ways fsck_tag() is stricter than "mktag" was, namely:

 D. fsck disallows zero-padded dates, but mktag didn't care. So
    e.g. the timestamp "0000000000 +0000" produces an error now. A
    test in "t1006-cat-file.sh" relied on this, it's been changed to
    use "hash-object" (without fsck) instead.

There was one check I deemed worth keeping by porting it over to
fsck_tag():

 E. "mktag" did not allow any custom headers, and by extension (as an
    empty commit is allowed) also forbade an extra stray trailing
    newline after the headers it knew about.

    Add a new check in the "ignore" category to fsck and use it. This
    somewhat abuses the facility added in efaba7cc77f (fsck:
    optionally ignore specific fsck issues completely, 2015-06-22).

    This is somewhat of hack, but probably the least invasive change
    we can make here. The fsck command will shuffle these categories
    around, e.g. under --strict the "info" becomes a "warn" and "warn"
    becomes "error". Existing users of fsck's (and others,
    e.g. index-pack) --strict option rely on this.

    So we need to put something into a category that'll be ignored by
    all existing users of the API. Pretending that
    fsck.extraHeaderEntry=error ("ignore" by default) was set serves
    to do this for us.

1. ec4465adb38 (Add "tag" objects that can be used to sign other
   objects., 2005-04-25)

2. https://en.wikipedia.org/wiki/List_of_UTC_time_offsets

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c     | 196 +++++++++++---------------------------------
 fsck.c              |  32 +++++++-
 fsck.h              |   9 ++
 t/t1006-cat-file.sh |   2 +-
 t/t3800-mktag.sh    |  79 +++++++++++-------
 5 files changed, 137 insertions(+), 181 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 97ca5f28b1b..5765cde0032 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -2,160 +2,60 @@
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
+#include "fsck.h"
 
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
+static int mktag_fsck_error_func(struct fsck_options *o,
+				 const struct object_id *oid,
+				 enum object_type object_type,
+				 int msg_type, const char *message)
 {
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
-
-	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
-		free(buffer);
+	switch (msg_type) {
+	case FSCK_WARN:
+	case FSCK_ERROR:
+		/*
+		 * We treat both warnings and errors as errors, things
+		 * like missing "tagger" lines are "only" warnings
+		 * under fsck, we've always considered them an error.
+		 */
+		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
+		return 1;
+	default:
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		    msg_type);
 	}
-	return ret;
 }
 
-static int verify_tag(char *buffer, unsigned long size)
+static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 {
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
+	int ret;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+	const struct object_id *repl;
+
+	buffer = read_object_file(tagged_oid, &type, &size);
+	if (!buffer)
+		die("could not read tagged object '%s'\n",
+		    oid_to_hex(tagged_oid));
+	if (type != *tagged_type)
+		die("object '%s' tagged as '%s', but is a '%s' type\n",
+		    oid_to_hex(tagged_oid),
+		    type_name(*tagged_type), type_name(type));
+
+	repl = lookup_replace_object(the_repository, tagged_oid);
+	ret = check_object_signature(the_repository, repl,
+				     buffer, size, type_name(*tagged_type));
+	free(buffer);
 
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
+	return ret;
 }
 
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
+	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+	struct object_id tagged_oid;
+	int tagged_type;
 	struct object_id result;
 
 	if (argc != 1)
@@ -164,10 +64,14 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
+	fsck_options.error_func = mktag_fsck_error_func;
+	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
+	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
+				&tagged_oid, &tagged_type))
+		die("tag on stdin did not pass our strict fsck check");
+
+	if (verify_object_in_tag(&tagged_oid, &tagged_type))
+		die("tag on stdin did not refer to a valid object");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write tag file");
diff --git a/fsck.c b/fsck.c
index f82e2fe9e30..bed5e20e03b 100644
--- a/fsck.c
+++ b/fsck.c
@@ -80,7 +80,9 @@ static struct oidset gitmodules_done = OIDSET_INIT;
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
-	FUNC(MISSING_TAGGER_ENTRY, INFO)
+	FUNC(MISSING_TAGGER_ENTRY, INFO) \
+	/* ignored (elevated when requested) */ \
+	FUNC(EXTRA_HEADER_ENTRY, IGNORE)
 
 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
 enum fsck_msg_id {
@@ -911,6 +913,16 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		    unsigned long size, struct fsck_options *options)
 {
 	struct object_id tagged_oid;
+	int tagged_type;
+	return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
+				   &tagged_type);
+}
+
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tagged_type)
+{
 	int ret = 0;
 	char *eol;
 	struct strbuf sb = STRBUF_INIT;
@@ -924,7 +936,7 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
 		goto done;
 	}
-	if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
+	if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
 		if (ret)
 			goto done;
@@ -940,7 +952,8 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
 		goto done;
 	}
-	if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
+	*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
+	if (*tagged_type < 0)
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
 	if (ret)
 		goto done;
@@ -975,6 +988,19 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (!starts_with(buffer, "\n")) {
+		/*
+		 * The verify_headers() check will allow
+		 * e.g. "[...]tagger <tagger>\nsome
+		 * garbage\n\nmessage" to pass, thinking "some
+		 * garbage" could be a custom header. E.g. "mktag"
+		 * doesn't want any unknown headers.
+		 */
+		ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+		if (ret)
+			goto done;
+	}
+
 done:
 	strbuf_release(&sb);
 	return ret;
diff --git a/fsck.h b/fsck.h
index 69cf715e798..29ee4c45e87 100644
--- a/fsck.h
+++ b/fsck.h
@@ -62,6 +62,15 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
 int fsck_object(struct object *obj, void *data, unsigned long size,
 	struct fsck_options *options);
 
+/*
+ * fsck a tag, and pass info about it back to the caller. This is
+ * exposed fsck_object() internals for git-mktag(1).
+ */
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tag_type);
+
 /*
  * Some fsck checks are context-dependent, and may end up queued; run this
  * after completing all fsck_object() calls in order to resolve any remaining
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2f501d2dc94..5d2dc99b74a 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
 
 $tag_description"
 
-tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
 tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 9ae1b0bb0af..19b3c1bca9c 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -37,7 +37,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+	'^error:.* missingObject:'
 
 ############################################################
 #  2. object line label check
@@ -50,7 +50,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
+check_verify_failure '"object" line label check' '^error:.* missingObject:'
 
 ############################################################
 #  3. object line hash check
@@ -63,7 +63,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
 
 ############################################################
 #  4. type line label check
@@ -76,7 +76,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
 
 ############################################################
 #  5. type line eol check
@@ -84,7 +84,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
 
 ############################################################
 #  6. tag line label check #1
@@ -98,7 +98,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* missingTagEntry:'
 
 ############################################################
 #  7. tag line label check #2
@@ -110,7 +110,7 @@ tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* badType:'
 
 ############################################################
 #  8. type line type-name length check
@@ -122,7 +122,7 @@ tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char.*: type too long$'
+	'^error:.* badType:'
 
 ############################################################
 #  9. verify object (hash/type) check
@@ -136,7 +136,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
-	'^error: char7: could not verify object.*$'
+	'^fatal: could not read tagged object'
 
 cat >tag.sig <<EOF
 object $head
@@ -147,7 +147,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
-	'^fatal: invalid object type'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
@@ -158,7 +158,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object.*$'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $head
@@ -169,7 +169,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object'
+	'^fatal: object.*tagged as.*tree.*but is.*commit'
 
 ############################################################
 # 10. verify tag-name check
@@ -183,7 +183,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char.*: could not verify tag name$'
+	'^error:.* badTagName:'
 
 ############################################################
 # 11. tagger line label check #1
@@ -197,7 +197,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
 # 12. tagger line label check #2
@@ -212,10 +212,10 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
-# 13. disallow missing tag author name
+# 13. allow missing tag author name like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -226,8 +226,9 @@ tagger  <> 0 +0000
 This is filler
 EOF
 
-check_verify_failure 'disallow missing tag author name' \
-	'^error: char.*: missing tagger name$'
+test_expect_success 'allow missing tag author name' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -242,7 +243,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char.*: malformed tagger field$'
+	'^error:.* badEmail:'
 
 ############################################################
 # 15. allow empty tag email
@@ -260,7 +261,7 @@ test_expect_success \
     'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
-# 16. disallow spaces in tag email
+# 16. allow spaces in tag email like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -270,8 +271,9 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 
 EOF
 
-check_verify_failure 'disallow spaces in tag email' \
-	'^error: char.*: malformed tagger field$'
+test_expect_success 'allow spaces in tag email like fsck' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -285,7 +287,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -299,7 +301,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -313,7 +315,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char.*: malformed tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -327,7 +329,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -341,10 +343,10 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
-# 22. detect invalid tag timezone3
+# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
 
 cat >tag.sig <<EOF
 object $head
@@ -354,8 +356,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 
 EOF
 
-check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char.*: malformed tag timezone$'
+test_expect_success 'allow invalid tag timezone' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 23. detect invalid header entry
@@ -370,7 +373,21 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char.*: trailing garbage in tag header$'
+	'^error:.* extraHeaderEntry:'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+
+this line comes after an extra newline
+EOF
+
+test_expect_success \
+    'allow extra newlines at start of body' \
+    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
 # 24. create valid tag
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 08/10] mktag doc: update to explain why to use this
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (8 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 07/10] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 09/10] fsck: make fsck_config() re-usable Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 10/10] mktag: allow turning off fsck.extraHeaderEntry Ævar Arnfjörð Bjarmason
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the mktag documentation to compare itself to the similar
"hash-object -t tag" command. Before this someone reading the
documentation wouldn't have much of an idea what the difference
was.

Let's make it clear that it's to do with slightly different fsck
validation logic, and cross-link the "mktag" and "hash-object"
documentation to aid discover-ability.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-hash-object.txt |  4 ++++
 Documentation/git-mktag.txt       | 27 +++++++++++++++++++++++----
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index df9e2c58bdb..c535661ced8 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -58,6 +58,10 @@ OPTIONS
 	stress-testing Git itself or reproducing characteristics of corrupt or
 	bogus objects encountered in the wild.
 
+SEE ALSO
+--------
+linkgit:git-mktag[1]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index a158428eb9f..b164ab563bd 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -3,7 +3,7 @@ git-mktag(1)
 
 NAME
 ----
-git-mktag - Creates a tag object
+git-mktag - Creates a tag object with extra validation
 
 
 SYNOPSIS
@@ -13,10 +13,25 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Reads a tag contents on standard input and creates a tag object
-that can also be used to sign other objects.
 
-The output is the new tag's <object> identifier.
+Reads a tag contents on standard input and creates a tag object. The
+output is the new tag's <object> identifier.
+
+This command is mostly equivalent to linkgit:git-hash-object[1]
+invoked with `-t tag -w --stdin`. I.e. both of these will create and
+write a tag found in `my-tag`:
+
+    git mktag <my-tag
+    git hash-object -t tag -w --stdin <my-tag
+
+The difference is that mktag will die before writing the tag if the
+tag doesn't pass a linkgit:git-fsck[1] check.
+
+The "fsck" check done mktag is is stricter than what
+linkgit:git-fsck[1] would run by default in that all `fsck.<msg-id>`
+messages are promoted from warnings to errors (so e.g. a missing
+"tagger" line is an error). Extra headers in the object are also an
+error under mktag, but ignored by linkgit:git-fsck[1].
 
 Tag Format
 ----------
@@ -34,6 +49,10 @@ exists, is separated by a blank line from the header.  The
 message part may contain a signature that Git itself doesn't
 care about, but that can be verified with gpg.
 
+SEE ALSO
+--------
+linkgit:git-hash-object[1],
+
 GIT
 ---
 Part of the linkgit:git[1] suite
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 09/10] fsck: make fsck_config() re-usable
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (9 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 08/10] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  2020-12-09 20:01             ` [PATCH v3 10/10] mktag: allow turning off fsck.extraHeaderEntry Ævar Arnfjörð Bjarmason
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Move the fsck_config() function from builtin/fsck.c to fsck.[ch]. This
allows for re-using it in other tools that expose fsck logic and want
to support its configuration variables.

A logical continuation of this change would be to use a common
function for all of {fetch,receive}.fsck.* and fsck.*. See
5d477a334a6 (fsck (receive-pack): allow demoting errors to warnings,
2015-06-22) and my own 1362df0d413 (fetch: implement fetch.fsck.*,
2018-07-27) for the relevant code.

However, those routines want to not parse the fsck.skipList into OIDs,
but rather pass them along with the --strict option to another
process. It would be possible to refactor that whole thing so we
support e.g. a "fetch." prefix, then just keep track of the skiplist
as a filename instead of parsing it, and learn to spew that all out
from our internal structures into something we can append to the
--strict option.

But instead I'm planning to re-use this in "mktag", which'll just
re-use these "fsck.*" variables as-is.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/fsck.c | 20 +-------------------
 fsck.c         | 25 +++++++++++++++++++++++++
 fsck.h         |  7 +++++++
 3 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/builtin/fsck.c b/builtin/fsck.c
index fbf26cafcfd..821e7798c70 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -73,25 +73,7 @@ static const char *printable_type(const struct object_id *oid,
 
 static int fsck_config(const char *var, const char *value, void *cb)
 {
-	if (strcmp(var, "fsck.skiplist") == 0) {
-		const char *path;
-		struct strbuf sb = STRBUF_INIT;
-
-		if (git_config_pathname(&path, var, value))
-			return 1;
-		strbuf_addf(&sb, "skiplist=%s", path);
-		free((char *)path);
-		fsck_set_msg_types(&fsck_obj_options, sb.buf);
-		strbuf_release(&sb);
-		return 0;
-	}
-
-	if (skip_prefix(var, "fsck.", &var)) {
-		fsck_set_msg_type(&fsck_obj_options, var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
+	return fsck_config_internal(var, value, cb, &fsck_obj_options);
 }
 
 static int objerror(struct object *obj, const char *err)
diff --git a/fsck.c b/fsck.c
index bed5e20e03b..9067a290a2e 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1310,3 +1310,28 @@ int fsck_finish(struct fsck_options *options)
 	oidset_clear(&gitmodules_done);
 	return ret;
 }
+
+int fsck_config_internal(const char *var, const char *value, void *cb,
+			 struct fsck_options *options)
+{
+	if (strcmp(var, "fsck.skiplist") == 0) {
+		const char *path;
+		struct strbuf sb = STRBUF_INIT;
+
+		if (git_config_pathname(&path, var, value))
+			return 1;
+		strbuf_addf(&sb, "skiplist=%s", path);
+		free((char *)path);
+		fsck_set_msg_types(options, sb.buf);
+		strbuf_release(&sb);
+		return 0;
+	}
+
+	if (skip_prefix(var, "fsck.", &var)) {
+		fsck_set_msg_type(options, var, value);
+		return 0;
+	}
+
+	return git_default_config(var, value, cb);
+}
+
diff --git a/fsck.h b/fsck.h
index 29ee4c45e87..423c467feb7 100644
--- a/fsck.h
+++ b/fsck.h
@@ -103,4 +103,11 @@ void fsck_put_object_name(struct fsck_options *options,
 const char *fsck_describe_object(struct fsck_options *options,
 				 const struct object_id *oid);
 
+/*
+ * git_config() callback for use by fsck-y tools that want to support
+ * fsck.<msg> fsck.skipList etc.
+ */
+int fsck_config_internal(const char *var, const char *value, void *cb,
+			 struct fsck_options *options);
+
 #endif
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v3 10/10] mktag: allow turning off fsck.extraHeaderEntry
  2020-11-26 22:22           ` [PATCH v2 00/10] " Ævar Arnfjörð Bjarmason
                               ` (10 preceding siblings ...)
  2020-12-09 20:01             ` [PATCH v3 09/10] fsck: make fsck_config() re-usable Ævar Arnfjörð Bjarmason
@ 2020-12-09 20:01             ` Ævar Arnfjörð Bjarmason
  11 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-09 20:01 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

In earlier commits mktag learned to use the fsck machinery, at which
point we needed to add fsck.extraHeaderEntry so it could be as strict
about extra headers as it's been ever since it was implemented.

But it's not nice to need to switch away from "mktag" to "hash-object"
+ manual "fsck" just because you'd like to have an extra header. So
let's support turning it off by getting "fsck.*" variables from the
config.

Pedantically speaking it's still not possible to make "mktag" behave
just like "hash-object -t tag" does, since we're unconditionally going
to check the referenced object in verify_object_in_tag(), which is our
own check, and not one that exists in fsck.c.

But the spirit of "this works like fsck" is preserved, in that if you
created such a tag with "hash-object" and did a full "fsck" on the
repository it would also error out about that invalid object, it just
wouldn't emit the same message as fsck does.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt |  9 +++++++--
 builtin/mktag.c             | 11 ++++++++++-
 t/t3800-mktag.sh            | 14 ++++++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index b164ab563bd..e1506dde561 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -30,8 +30,13 @@ tag doesn't pass a linkgit:git-fsck[1] check.
 The "fsck" check done mktag is is stricter than what
 linkgit:git-fsck[1] would run by default in that all `fsck.<msg-id>`
 messages are promoted from warnings to errors (so e.g. a missing
-"tagger" line is an error). Extra headers in the object are also an
-error under mktag, but ignored by linkgit:git-fsck[1].
+"tagger" line is an error).
+
+Extra headers in the object are also an error under mktag, but ignored
+by linkgit:git-fsck[1]. This extra check can be turned off by setting
+the appropriate `fsck.<msg-id>` varible:
+
+    git -c fsck.extraHeaderEntry=ignore mktag <my-tag-with-headers
 
 Tag Format
 ----------
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 5765cde0032..c1398ccf133 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -3,6 +3,14 @@
 #include "replace-object.h"
 #include "object-store.h"
 #include "fsck.h"
+#include "config.h"
+
+static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+
+static int mktag_config(const char *var, const char *value, void *cb)
+{
+	return fsck_config_internal(var, value, cb, &fsck_options);
+}
 
 static int mktag_fsck_error_func(struct fsck_options *o,
 				 const struct object_id *oid,
@@ -53,7 +61,6 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
-	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
 	struct object_id tagged_oid;
 	int tagged_type;
 	struct object_id result;
@@ -66,6 +73,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 
 	fsck_options.error_func = mktag_fsck_error_func;
 	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
+	/* config might set fsck.extraHeaderEntry=* again */
+	git_config(mktag_config, NULL);
 	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
 				&tagged_oid, &tagged_type))
 		die("tag on stdin did not pass our strict fsck check");
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 19b3c1bca9c..59082e06277 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -375,6 +375,20 @@ EOF
 check_verify_failure 'detect invalid header entry' \
 	'^error:.* extraHeaderEntry:'
 
+test_expect_success 'invalid header entry config & fsck' '
+	test_must_fail git mktag <tag.sig &&
+	test_must_fail git -c fsck.extraHeaderEntry=error mktag <tag.sig &&
+	test_must_fail git -c fsck.extraHeaderEntry=warn mktag <tag.sig &&
+	git -c fsck.extraHeaderEntry=ignore mktag <tag.sig &&
+	git fsck &&
+	env GIT_TEST_GETTEXT_POISON=false \
+		git -c fsck.extraHeaderEntry=warn fsck 2>err &&
+	grep "warning .*extraHeaderEntry:" err &&
+	test_must_fail env GIT_TEST_GETTEXT_POISON=false \
+		git -c fsck.extraHeaderEntry=error 2>err fsck &&
+	grep "error .* extraHeaderEntry:" err
+'
+
 cat >tag.sig <<EOF
 object $head
 type commit
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v3 00/10] make "mktag" use fsck_tag()
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
@ 2020-12-09 22:30               ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                 ` (20 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-09 22:30 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> This version should address all the comments Junio made on v2. Changes:
>
>  * The whole "extra" fsck option is gone, I just didn't realize I
>    could set the new check to "ignore", and then manually promote it.
>
>  * Ejected "mktag: reword write_object_file() error". It was the same
>    phrasing as "git tag" uses, let's just keep it.
>
>  * Clarifications in docs/commit messages
>
>  * There's 2 extra patches at the end now which take the first steps
>    into making "git mktag" more of a normal builtin. It reads fsck.*
>    config variables, so you can turn off that "no extra headers" check
>    through the normal fsck.<msg-id>=ignore config.
>
>    It should also be moved to getopts, and we could make it support
>    --no-strict to have the same idea of error/warning as fsck itself,
>    but that's #leftoverbits, along with moving it to i18n.
>
>    It would be nice to have patches 1-8 merged down if they're deemed
>    ready, and if 9-10 aren't deemed wanted just discard them. I think
>    it makes sense though...

Thanks.  I haven't read the individual patches, but spotted an
obvious "is is" typo in the doc while scanning through the end
result of applying all of them.

 Documentation/git-mktag.txt | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git c/Documentation/git-mktag.txt w/Documentation/git-mktag.txt
index e1506dde56..2c1afedef6 100644
--- c/Documentation/git-mktag.txt
+++ w/Documentation/git-mktag.txt
@@ -27,10 +27,9 @@ write a tag found in `my-tag`:
 The difference is that mktag will die before writing the tag if the
 tag doesn't pass a linkgit:git-fsck[1] check.
 
-The "fsck" check done mktag is is stricter than what
-linkgit:git-fsck[1] would run by default in that all `fsck.<msg-id>`
-messages are promoted from warnings to errors (so e.g. a missing
-"tagger" line is an error).
+The "fsck" check done mktag is stricter than what linkgit:git-fsck[1]
+would run by default in that all `fsck.<msg-id>` messages are promoted
+from warnings to errors (so e.g. a missing "tagger" line is an error).
 
 Extra headers in the object are also an error under mktag, but ignored
 by linkgit:git-fsck[1]. This extra check can be turned off by setting

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 00/20] make "mktag" use fsck_tag() & more
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
  2020-12-09 22:30               ` Junio C Hamano
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23 13:54                 ` Junio C Hamano
                                   ` (24 more replies)
  2020-12-23  1:35               ` [PATCH v4 01/20] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
                                 ` (19 subsequent siblings)
  21 siblings, 25 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

So, when re-rolling this with Junio's small fixup this grew in scope a
bit, but should paradoxically be easier to deal with even though it's
2x the size now. Read on:

Ævar Arnfjörð Bjarmason (20):
  mktag doc: say <hash> not <sha1>
  mktag doc: grammar fix, when exists -> when it exists
  mktag doc: update to explain why to use this
  mktag tests: don't needlessly use a subshell
  mktag tests: remove needless SHA-1 hardcoding
  mktag tests: improve verify_object() test coverage
  mktag tests: don't pipe to stderr needlessly
  mktag tests: don't create "mytag" twice
  mktag tests: stress test whitespace handling
  mktag tests: test "hash-object" compatibility

I re-arranged this series so the doc/test patches for existing
behavior all come first now. There's some new patches there (see
range-diff), but all rather easy-to review fixes or tests for existing
behavior.

  mktag: use default strbuf_read() hint
  mktag: remove redundant braces in one-line body "if"
  mktag: use puts(str) instead of printf("%s\n", str)

Trivial coding style changes, the puts() patch is new.

  mktag: use fsck instead of custom verify_tag()

Still the real meat of the series, unchanged in any meaningful way,
except in (as seen in the range-diff) carrying forward doc/test
changes made earlier.

  fsck: make fsck_config() re-usable
  mktag: allow turning off fsck.extraHeaderEntry

ditto unchanged.

  mktag: allow omitting the header/body \n separator

I discovered a regression in mktag in git since 2008 where it refuses
to accept input without an empty newline separating the body & message
in cases where there's no message.

Now we again accept the same input as hash-object, and with the new
"hash-object" test integration earlier in the series we're confident
that mktag & hash-object do the same thing in all these cases.

  mktag: convert to parse-options
  mktag: mark strings for translation
  mktag: add a --no-strict option

The #leftoverbits I suggested in v3 of converting to parse-options &
doing i18n for mktag, and finally supporting --no-strict so you can
make it behave like "fsck" does in its default mode.

 Documentation/git-hash-object.txt |   4 +
 Documentation/git-mktag.txt       |  42 +++++-
 builtin/fsck.c                    |  20 +--
 builtin/mktag.c                   | 235 +++++++++++-------------------
 fsck.c                            |  59 +++++++-
 fsck.h                            |  16 ++
 parse-options.h                   |   1 +
 t/t1006-cat-file.sh               |   2 +-
 t/t3800-mktag.sh                  | 211 +++++++++++++++++++++------
 9 files changed, 361 insertions(+), 229 deletions(-)

Range-diff:
 1:  aee3f52a47 =  1:  a31c305cfc mktag doc: say <hash> not <sha1>
 -:  ---------- >  2:  81cb4cba5c mktag doc: grammar fix, when exists -> when it exists
 8:  fa04664f7f !  3:  b4bc6f894c mktag doc: update to explain why to use this
    @@ Commit message
         documentation wouldn't have much of an idea what the difference
         was.
     
    -    Let's make it clear that it's to do with slightly different fsck
    -    validation logic, and cross-link the "mktag" and "hash-object"
    -    documentation to aid discover-ability.
    +    Let's allude to our own validation logic, and cross-link the "mktag"
    +    and "hash-object" documentation to aid discover-ability. A follow-up
    +    change to migrate "mktag" to use "fsck" validation will make the part
    +    about validation logic clearer.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ Documentation/git-mktag.txt: SYNOPSIS
     +    git hash-object -t tag -w --stdin <my-tag
     +
     +The difference is that mktag will die before writing the tag if the
    -+tag doesn't pass a linkgit:git-fsck[1] check.
    -+
    -+The "fsck" check done mktag is is stricter than what
    -+linkgit:git-fsck[1] would run by default in that all `fsck.<msg-id>`
    -+messages are promoted from warnings to errors (so e.g. a missing
    -+"tagger" line is an error). Extra headers in the object are also an
    -+error under mktag, but ignored by linkgit:git-fsck[1].
    ++tag doesn't pass a sanity check.
      
      Tag Format
      ----------
 4:  1f06b9c0cf =  4:  acb94e0289 mktag tests: don't needlessly use a subshell
 5:  5d1cb73ca3 =  5:  4ae76ec5e3 mktag tests: remove needless SHA-1 hardcoding
 6:  cf86f4ca37 =  6:  9effb4532b mktag tests: improve verify_object() test coverage
 -:  ---------- >  7:  b81d31a917 mktag tests: don't pipe to stderr needlessly
 -:  ---------- >  8:  11f59718b4 mktag tests: don't create "mytag" twice
 -:  ---------- >  9:  dd6b012b0c mktag tests: stress test whitespace handling
 -:  ---------- > 10:  56c6b562fd mktag tests: test "hash-object" compatibility
 2:  6e98557709 = 11:  1e2e4ec269 mktag: use default strbuf_read() hint
 3:  8e5fe08f15 = 12:  be2ab3edab mktag: remove redundant braces in one-line body "if"
 -:  ---------- > 13:  d8514df970 mktag: use puts(str) instead of printf("%s\n", str)
 7:  5812ee53c9 ! 14:  346d73cc97 mktag: use fsck instead of custom verify_tag()
    @@ Commit message
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    + ## Documentation/git-mktag.txt ##
    +@@ Documentation/git-mktag.txt: write a tag found in `my-tag`:
    +     git hash-object -t tag -w --stdin <my-tag
    + 
    + The difference is that mktag will die before writing the tag if the
    +-tag doesn't pass a sanity check.
    ++tag doesn't pass a linkgit:git-fsck[1] check.
    ++
    ++The "fsck" check done mktag is stricter than what linkgit:git-fsck[1]
    ++would run by default in that all `fsck.<msg-id>` messages are promoted
    ++from warnings to errors (so e.g. a missing "tagger" line is an error).
    ++
    ++Extra headers in the object are also an error under mktag, but ignored
    ++by linkgit:git-fsck[1]
    + 
    + Tag Format
    + ----------
    +
      ## builtin/mktag.c ##
     @@
      #include "tag.h"
    @@ builtin/mktag.c
     +
     +	buffer = read_object_file(tagged_oid, &type, &size);
     +	if (!buffer)
    -+		die("could not read tagged object '%s'\n",
    ++		die("could not read tagged object '%s'",
     +		    oid_to_hex(tagged_oid));
     +	if (type != *tagged_type)
    -+		die("object '%s' tagged as '%s', but is a '%s' type\n",
    ++		die("object '%s' tagged as '%s', but is a '%s' type",
     +		    oid_to_hex(tagged_oid),
     +		    type_name(*tagged_type), type_name(type));
     +
    @@ t/t3800-mktag.sh: tagger  <> 0 +0000
      
     -check_verify_failure 'disallow missing tag author name' \
     -	'^error: char.*: missing tagger name$'
    -+test_expect_success 'allow missing tag author name' '
    -+	git mktag <tag.sig
    -+'
    ++test_expect_mktag_success 'allow missing tag author name'
      
      ############################################################
      # 14. disallow missing tag author name
    @@ t/t3800-mktag.sh: tagger T A Gger <
      
      ############################################################
      # 15. allow empty tag email
    -@@ t/t3800-mktag.sh: test_expect_success \
    -     'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
    +@@ t/t3800-mktag.sh: EOF
    + test_expect_mktag_success 'allow empty tag email'
      
      ############################################################
     -# 16. disallow spaces in tag email
    @@ t/t3800-mktag.sh: tagger T A Gger <tag ger@example.com> 0 +0000
      
     -check_verify_failure 'disallow spaces in tag email' \
     -	'^error: char.*: malformed tagger field$'
    -+test_expect_success 'allow spaces in tag email like fsck' '
    -+	git mktag <tag.sig
    -+'
    ++test_expect_mktag_success 'allow spaces in tag email like fsck'
      
      ############################################################
      # 17. disallow missing tag timestamp
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -1430
      
     -check_verify_failure 'detect invalid tag timezone3' \
     -	'^error: char.*: malformed tag timezone$'
    -+test_expect_success 'allow invalid tag timezone' '
    -+	git mktag <tag.sig
    -+'
    ++test_expect_mktag_success 'allow invalid tag timezone'
      
      ############################################################
      # 23. detect invalid header entry
    @@ t/t3800-mktag.sh: this line should not be here
      check_verify_failure 'detect invalid header entry' \
     -	'^error: char.*: trailing garbage in tag header$'
     +	'^error:.* extraHeaderEntry:'
    -+
    -+cat >tag.sig <<EOF
    -+object $head
    -+type commit
    -+tag mytag
    -+tagger T A Gger <tagger@example.com> 1206478233 -0500
    -+
    -+
    -+this line comes after an extra newline
    -+EOF
    -+
    -+test_expect_success \
    -+    'allow extra newlines at start of body' \
    -+    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
    + 
    + cat >tag.sig <<EOF
    + object $head
    +@@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500$space
    + EOF
    + 
    + check_verify_failure 'extra whitespace at end of headers' \
    +-	'^error: char.*: malformed tag timezone$'
    ++	'^error:.* badTimezone:'
    + 
    + cat >tag.sig <<EOF
    + object $head
    +@@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500
    + EOF
    + 
    + check_verify_failure 'disallow no header / body newline separator' \
    +-	'^error: char.*: trailing garbage in tag header$'
    ++	'^error:.* extraHeaderEntry:'
      
      ############################################################
      # 24. create valid tag
 9:  30eff9170f = 15:  0e7994d8fc fsck: make fsck_config() re-usable
10:  11139ec2b8 ! 16:  5e8046022b mktag: allow turning off fsck.extraHeaderEntry
    @@ Commit message
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Documentation/git-mktag.txt ##
    -@@ Documentation/git-mktag.txt: tag doesn't pass a linkgit:git-fsck[1] check.
    - The "fsck" check done mktag is is stricter than what
    - linkgit:git-fsck[1] would run by default in that all `fsck.<msg-id>`
    - messages are promoted from warnings to errors (so e.g. a missing
    --"tagger" line is an error). Extra headers in the object are also an
    --error under mktag, but ignored by linkgit:git-fsck[1].
    -+"tagger" line is an error).
    -+
    -+Extra headers in the object are also an error under mktag, but ignored
    +@@ Documentation/git-mktag.txt: would run by default in that all `fsck.<msg-id>` messages are promoted
    + from warnings to errors (so e.g. a missing "tagger" line is an error).
    + 
    + Extra headers in the object are also an error under mktag, but ignored
    +-by linkgit:git-fsck[1]
     +by linkgit:git-fsck[1]. This extra check can be turned off by setting
     +the appropriate `fsck.<msg-id>` varible:
     +
 -:  ---------- > 17:  32698e1d00 mktag: allow omitting the header/body \n separator
 -:  ---------- > 18:  b6a22f2f99 mktag: convert to parse-options
 -:  ---------- > 19:  7fc0b81df7 mktag: mark strings for translation
 -:  ---------- > 20:  6fa443d528 mktag: add a --no-strict option
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 01/20] mktag doc: say <hash> not <sha1>
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
  2020-12-09 22:30               ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 02/20] mktag doc: grammar fix, when exists -> when it exists Ævar Arnfjörð Bjarmason
                                 ` (18 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the "mktag" documentation to refer to the input hash as just
"hash", not "sha1". This command has supported SHA-256 for a while
now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index fa6a756123..a158428eb9 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -23,7 +23,7 @@ Tag Format
 A tag signature file, to be fed to this command's standard input,
 has a very simple fixed format: four lines of
 
-  object <sha1>
+  object <hash>
   type <typename>
   tag <tagname>
   tagger <tagger>
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 02/20] mktag doc: grammar fix, when exists -> when it exists
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (2 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 01/20] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 03/20] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
                                 ` (17 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Amend the wording of documentation added in 6cfec03680 (mktag:
minimally update the description., 2007-06-10). It makes more sense to
say "when it exists" here, as we're referring to "the message".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index a158428eb9..1b0667e372 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -29,7 +29,7 @@ has a very simple fixed format: four lines of
   tagger <tagger>
 
 followed by some 'optional' free-form message (some tags created
-by older Git may not have `tagger` line).  The message, when
+by older Git may not have `tagger` line).  The message, when it
 exists, is separated by a blank line from the header.  The
 message part may contain a signature that Git itself doesn't
 care about, but that can be verified with gpg.
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 03/20] mktag doc: update to explain why to use this
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (3 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 02/20] mktag doc: grammar fix, when exists -> when it exists Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:57                 ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 04/20] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
                                 ` (16 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the mktag documentation to compare itself to the similar
"hash-object -t tag" command. Before this someone reading the
documentation wouldn't have much of an idea what the difference
was.

Let's allude to our own validation logic, and cross-link the "mktag"
and "hash-object" documentation to aid discover-ability. A follow-up
change to migrate "mktag" to use "fsck" validation will make the part
about validation logic clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-hash-object.txt |  4 ++++
 Documentation/git-mktag.txt       | 21 +++++++++++++++++----
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index df9e2c58bd..c535661ced 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -58,6 +58,10 @@ OPTIONS
 	stress-testing Git itself or reproducing characteristics of corrupt or
 	bogus objects encountered in the wild.
 
+SEE ALSO
+--------
+linkgit:git-mktag[1]
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 1b0667e372..adc63f6d4e 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -3,7 +3,7 @@ git-mktag(1)
 
 NAME
 ----
-git-mktag - Creates a tag object
+git-mktag - Creates a tag object with extra validation
 
 
 SYNOPSIS
@@ -13,10 +13,19 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Reads a tag contents on standard input and creates a tag object
-that can also be used to sign other objects.
 
-The output is the new tag's <object> identifier.
+Reads a tag contents on standard input and creates a tag object. The
+output is the new tag's <object> identifier.
+
+This command is mostly equivalent to linkgit:git-hash-object[1]
+invoked with `-t tag -w --stdin`. I.e. both of these will create and
+write a tag found in `my-tag`:
+
+    git mktag <my-tag
+    git hash-object -t tag -w --stdin <my-tag
+
+The difference is that mktag will die before writing the tag if the
+tag doesn't pass a sanity check.
 
 Tag Format
 ----------
@@ -34,6 +43,10 @@ exists, is separated by a blank line from the header.  The
 message part may contain a signature that Git itself doesn't
 care about, but that can be verified with gpg.
 
+SEE ALSO
+--------
+linkgit:git-hash-object[1],
+
 GIT
 ---
 Part of the linkgit:git[1] suite
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 04/20] mktag tests: don't needlessly use a subshell
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (4 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 03/20] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 05/20] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
                                 ` (15 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The use of a subshell dates back to e9b20943b77 (t/t3800: do not use a
temporary file to hold expected result., 2008-01-04). It's not needed
anymore, if it ever was.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d696aa4e52..0e411e3c45 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,7 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		( test_must_fail git mktag <tag.sig 2>message ) &&
+		test_must_fail git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 05/20] mktag tests: remove needless SHA-1 hardcoding
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (5 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 04/20] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 06/20] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
                                 ` (14 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the tests amended in acb49d1cc8b (t3800: make hash-size
independent, 2019-08-18) even more to make them independent of either
SHA-1 or SHA-256.

Some of these tests were failing for the wrong reasons. The first one
being modified here would fail because the line starts with "xxxxxx"
instead of "object", the rest of the line doesn't matter.

Let's just put a valid hash on the rest of the line anyway to narrow
the test down for just the s/object/xxxxxx/ case.

The second one being modified here would fail under
GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
invalid SHA-256, but we should really be testing <some sha-256 length
garbage> when under SHA-256.

This doesn't really matter since we should be able to trust other
parts of the code to validate things in the 0-9a-f range, but let's
keep it for good measure.

There's a later test which tests an invalid SHA which looks like a
valid one, to stress the "We refuse to tag something we can't
verify[...]" logic in mktag.c.

But here we're testing for a SHA-length string which contains
characters outside of the /[0-9a-f]/i set.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 0e411e3c45..a22a0954d5 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -43,7 +43,7 @@ check_verify_failure 'Tag object length check' \
 #  2. object line label check
 
 cat >tag.sig <<EOF
-xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
+xxxxxx $head
 type tag
 tag mytag
 tagger . <> 0 +0000
@@ -53,10 +53,10 @@ EOF
 check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
 
 ############################################################
-#  3. object line SHA1 check
+#  3. object line hash check
 
 cat >tag.sig <<EOF
-object zz9e9b33986b1c2670fff52c5067603117b3e895
+object $(echo $head | tr 0-9a-f z)
 type tag
 tag mytag
 tagger . <> 0 +0000
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 06/20] mktag tests: improve verify_object() test coverage
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (6 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 05/20] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  2:04                 ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 07/20] mktag tests: don't pipe to stderr needlessly Ævar Arnfjörð Bjarmason
                                 ` (13 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

The verify_object() function in "mktag.c" is tasked with ensuring that
our tag refers to a valid object.

The existing test for this might fail because it was also testing that
"type taggg" didn't refer to a valid object type (it should be "type
tag"), or because we referred to a valid object but got the type
wrong.

Let's split these tests up, so we're testing all combinations of a
non-existing object and in invalid/wrong "type" lines.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index a22a0954d5..9ae1b0bb0a 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -125,19 +125,52 @@ check_verify_failure '"type" line type-name length check' \
 	'^error: char.*: type too long$'
 
 ############################################################
-#  9. verify object (SHA1/type) check
+#  9. verify object (hash/type) check
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
+type tag
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
+	'^error: char7: could not verify object.*$'
+
+cat >tag.sig <<EOF
+object $head
 type tagggg
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure 'verify object (SHA1/type) check' \
+check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
+	'^fatal: invalid object type'
+
+cat >tag.sig <<EOF
+object $(test_oid deadbeef)
+type tagggg
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
 	'^error: char7: could not verify object.*$'
 
+cat >tag.sig <<EOF
+object $head
+type tree
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
+	'^error: char7: could not verify object'
+
 ############################################################
 # 10. verify tag-name check
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 07/20] mktag tests: don't pipe to stderr needlessly
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (7 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 06/20] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  2:10                 ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 08/20] mktag tests: don't create "mytag" twice Ævar Arnfjörð Bjarmason
                                 ` (12 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Remove the piping of stderr to "message" in the valid tag test. This
pattern seems to have been copy/pasted from the failure case in
446c6faec6 (New tests and en-passant modifications to mktag.,
2006-07-29).

Nothing is piped to "message" here, and in the event of the test
failing it only serves to hide the error.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 9ae1b0bb0a..bbd148618e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -257,7 +257,7 @@ EOF
 
 test_expect_success \
     'allow empty tag email' \
-    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
+    'git mktag <tag.sig >.git/refs/tags/mytag'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -385,7 +385,7 @@ EOF
 
 test_expect_success \
     'create valid tag' \
-    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
+    'git mktag <tag.sig >.git/refs/tags/mytag'
 
 ############################################################
 # 25. check mytag
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 08/20] mktag tests: don't create "mytag" twice
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (8 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 07/20] mktag tests: don't pipe to stderr needlessly Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  2:18                 ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 09/20] mktag tests: stress test whitespace handling Ævar Arnfjörð Bjarmason
                                 ` (11 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change a test added in e0aaf781f6 (mktag.c: improve verification of
tagger field and tests, 2008-03-27) to not create "mytag", which
should only be created and verified at the end in an earlier test
added in 446c6faec6 (New tests and en-passant modifications to mktag.,
2006-07-29).

While we're at it let's prevent a similar logic error from creeping
into the test by asserting that "mytag" doesn't exist before we create
it. Let's do this by moving the test to use "update-ref", instead of
our own homebrew ad-hoc refstore update.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index bbd148618e..b6dcdbebe6 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -257,7 +257,7 @@ EOF
 
 test_expect_success \
     'allow empty tag email' \
-    'git mktag <tag.sig >.git/refs/tags/mytag'
+    'git mktag <tag.sig'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -383,16 +383,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 
 EOF
 
-test_expect_success \
-    'create valid tag' \
-    'git mktag <tag.sig >.git/refs/tags/mytag'
-
-############################################################
-# 25. check mytag
-
-test_expect_success \
-    'check mytag' \
-    'git tag -l | grep mytag'
-
+test_expect_success 'create valid tag' '
+	git mktag <tag.sig >hash &&
+	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero)
+'
 
 test_done
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 09/20] mktag tests: stress test whitespace handling
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (9 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 08/20] mktag tests: don't create "mytag" twice Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  2:27                 ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 10/20] mktag tests: test "hash-object" compatibility Ævar Arnfjörð Bjarmason
                                 ` (10 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Add tests for various whitespace edge cases around the header/body
boundary, such as two newlines separating the header and body, a space
at the end of the "tagger" line before the header etc.

Add a test showing that we insist that an empty body must be preceded
by an empty line. This test for a long-standing regression which goes
against the command's documented behavior. It'll be addressed in a
follow-up change.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index b6dcdbebe6..f339321be8 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -372,6 +372,54 @@ EOF
 check_verify_failure 'detect invalid header entry' \
 	'^error: char.*: trailing garbage in tag header$'
 
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+
+this line comes after an extra newline
+EOF
+
+test_expect_success 'allow extra newlines at start of body' '
+	git mktag <tag.sig
+'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+EOF
+
+test_expect_success 'allow extra newlines at end of headers' '
+	git mktag <tag.sig
+'
+
+space=' '
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500$space
+
+EOF
+
+check_verify_failure 'extra whitespace at end of headers' \
+	'^error: char.*: malformed tag timezone$'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+EOF
+
+check_verify_failure 'disallow no header / body newline separator' \
+	'^error: char.*: trailing garbage in tag header$'
+
 ############################################################
 # 24. create valid tag
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 10/20] mktag tests: test "hash-object" compatibility
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (10 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 09/20] mktag tests: stress test whitespace handling Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  2:29                 ` Junio C Hamano
  2020-12-23  1:35               ` [PATCH v4 11/20] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
                                 ` (9 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change all the successful "mktag" tests to test that "hash-object"
produces the same hash for the input, and that fsck passes for
both.

This tests e.g. that "mktag" doesn't trim its input or otherwise munge
it in a way that "hash-object" doesn't.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index f339321be8..c6826762d9 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -19,6 +19,16 @@ check_verify_failure () {
 	'
 }
 
+test_expect_mktag_success() {
+	test_expect_success "$1" '
+		git hash-object -t tag -w --stdin <tag.sig >expected &&
+		git fsck --strict &&
+		git mktag <tag.sig >hash &&
+		git fsck --strict &&
+		test_cmp expected hash
+	'
+}
+
 ###########################################################
 # first create a commit, so we have a valid object/type
 # for the tag.
@@ -255,9 +265,7 @@ tagger T A Gger <> 0 +0000
 
 EOF
 
-test_expect_success \
-    'allow empty tag email' \
-    'git mktag <tag.sig'
+test_expect_mktag_success 'allow empty tag email'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -382,9 +390,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 this line comes after an extra newline
 EOF
 
-test_expect_success 'allow extra newlines at start of body' '
-	git mktag <tag.sig
-'
+test_expect_mktag_success 'allow extra newlines at start of body'
 
 cat >tag.sig <<EOF
 object $head
@@ -394,9 +400,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 
 EOF
 
-test_expect_success 'allow extra newlines at end of headers' '
-	git mktag <tag.sig
-'
+test_expect_mktag_success 'allow extra newlines at end of headers'
 
 space=' '
 cat >tag.sig <<EOF
@@ -431,8 +435,8 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 
 EOF
 
-test_expect_success 'create valid tag' '
-	git mktag <tag.sig >hash &&
+test_expect_mktag_success 'create valid tag object'
+test_expect_success 'create valid tag name' '
 	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero)
 '
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 11/20] mktag: use default strbuf_read() hint
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (11 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 10/20] mktag tests: test "hash-object" compatibility Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 12/20] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
                                 ` (8 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the hardcoded hint of 2^12 to 0. The default strbuf hint is
perfectly fine here, and the only reason we were hardcoding it is
because it survived migration from a pre-strbuf fixed-sized buffer.

See fd17f5b5f77 (Replace all read_fd use with strbuf_read, and get rid
of it., 2007-09-10) for that migration.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4982d3a93e..ff7ac8e0e5 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,7 +161,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 4096) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0) {
 		die_errno("could not read from stdin");
 	}
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 12/20] mktag: remove redundant braces in one-line body "if"
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (12 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 11/20] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 13/20] mktag: use puts(str) instead of printf("%s\n", str) Ævar Arnfjörð Bjarmason
                                 ` (7 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This minor stylistic churn is usually something we'd avoid, but if we
don't do this then the file after changes in subsequent commits will
only have this minor style inconsistency, so let's change this while
we're at it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index ff7ac8e0e5..97ca5f28b1 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,9 +161,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 0) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
-	}
 
 	/* Verify it for some basic sanity: it needs to start with
 	   "object <sha1>\ntype\ntagger " */
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 13/20] mktag: use puts(str) instead of printf("%s\n", str)
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (13 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 12/20] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:35               ` [PATCH v4 14/20] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
                                 ` (6 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

This introduces no functional change, but refactors the print-out of
the hash at the end to do the same thing with less code.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 97ca5f28b1..d89a3c201d 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -173,6 +173,6 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 		die("unable to write tag file");
 
 	strbuf_release(&buf);
-	printf("%s\n", oid_to_hex(&result));
+	puts(oid_to_hex(&result));
 	return 0;
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 14/20] mktag: use fsck instead of custom verify_tag()
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (14 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 13/20] mktag: use puts(str) instead of printf("%s\n", str) Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:35               ` Ævar Arnfjörð Bjarmason
  2020-12-23 13:34                 ` Junio C Hamano
  2020-12-23  1:36               ` [PATCH v4 15/20] fsck: make fsck_config() re-usable Ævar Arnfjörð Bjarmason
                                 ` (5 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:35 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change the validation logic in "mktag" to use fsck's fsck_tag()
instead of its own custom parser. Curiously the logic for both dates
back to the same commit[1]. Let's unify them so we're not maintaining
two sets functions to verify that a tag is OK.

The behavior of fsck_tag() and the old "mktag" code being removed here
is different in few aspects.

I think it makes sense to remove some of those checks, namely:

 A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
    code disallowed values larger than 1400.

    Yes there's currently no timezone with a greater offset[2], but
    since we allow any number of non-offical timezones (e.g. +1234)
    passing this through seems fine. Git also won't break in the
    future if e.g. French Polynesia decides it needs to outdo the Line
    Islands when it comes to timezone extravagance.

 B. fsck allows missing author names such as "tagger <email>", mktag
    wouldn't, but would allow e.g. "tagger [2 spaces] <email>" (but
    not "tagger [1 space] <email>"). Now we allow all of these.

 C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
    allows it.

In some ways fsck_tag() is stricter than "mktag" was, namely:

 D. fsck disallows zero-padded dates, but mktag didn't care. So
    e.g. the timestamp "0000000000 +0000" produces an error now. A
    test in "t1006-cat-file.sh" relied on this, it's been changed to
    use "hash-object" (without fsck) instead.

There was one check I deemed worth keeping by porting it over to
fsck_tag():

 E. "mktag" did not allow any custom headers, and by extension (as an
    empty commit is allowed) also forbade an extra stray trailing
    newline after the headers it knew about.

    Add a new check in the "ignore" category to fsck and use it. This
    somewhat abuses the facility added in efaba7cc77f (fsck:
    optionally ignore specific fsck issues completely, 2015-06-22).

    This is somewhat of hack, but probably the least invasive change
    we can make here. The fsck command will shuffle these categories
    around, e.g. under --strict the "info" becomes a "warn" and "warn"
    becomes "error". Existing users of fsck's (and others,
    e.g. index-pack) --strict option rely on this.

    So we need to put something into a category that'll be ignored by
    all existing users of the API. Pretending that
    fsck.extraHeaderEntry=error ("ignore" by default) was set serves
    to do this for us.

1. ec4465adb38 (Add "tag" objects that can be used to sign other
   objects., 2005-04-25)

2. https://en.wikipedia.org/wiki/List_of_UTC_time_offsets

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt |   9 +-
 builtin/mktag.c             | 196 +++++++++---------------------------
 fsck.c                      |  32 +++++-
 fsck.h                      |   9 ++
 t/t1006-cat-file.sh         |   2 +-
 t/t3800-mktag.sh            |  63 ++++++------
 6 files changed, 127 insertions(+), 184 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index adc63f6d4e..03cd63d9f6 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -25,7 +25,14 @@ write a tag found in `my-tag`:
     git hash-object -t tag -w --stdin <my-tag
 
 The difference is that mktag will die before writing the tag if the
-tag doesn't pass a sanity check.
+tag doesn't pass a linkgit:git-fsck[1] check.
+
+The "fsck" check done mktag is stricter than what linkgit:git-fsck[1]
+would run by default in that all `fsck.<msg-id>` messages are promoted
+from warnings to errors (so e.g. a missing "tagger" line is an error).
+
+Extra headers in the object are also an error under mktag, but ignored
+by linkgit:git-fsck[1]
 
 Tag Format
 ----------
diff --git a/builtin/mktag.c b/builtin/mktag.c
index d89a3c201d..4dd35bc79e 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -2,160 +2,60 @@
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
+#include "fsck.h"
 
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
+static int mktag_fsck_error_func(struct fsck_options *o,
+				 const struct object_id *oid,
+				 enum object_type object_type,
+				 int msg_type, const char *message)
 {
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
-
-	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
-		free(buffer);
+	switch (msg_type) {
+	case FSCK_WARN:
+	case FSCK_ERROR:
+		/*
+		 * We treat both warnings and errors as errors, things
+		 * like missing "tagger" lines are "only" warnings
+		 * under fsck, we've always considered them an error.
+		 */
+		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
+		return 1;
+	default:
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		    msg_type);
 	}
-	return ret;
 }
 
-static int verify_tag(char *buffer, unsigned long size)
+static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 {
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
+	int ret;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+	const struct object_id *repl;
+
+	buffer = read_object_file(tagged_oid, &type, &size);
+	if (!buffer)
+		die("could not read tagged object '%s'",
+		    oid_to_hex(tagged_oid));
+	if (type != *tagged_type)
+		die("object '%s' tagged as '%s', but is a '%s' type",
+		    oid_to_hex(tagged_oid),
+		    type_name(*tagged_type), type_name(type));
+
+	repl = lookup_replace_object(the_repository, tagged_oid);
+	ret = check_object_signature(the_repository, repl,
+				     buffer, size, type_name(*tagged_type));
+	free(buffer);
 
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
+	return ret;
 }
 
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
+	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+	struct object_id tagged_oid;
+	int tagged_type;
 	struct object_id result;
 
 	if (argc != 1)
@@ -164,10 +64,14 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
+	fsck_options.error_func = mktag_fsck_error_func;
+	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
+	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
+				&tagged_oid, &tagged_type))
+		die("tag on stdin did not pass our strict fsck check");
+
+	if (verify_object_in_tag(&tagged_oid, &tagged_type))
+		die("tag on stdin did not refer to a valid object");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write tag file");
diff --git a/fsck.c b/fsck.c
index f82e2fe9e3..bed5e20e03 100644
--- a/fsck.c
+++ b/fsck.c
@@ -80,7 +80,9 @@ static struct oidset gitmodules_done = OIDSET_INIT;
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
-	FUNC(MISSING_TAGGER_ENTRY, INFO)
+	FUNC(MISSING_TAGGER_ENTRY, INFO) \
+	/* ignored (elevated when requested) */ \
+	FUNC(EXTRA_HEADER_ENTRY, IGNORE)
 
 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
 enum fsck_msg_id {
@@ -911,6 +913,16 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		    unsigned long size, struct fsck_options *options)
 {
 	struct object_id tagged_oid;
+	int tagged_type;
+	return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
+				   &tagged_type);
+}
+
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tagged_type)
+{
 	int ret = 0;
 	char *eol;
 	struct strbuf sb = STRBUF_INIT;
@@ -924,7 +936,7 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
 		goto done;
 	}
-	if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
+	if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
 		if (ret)
 			goto done;
@@ -940,7 +952,8 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
 		goto done;
 	}
-	if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
+	*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
+	if (*tagged_type < 0)
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
 	if (ret)
 		goto done;
@@ -975,6 +988,19 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (!starts_with(buffer, "\n")) {
+		/*
+		 * The verify_headers() check will allow
+		 * e.g. "[...]tagger <tagger>\nsome
+		 * garbage\n\nmessage" to pass, thinking "some
+		 * garbage" could be a custom header. E.g. "mktag"
+		 * doesn't want any unknown headers.
+		 */
+		ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+		if (ret)
+			goto done;
+	}
+
 done:
 	strbuf_release(&sb);
 	return ret;
diff --git a/fsck.h b/fsck.h
index 69cf715e79..29ee4c45e8 100644
--- a/fsck.h
+++ b/fsck.h
@@ -62,6 +62,15 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
 int fsck_object(struct object *obj, void *data, unsigned long size,
 	struct fsck_options *options);
 
+/*
+ * fsck a tag, and pass info about it back to the caller. This is
+ * exposed fsck_object() internals for git-mktag(1).
+ */
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tag_type);
+
 /*
  * Some fsck checks are context-dependent, and may end up queued; run this
  * after completing all fsck_object() calls in order to resolve any remaining
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2f501d2dc9..5d2dc99b74 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
 
 $tag_description"
 
-tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
 tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index c6826762d9..d20adf0544 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -47,7 +47,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+	'^error:.* missingObject:'
 
 ############################################################
 #  2. object line label check
@@ -60,7 +60,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
+check_verify_failure '"object" line label check' '^error:.* missingObject:'
 
 ############################################################
 #  3. object line hash check
@@ -73,7 +73,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
 
 ############################################################
 #  4. type line label check
@@ -86,7 +86,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
 
 ############################################################
 #  5. type line eol check
@@ -94,7 +94,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
 
 ############################################################
 #  6. tag line label check #1
@@ -108,7 +108,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* missingTagEntry:'
 
 ############################################################
 #  7. tag line label check #2
@@ -120,7 +120,7 @@ tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* badType:'
 
 ############################################################
 #  8. type line type-name length check
@@ -132,7 +132,7 @@ tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char.*: type too long$'
+	'^error:.* badType:'
 
 ############################################################
 #  9. verify object (hash/type) check
@@ -146,7 +146,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
-	'^error: char7: could not verify object.*$'
+	'^fatal: could not read tagged object'
 
 cat >tag.sig <<EOF
 object $head
@@ -157,7 +157,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
-	'^fatal: invalid object type'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
@@ -168,7 +168,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object.*$'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $head
@@ -179,7 +179,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
-	'^error: char7: could not verify object'
+	'^fatal: object.*tagged as.*tree.*but is.*commit'
 
 ############################################################
 # 10. verify tag-name check
@@ -193,7 +193,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char.*: could not verify tag name$'
+	'^error:.* badTagName:'
 
 ############################################################
 # 11. tagger line label check #1
@@ -207,7 +207,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
 # 12. tagger line label check #2
@@ -222,10 +222,10 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
-# 13. disallow missing tag author name
+# 13. allow missing tag author name like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -236,8 +236,7 @@ tagger  <> 0 +0000
 This is filler
 EOF
 
-check_verify_failure 'disallow missing tag author name' \
-	'^error: char.*: missing tagger name$'
+test_expect_mktag_success 'allow missing tag author name'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -252,7 +251,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char.*: malformed tagger field$'
+	'^error:.* badEmail:'
 
 ############################################################
 # 15. allow empty tag email
@@ -268,7 +267,7 @@ EOF
 test_expect_mktag_success 'allow empty tag email'
 
 ############################################################
-# 16. disallow spaces in tag email
+# 16. allow spaces in tag email like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -278,8 +277,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 
 EOF
 
-check_verify_failure 'disallow spaces in tag email' \
-	'^error: char.*: malformed tagger field$'
+test_expect_mktag_success 'allow spaces in tag email like fsck'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -293,7 +291,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -307,7 +305,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -321,7 +319,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char.*: malformed tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 20. detect invalid tag timezone1
@@ -335,7 +333,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
 EOF
 
 check_verify_failure 'detect invalid tag timezone1' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
 # 21. detect invalid tag timezone2
@@ -349,10 +347,10 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
 EOF
 
 check_verify_failure 'detect invalid tag timezone2' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 ############################################################
-# 22. detect invalid tag timezone3
+# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
 
 cat >tag.sig <<EOF
 object $head
@@ -362,8 +360,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
 
 EOF
 
-check_verify_failure 'detect invalid tag timezone3' \
-	'^error: char.*: malformed tag timezone$'
+test_expect_mktag_success 'allow invalid tag timezone'
 
 ############################################################
 # 23. detect invalid header entry
@@ -378,7 +375,7 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error: char.*: trailing garbage in tag header$'
+	'^error:.* extraHeaderEntry:'
 
 cat >tag.sig <<EOF
 object $head
@@ -412,7 +409,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500$space
 EOF
 
 check_verify_failure 'extra whitespace at end of headers' \
-	'^error: char.*: malformed tag timezone$'
+	'^error:.* badTimezone:'
 
 cat >tag.sig <<EOF
 object $head
@@ -422,7 +419,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 EOF
 
 check_verify_failure 'disallow no header / body newline separator' \
-	'^error: char.*: trailing garbage in tag header$'
+	'^error:.* extraHeaderEntry:'
 
 ############################################################
 # 24. create valid tag
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 15/20] fsck: make fsck_config() re-usable
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (15 preceding siblings ...)
  2020-12-23  1:35               ` [PATCH v4 14/20] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:36               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:36               ` [PATCH v4 16/20] mktag: allow turning off fsck.extraHeaderEntry Ævar Arnfjörð Bjarmason
                                 ` (4 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Move the fsck_config() function from builtin/fsck.c to fsck.[ch]. This
allows for re-using it in other tools that expose fsck logic and want
to support its configuration variables.

A logical continuation of this change would be to use a common
function for all of {fetch,receive}.fsck.* and fsck.*. See
5d477a334a6 (fsck (receive-pack): allow demoting errors to warnings,
2015-06-22) and my own 1362df0d413 (fetch: implement fetch.fsck.*,
2018-07-27) for the relevant code.

However, those routines want to not parse the fsck.skipList into OIDs,
but rather pass them along with the --strict option to another
process. It would be possible to refactor that whole thing so we
support e.g. a "fetch." prefix, then just keep track of the skiplist
as a filename instead of parsing it, and learn to spew that all out
from our internal structures into something we can append to the
--strict option.

But instead I'm planning to re-use this in "mktag", which'll just
re-use these "fsck.*" variables as-is.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/fsck.c | 20 +-------------------
 fsck.c         | 25 +++++++++++++++++++++++++
 fsck.h         |  7 +++++++
 3 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/builtin/fsck.c b/builtin/fsck.c
index fbf26cafcf..821e7798c7 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -73,25 +73,7 @@ static const char *printable_type(const struct object_id *oid,
 
 static int fsck_config(const char *var, const char *value, void *cb)
 {
-	if (strcmp(var, "fsck.skiplist") == 0) {
-		const char *path;
-		struct strbuf sb = STRBUF_INIT;
-
-		if (git_config_pathname(&path, var, value))
-			return 1;
-		strbuf_addf(&sb, "skiplist=%s", path);
-		free((char *)path);
-		fsck_set_msg_types(&fsck_obj_options, sb.buf);
-		strbuf_release(&sb);
-		return 0;
-	}
-
-	if (skip_prefix(var, "fsck.", &var)) {
-		fsck_set_msg_type(&fsck_obj_options, var, value);
-		return 0;
-	}
-
-	return git_default_config(var, value, cb);
+	return fsck_config_internal(var, value, cb, &fsck_obj_options);
 }
 
 static int objerror(struct object *obj, const char *err)
diff --git a/fsck.c b/fsck.c
index bed5e20e03..9067a290a2 100644
--- a/fsck.c
+++ b/fsck.c
@@ -1310,3 +1310,28 @@ int fsck_finish(struct fsck_options *options)
 	oidset_clear(&gitmodules_done);
 	return ret;
 }
+
+int fsck_config_internal(const char *var, const char *value, void *cb,
+			 struct fsck_options *options)
+{
+	if (strcmp(var, "fsck.skiplist") == 0) {
+		const char *path;
+		struct strbuf sb = STRBUF_INIT;
+
+		if (git_config_pathname(&path, var, value))
+			return 1;
+		strbuf_addf(&sb, "skiplist=%s", path);
+		free((char *)path);
+		fsck_set_msg_types(options, sb.buf);
+		strbuf_release(&sb);
+		return 0;
+	}
+
+	if (skip_prefix(var, "fsck.", &var)) {
+		fsck_set_msg_type(options, var, value);
+		return 0;
+	}
+
+	return git_default_config(var, value, cb);
+}
+
diff --git a/fsck.h b/fsck.h
index 29ee4c45e8..423c467feb 100644
--- a/fsck.h
+++ b/fsck.h
@@ -103,4 +103,11 @@ void fsck_put_object_name(struct fsck_options *options,
 const char *fsck_describe_object(struct fsck_options *options,
 				 const struct object_id *oid);
 
+/*
+ * git_config() callback for use by fsck-y tools that want to support
+ * fsck.<msg> fsck.skipList etc.
+ */
+int fsck_config_internal(const char *var, const char *value, void *cb,
+			 struct fsck_options *options);
+
 #endif
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 16/20] mktag: allow turning off fsck.extraHeaderEntry
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (16 preceding siblings ...)
  2020-12-23  1:36               ` [PATCH v4 15/20] fsck: make fsck_config() re-usable Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:36               ` Ævar Arnfjörð Bjarmason
  2020-12-23 22:09                 ` SZEDER Gábor
  2020-12-23  1:36               ` [PATCH v4 17/20] mktag: allow omitting the header/body \n separator Ævar Arnfjörð Bjarmason
                                 ` (3 subsequent siblings)
  21 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

In earlier commits mktag learned to use the fsck machinery, at which
point we needed to add fsck.extraHeaderEntry so it could be as strict
about extra headers as it's been ever since it was implemented.

But it's not nice to need to switch away from "mktag" to "hash-object"
+ manual "fsck" just because you'd like to have an extra header. So
let's support turning it off by getting "fsck.*" variables from the
config.

Pedantically speaking it's still not possible to make "mktag" behave
just like "hash-object -t tag" does, since we're unconditionally going
to check the referenced object in verify_object_in_tag(), which is our
own check, and not one that exists in fsck.c.

But the spirit of "this works like fsck" is preserved, in that if you
created such a tag with "hash-object" and did a full "fsck" on the
repository it would also error out about that invalid object, it just
wouldn't emit the same message as fsck does.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt |  5 ++++-
 builtin/mktag.c             | 11 ++++++++++-
 t/t3800-mktag.sh            | 14 ++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 03cd63d9f6..d04657b219 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -32,7 +32,10 @@ would run by default in that all `fsck.<msg-id>` messages are promoted
 from warnings to errors (so e.g. a missing "tagger" line is an error).
 
 Extra headers in the object are also an error under mktag, but ignored
-by linkgit:git-fsck[1]
+by linkgit:git-fsck[1]. This extra check can be turned off by setting
+the appropriate `fsck.<msg-id>` varible:
+
+    git -c fsck.extraHeaderEntry=ignore mktag <my-tag-with-headers
 
 Tag Format
 ----------
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4dd35bc79e..373926d7e0 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -3,6 +3,14 @@
 #include "replace-object.h"
 #include "object-store.h"
 #include "fsck.h"
+#include "config.h"
+
+static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+
+static int mktag_config(const char *var, const char *value, void *cb)
+{
+	return fsck_config_internal(var, value, cb, &fsck_options);
+}
 
 static int mktag_fsck_error_func(struct fsck_options *o,
 				 const struct object_id *oid,
@@ -53,7 +61,6 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
-	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
 	struct object_id tagged_oid;
 	int tagged_type;
 	struct object_id result;
@@ -66,6 +73,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 
 	fsck_options.error_func = mktag_fsck_error_func;
 	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
+	/* config might set fsck.extraHeaderEntry=* again */
+	git_config(mktag_config, NULL);
 	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
 				&tagged_oid, &tagged_type))
 		die("tag on stdin did not pass our strict fsck check");
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d20adf0544..1019b42378 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -377,6 +377,20 @@ EOF
 check_verify_failure 'detect invalid header entry' \
 	'^error:.* extraHeaderEntry:'
 
+test_expect_success 'invalid header entry config & fsck' '
+	test_must_fail git mktag <tag.sig &&
+	test_must_fail git -c fsck.extraHeaderEntry=error mktag <tag.sig &&
+	test_must_fail git -c fsck.extraHeaderEntry=warn mktag <tag.sig &&
+	git -c fsck.extraHeaderEntry=ignore mktag <tag.sig &&
+	git fsck &&
+	env GIT_TEST_GETTEXT_POISON=false \
+		git -c fsck.extraHeaderEntry=warn fsck 2>err &&
+	grep "warning .*extraHeaderEntry:" err &&
+	test_must_fail env GIT_TEST_GETTEXT_POISON=false \
+		git -c fsck.extraHeaderEntry=error 2>err fsck &&
+	grep "error .* extraHeaderEntry:" err
+'
+
 cat >tag.sig <<EOF
 object $head
 type commit
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 17/20] mktag: allow omitting the header/body \n separator
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (17 preceding siblings ...)
  2020-12-23  1:36               ` [PATCH v4 16/20] mktag: allow turning off fsck.extraHeaderEntry Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:36               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:36               ` [PATCH v4 18/20] mktag: convert to parse-options Ævar Arnfjörð Bjarmason
                                 ` (2 subsequent siblings)
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Change mktag's acceptance rules to accept an empty body without an
empty line after the header again. This fixes an ancient unintended
dregression in "mktag".

When "mktag" was introduced in ec4465adb3 (Add "tag" objects that can
be used to sign other objects., 2005-04-25) the input checks were much
looser. When it was documented it 6cfec03680 (mktag: minimally update
the description., 2007-06-10) it was clearly intended for this \n to
be optional:

    The message, when [it] exists, is separated by a blank line from
    the header.

But then in e0aaf781f6 (mktag.c: improve verification of tagger field
and tests, 2008-03-27) this was made an error, seemingly by
accident. It was just a result of the general header checks, and all
the tests after that patch have a trailing empty line (but did not
before).

Let's allow this again, and tweak the test semantics changed in
e0aaf781f6 to remove the redundant empty line. New tests added in
previous commits of mine already added an explicit test for allowing
the empty line between header and body.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 fsck.c           | 2 ++
 t/t3800-mktag.sh | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/fsck.c b/fsck.c
index 9067a290a2..29c1eaca4c 100644
--- a/fsck.c
+++ b/fsck.c
@@ -987,6 +987,8 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
 	}
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
+	if (!*buffer)
+		goto done;
 
 	if (!starts_with(buffer, "\n")) {
 		/*
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 1019b42378..9383f7795b 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -432,8 +432,9 @@ tag mytag
 tagger T A Gger <tagger@example.com> 1206478233 -0500
 EOF
 
-check_verify_failure 'disallow no header / body newline separator' \
-	'^error:.* extraHeaderEntry:'
+test_expect_success 'allow no header / body newline separator' '
+	git mktag <tag.sig
+'
 
 ############################################################
 # 24. create valid tag
@@ -443,7 +444,6 @@ object $head
 type commit
 tag mytag
 tagger T A Gger <tagger@example.com> 1206478233 -0500
-
 EOF
 
 test_expect_mktag_success 'create valid tag object'
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 18/20] mktag: convert to parse-options
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (18 preceding siblings ...)
  2020-12-23  1:36               ` [PATCH v4 17/20] mktag: allow omitting the header/body \n separator Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:36               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:36               ` [PATCH v4 19/20] mktag: mark strings for translation Ævar Arnfjörð Bjarmason
  2020-12-23  1:36               ` [PATCH v4 20/20] mktag: add a --no-strict option Ævar Arnfjörð Bjarmason
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Convert the "mktag" command to use parse-options.h instead of its own
ad-hoc argc handling. This doesn't matter much in practice since it
doesn't support any options, but removes another special-case in our
codebase, and makes it easier to add options to it in the future.

It does marginally improve the situation for programs that want to
execute git commands in a consistent manner and e.g. always use
--end-of-options. E.g. "gitaly" does that, and has a blacklist of
built-ins that don't support --end-of-options. This is one less
special case for it and other similar programs to support.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c  | 14 ++++++++++++--
 t/t3800-mktag.sh | 12 ++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 373926d7e0..18b8492f4d 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -1,10 +1,16 @@
 #include "builtin.h"
+#include "parse-options.h"
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
 #include "fsck.h"
 #include "config.h"
 
+static char const * const builtin_mktag_usage[] = {
+	N_("git mktag"),
+	NULL
+};
+
 static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
 
 static int mktag_config(const char *var, const char *value, void *cb)
@@ -60,13 +66,17 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
+	static struct option builtin_mktag_options[] = {
+		OPT_END(),
+	};
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id tagged_oid;
 	int tagged_type;
 	struct object_id result;
 
-	if (argc != 1)
-		usage("git mktag");
+	argc = parse_options(argc, argv, NULL,
+			     builtin_mktag_options,
+			     builtin_mktag_usage, 0);
 
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 9383f7795b..177ab1682d 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -39,6 +39,18 @@ test_expect_success 'setup' '
 	head=$(git rev-parse --verify HEAD)
 '
 
+test_expect_success 'basic usage' '
+	cat >tag.sig <<-EOF &&
+	object $head
+	type commit
+	tag mytag
+	tagger T A Gger <tagger@example.com> 1206478233 -0500
+	EOF
+	git mktag <tag.sig &&
+	git mktag --end-of-options <tag.sig &&
+	test_expect_code 129 git mktag --unknown-option
+'
+
 ############################################################
 #  1. length check
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 19/20] mktag: mark strings for translation
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (19 preceding siblings ...)
  2020-12-23  1:36               ` [PATCH v4 18/20] mktag: convert to parse-options Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:36               ` Ævar Arnfjörð Bjarmason
  2020-12-23  1:36               ` [PATCH v4 20/20] mktag: add a --no-strict option Ævar Arnfjörð Bjarmason
  21 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Mark the errors mktag might emit for translation. This is a plumbing
command, but the errors it emits are intended to be human-readable.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c  | 16 ++++++++--------
 t/t3800-mktag.sh |  3 ++-
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 18b8492f4d..9b04b61c2b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -31,10 +31,10 @@ static int mktag_fsck_error_func(struct fsck_options *o,
 		 * like missing "tagger" lines are "only" warnings
 		 * under fsck, we've always considered them an error.
 		 */
-		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
+		fprintf_ln(stderr, _("error: tag input does not pass fsck: %s"), message);
 		return 1;
 	default:
-		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		BUG(_("%d (FSCK_IGNORE?) should never trigger this callback"),
 		    msg_type);
 	}
 }
@@ -49,10 +49,10 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 
 	buffer = read_object_file(tagged_oid, &type, &size);
 	if (!buffer)
-		die("could not read tagged object '%s'",
+		die(_("could not read tagged object '%s'"),
 		    oid_to_hex(tagged_oid));
 	if (type != *tagged_type)
-		die("object '%s' tagged as '%s', but is a '%s' type",
+		die(_("object '%s' tagged as '%s', but is a '%s' type"),
 		    oid_to_hex(tagged_oid),
 		    type_name(*tagged_type), type_name(type));
 
@@ -79,7 +79,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 			     builtin_mktag_usage, 0);
 
 	if (strbuf_read(&buf, 0, 0) < 0)
-		die_errno("could not read from stdin");
+		die_errno(_("could not read from stdin"));
 
 	fsck_options.error_func = mktag_fsck_error_func;
 	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
@@ -87,13 +87,13 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	git_config(mktag_config, NULL);
 	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
 				&tagged_oid, &tagged_type))
-		die("tag on stdin did not pass our strict fsck check");
+		die(_("tag on stdin did not pass our strict fsck check"));
 
 	if (verify_object_in_tag(&tagged_oid, &tagged_type))
-		die("tag on stdin did not refer to a valid object");
+		die(_("tag on stdin did not refer to a valid object"));
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
-		die("unable to write tag file");
+		die(_("unable to write tag file"));
 
 	strbuf_release(&buf);
 	puts(oid_to_hex(&result));
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 177ab1682d..2e8b718379 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,8 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		test_must_fail git mktag <tag.sig 2>message &&
+		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
+			git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v4 20/20] mktag: add a --no-strict option
  2020-12-09 20:01             ` [PATCH v3 " Ævar Arnfjörð Bjarmason
                                 ` (20 preceding siblings ...)
  2020-12-23  1:36               ` [PATCH v4 19/20] mktag: mark strings for translation Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:36               ` Ævar Arnfjörð Bjarmason
  2020-12-23 11:54                 ` Junio C Hamano
  2020-12-23 22:20                 ` SZEDER Gábor
  21 siblings, 2 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2020-12-23  1:36 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, Ævar Arnfjörð Bjarmason

Now that mktag has been migrated to use the fsck machinery to check
its input, it makes sense to teach it to run in the equivalent of "git
fsck"'s default mode, instead of hardcoding "git fsck --strict". Let's
do that and support the "--no-strict" option.

Since this is a new option we don't need to cater to parse-option.c's
default of automatically supporting --strict. So let's use
PARSE_OPT_NONEG, using a new trivial helper macro.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt |  7 +++++++
 builtin/mktag.c             |  9 +++++++++
 parse-options.h             |  1 +
 t/t3800-mktag.sh            | 35 ++++++++++++++++++++++++-----------
 4 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index d04657b219..05e49b6787 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -11,6 +11,13 @@ SYNOPSIS
 [verse]
 'git mktag'
 
+OPTIONS
+-------
+
+--no-strict::
+	By default mktag turns on the equivalent of
+	linkgit:git-fsck[1] `--strict` mode. This disables it.
+
 DESCRIPTION
 -----------
 
diff --git a/builtin/mktag.c b/builtin/mktag.c
index 9b04b61c2b..a6a4612247 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -10,6 +10,7 @@ static char const * const builtin_mktag_usage[] = {
 	N_("git mktag"),
 	NULL
 };
+static int option_no_strict;
 
 static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
 
@@ -25,6 +26,12 @@ static int mktag_fsck_error_func(struct fsck_options *o,
 {
 	switch (msg_type) {
 	case FSCK_WARN:
+		if (option_no_strict) {
+			fprintf_ln(stderr, _("warning: tag input does not pass fsck: %s"), message);
+			return 0;
+
+		}
+		/* fallthrough */
 	case FSCK_ERROR:
 		/*
 		 * We treat both warnings and errors as errors, things
@@ -67,6 +74,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	static struct option builtin_mktag_options[] = {
+		OPT_NO_BOOL(0, "no-strict", &option_no_strict,
+			    N_("don't do strict fsck checks")),
 		OPT_END(),
 	};
 	struct strbuf buf = STRBUF_INIT;
diff --git a/parse-options.h b/parse-options.h
index 7030d8f3da..90d6a817d7 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -166,6 +166,7 @@ struct option {
 #define OPT_COUNTUP(s, l, v, h)     OPT_COUNTUP_F(s, l, v, h, 0)
 #define OPT_SET_INT(s, l, v, h, i)  OPT_SET_INT_F(s, l, v, h, i, 0)
 #define OPT_BOOL(s, l, v, h)        OPT_BOOL_F(s, l, v, h, 0)
+#define OPT_NO_BOOL(s, l, v, h)     OPT_BOOL_F(s, l, v, h, PARSE_OPT_NONEG)
 #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
 				      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
 #define OPT_CMDMODE(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 2e8b718379..b436ae1e44 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -12,12 +12,16 @@ test_description='git mktag: tag object verify test'
 # given in the expect.pat file.
 
 check_verify_failure () {
-	expect="$2"
-	test_expect_success "$1" '
+	test_expect_success "$1" "
 		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
 			git mktag <tag.sig 2>message &&
-		grep "$expect" message
-	'
+		grep '$2' message &&
+		if test '$3' != '--no-strict'
+		then
+			test_must_fail git mktag --no-strict <tag.sig 2>message.no-strict &&
+			grep '$2' message.no-strict
+		fi
+	"
 }
 
 test_expect_mktag_success() {
@@ -49,7 +53,8 @@ test_expect_success 'basic usage' '
 	EOF
 	git mktag <tag.sig &&
 	git mktag --end-of-options <tag.sig &&
-	test_expect_code 129 git mktag --unknown-option
+	test_expect_code 129 git mktag --unknown-option &&
+	test_expect_code 129 git mktag --strict
 '
 
 ############################################################
@@ -60,7 +65,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error:.* missingObject:'
+	'^error:.* missingObject:' 'strict'
 
 ############################################################
 #  2. object line label check
@@ -206,7 +211,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error:.* badTagName:'
+	'^error:.* badTagName:' '--no-strict'
 
 ############################################################
 # 11. tagger line label check #1
@@ -220,7 +225,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error:.* missingTaggerEntry:'
+	'^error:.* missingTaggerEntry:' '--no-strict'
 
 ############################################################
 # 12. tagger line label check #2
@@ -235,7 +240,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error:.* missingTaggerEntry:'
+	'^error:.* missingTaggerEntry:' '--no-strict'
 
 ############################################################
 # 13. allow missing tag author name like fsck
@@ -264,7 +269,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error:.* badEmail:'
+	'^error:.* badEmail:' '--no-strict'
 
 ############################################################
 # 15. allow empty tag email
@@ -388,13 +393,21 @@ this line should not be here
 EOF
 
 check_verify_failure 'detect invalid header entry' \
-	'^error:.* extraHeaderEntry:'
+	'^error:.* extraHeaderEntry:' '--no-strict'
 
 test_expect_success 'invalid header entry config & fsck' '
 	test_must_fail git mktag <tag.sig &&
+	git mktag --no-strict <tag.sig &&
+
 	test_must_fail git -c fsck.extraHeaderEntry=error mktag <tag.sig &&
+	test_must_fail git -c fsck.extraHeaderEntry=error mktag --no-strict <tag.sig &&
+
 	test_must_fail git -c fsck.extraHeaderEntry=warn mktag <tag.sig &&
+	git -c fsck.extraHeaderEntry=warn mktag --no-strict <tag.sig &&
+
 	git -c fsck.extraHeaderEntry=ignore mktag <tag.sig &&
+	git -c fsck.extraHeaderEntry=ignore mktag --no-strict <tag.sig &&
+
 	git fsck &&
 	env GIT_TEST_GETTEXT_POISON=false \
 		git -c fsck.extraHeaderEntry=warn fsck 2>err &&
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 03/20] mktag doc: update to explain why to use this
  2020-12-23  1:35               ` [PATCH v4 03/20] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
@ 2020-12-23  1:57                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23  1:57 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change the mktag documentation to compare itself to the similar
> "hash-object -t tag" command. Before this someone reading the
> documentation wouldn't have much of an idea what the difference
> was.
>
> Let's allude to our own validation logic, and cross-link the "mktag"
> and "hash-object" documentation to aid discover-ability. A follow-up
> change to migrate "mktag" to use "fsck" validation will make the part
> about validation logic clearer.

We do not add links to refer to commands like "git commit-tree",
"git mktree" or "git add" just because these other commands can
create commit, tree and blob objects like hash-object does, so
adding a link to mktag in the hash-object documentation feels a
bit fishy, but the extended description in mktag that highlights
the added value of the command over hash-object reads very well.

>  Tag Format
>  ----------
> @@ -34,6 +43,10 @@ exists, is separated by a blank line from the header.  The
>  message part may contain a signature that Git itself doesn't
>  care about, but that can be verified with gpg.
>  
> +SEE ALSO
> +--------
> +linkgit:git-hash-object[1],

Comma,

> +
>  GIT
>  ---
>  Part of the linkgit:git[1] suite

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 06/20] mktag tests: improve verify_object() test coverage
  2020-12-23  1:35               ` [PATCH v4 06/20] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
@ 2020-12-23  2:04                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23  2:04 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

>  cat >tag.sig <<EOF
>  object $(test_oid deadbeef)
> +type tag
> +tag mytag
> +tagger . <> 0 +0000
> +
> +EOF
> +
> +check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
> +	'^error: char7: could not verify object.*$'
> +

OK.


> +cat >tag.sig <<EOF
> +object $head
>  type tagggg
>  tag mytag
>  tagger . <> 0 +0000
>  
>  EOF
>  
> -check_verify_failure 'verify object (SHA1/type) check' \
> +check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
> +	'^fatal: invalid object type'

tagggg is "made-up type".  Where did we grab head from?  it is
head=$(git rev-parse --verify HEAD) at the very beginning.  Is that
really a nonexisting object?

> +cat >tag.sig <<EOF
> +object $(test_oid deadbeef)
> +type tagggg
> +tag mytag
> +tagger . <> 0 +0000
> +
> +EOF
> +
> +check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
>  	'^error: char7: could not verify object.*$'

This is the "made-up type, nonexisting object", and previous one is
"made-up type, valid object", no?

> +cat >tag.sig <<EOF
> +object $head
> +type tree
> +tag mytag
> +tagger . <> 0 +0000
> +
> +EOF
> +
> +check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
> +	'^error: char7: could not verify object'

And this is correct.  "type tree" is not a made-up type, and $head
is a valid object but it is not of "type tree".


Somehow I feel as if this patch is trying to see if reviewers are
paying attention to ;-)

Thanks.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 07/20] mktag tests: don't pipe to stderr needlessly
  2020-12-23  1:35               ` [PATCH v4 07/20] mktag tests: don't pipe to stderr needlessly Ævar Arnfjörð Bjarmason
@ 2020-12-23  2:10                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23  2:10 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Remove the piping of stderr to "message" in the valid tag test. This
> pattern seems to have been copy/pasted from the failure case in
> 446c6faec6 (New tests and en-passant modifications to mktag.,
> 2006-07-29).
>
> Nothing is piped to "message" here, and in the event of the test
> failing it only serves to hide the error.

I think the verb "to pipe" specifically means "redirecting the
output to a pipe" and nothing else.

    mktag tests: don't redirect stderr to a file needlessly

    Remove the redirection of stderr to "message" in the valid tag
    tests.  This pattern ... 2006-07-29).  Nobody examines the
    contents of the resulting "message" file, so the net result is
    that error messages cannot be seen in "sh t3800-mktag.sh -v"
    output.

or something like that?

>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t3800-mktag.sh | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index 9ae1b0bb0a..bbd148618e 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -257,7 +257,7 @@ EOF
>  
>  test_expect_success \
>      'allow empty tag email' \
> -    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
> +    'git mktag <tag.sig >.git/refs/tags/mytag'
>  
>  ############################################################
>  # 16. disallow spaces in tag email
> @@ -385,7 +385,7 @@ EOF
>  
>  test_expect_success \
>      'create valid tag' \
> -    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
> +    'git mktag <tag.sig >.git/refs/tags/mytag'
>  
>  ############################################################
>  # 25. check mytag

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 08/20] mktag tests: don't create "mytag" twice
  2020-12-23  1:35               ` [PATCH v4 08/20] mktag tests: don't create "mytag" twice Ævar Arnfjörð Bjarmason
@ 2020-12-23  2:18                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23  2:18 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change a test added in e0aaf781f6 (mktag.c: improve verification of
> tagger field and tests, 2008-03-27) to not create "mytag", which
> should only be created and verified at the end in an earlier test
> added in 446c6faec6 (New tests and en-passant modifications to mktag.,
> 2006-07-29).

If mktag fails to create a tag, presumably .git/refs/tags/mytag file
would be left empty.  Wouldn't "git tag -l" notice that it is not a
valid ref and omit it from its output?  I suspect if you corrupt the
contents of tag.sig temporarily while the first of the original
tests were running in such a way that mktag notices a bogosity, the
second half of the original would notice.

Having said that, I like the new way much better.

But do we even need to create the tag with update-ref in the first
place?  What does it check?  The fact that "mktag" only creates an
object and never creates a new ref to point at the newly created
object (hence we expect refs/tags/mytag does not yet exist)?

I am not complaining that it runs update-ref there or creates the
mytag tag.  I am just saying I do not understand what the test wants
to check by doing so.

> While we're at it let's prevent a similar logic error from creeping
> into the test by asserting that "mytag" doesn't exist before we create
> it. Let's do this by moving the test to use "update-ref", instead of
> our own homebrew ad-hoc refstore update.

Great.  I really like this part of the change that future-proofs us.

Thanks.

> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t3800-mktag.sh | 17 +++++------------
>  1 file changed, 5 insertions(+), 12 deletions(-)
>
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index bbd148618e..b6dcdbebe6 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -257,7 +257,7 @@ EOF
>  
>  test_expect_success \
>      'allow empty tag email' \
> -    'git mktag <tag.sig >.git/refs/tags/mytag'
> +    'git mktag <tag.sig'
>  
>  ############################################################
>  # 16. disallow spaces in tag email
> @@ -383,16 +383,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
>  
>  EOF
>  
> -test_expect_success \
> -    'create valid tag' \
> -    'git mktag <tag.sig >.git/refs/tags/mytag'
> -
> -############################################################
> -# 25. check mytag
> -
> -test_expect_success \
> -    'check mytag' \
> -    'git tag -l | grep mytag'
> -
> +test_expect_success 'create valid tag' '
> +	git mktag <tag.sig >hash &&
> +	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero)
> +'
>  
>  test_done

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 09/20] mktag tests: stress test whitespace handling
  2020-12-23  1:35               ` [PATCH v4 09/20] mktag tests: stress test whitespace handling Ævar Arnfjörð Bjarmason
@ 2020-12-23  2:27                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23  2:27 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> +cat >tag.sig <<EOF
> +object $head
> +type commit
> +tag mytag
> +tagger T A Gger <tagger@example.com> 1206478233 -0500
> +
> +
> +this line comes after an extra newline
> +EOF
> +
> +test_expect_success 'allow extra newlines at start of body' '
> +	git mktag <tag.sig
> +'

OK.

> +cat >tag.sig <<EOF
> +object $head
> +type commit
> +tag mytag
> +tagger T A Gger <tagger@example.com> 1206478233 -0500
> +
> +EOF
> +
> +test_expect_success 'allow extra newlines at end of headers' '
> +	git mktag <tag.sig
> +'

I am not sure what the contrast between "at start of body" and "at
end of headers" means.

Ahh, OK, we are making sure that we "allow a blank line after the
headers before an empty body".

Makes sense (but see below).

> +space=' '
> +cat >tag.sig <<EOF
> +object $head
> +type commit
> +tag mytag
> +tagger T A Gger <tagger@example.com> 1206478233 -0500$space
> +
> +EOF
> +
> +check_verify_failure 'extra whitespace at end of headers' \
> +	'^error: char.*: malformed tag timezone$'

OK.  Presumably all the other header lines forbid trailing space
as a malformed line?

> +cat >tag.sig <<EOF
> +object $head
> +type commit
> +tag mytag
> +tagger T A Gger <tagger@example.com> 1206478233 -0500
> +EOF
> +
> +check_verify_failure 'disallow no header / body newline separator' \
> +	'^error: char.*: trailing garbage in tag header$'

Now I am confused.  This fails because...?   We earlier saw that we
"allow" a blank line after the header when no body is present, but
this says the test fails if a blank line exists after the header
when no body exists.  I do not have any objection to the behaviour
of the command, but doesn't this mean the earlier test was not
labelled correctly?  It may make more sense to move this test next
to the earlier one, and name them

    "require a blank line before even an empty body (1)"
    "require a blank line before even an empty body (2)"

or something?  The earlier one ensures that a payload with such a
blank line is OK, and this one ensures that a payload without such a
blank line causes a failure.

Thanks.


> +
>  ############################################################
>  # 24. create valid tag

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 10/20] mktag tests: test "hash-object" compatibility
  2020-12-23  1:35               ` [PATCH v4 10/20] mktag tests: test "hash-object" compatibility Ævar Arnfjörð Bjarmason
@ 2020-12-23  2:29                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23  2:29 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Change all the successful "mktag" tests to test that "hash-object"
> produces the same hash for the input, and that fsck passes for
> both.
>
> This tests e.g. that "mktag" doesn't trim its input or otherwise munge
> it in a way that "hash-object" doesn't.
>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  t/t3800-mktag.sh | 26 +++++++++++++++-----------
>  1 file changed, 15 insertions(+), 11 deletions(-)
>
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index f339321be8..c6826762d9 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -19,6 +19,16 @@ check_verify_failure () {
>  	'
>  }
>  
> +test_expect_mktag_success() {
> +	test_expect_success "$1" '
> +		git hash-object -t tag -w --stdin <tag.sig >expected &&
> +		git fsck --strict &&
> +		git mktag <tag.sig >hash &&
> +		git fsck --strict &&
> +		test_cmp expected hash
> +	'
> +}

;-)  Nice.

I'll stop here for tonight.  Thanks for working on this.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 20/20] mktag: add a --no-strict option
  2020-12-23  1:36               ` [PATCH v4 20/20] mktag: add a --no-strict option Ævar Arnfjörð Bjarmason
@ 2020-12-23 11:54                 ` Junio C Hamano
  2020-12-23 22:20                 ` SZEDER Gábor
  1 sibling, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23 11:54 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> Now that mktag has been migrated to use the fsck machinery to check
> its input, it makes sense to teach it to run in the equivalent of "git
> fsck"'s default mode, instead of hardcoding "git fsck --strict". Let's
> do that and support the "--no-strict" option.
>
> Since this is a new option we don't need to cater to parse-option.c's
> default of automatically supporting --strict. So let's use
> PARSE_OPT_NONEG, using a new trivial helper macro.

Hmph, I would have thought that the internal file-scope static done
like

    static int option_strict = 1;

with OPT_BOOL() would be more natural, than a double negation.

What problem does this new OPT_NO_BOOL() thing solve?


> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  Documentation/git-mktag.txt |  7 +++++++
>  builtin/mktag.c             |  9 +++++++++
>  parse-options.h             |  1 +
>  t/t3800-mktag.sh            | 35 ++++++++++++++++++++++++-----------
>  4 files changed, 41 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
> index d04657b219..05e49b6787 100644
> --- a/Documentation/git-mktag.txt
> +++ b/Documentation/git-mktag.txt
> @@ -11,6 +11,13 @@ SYNOPSIS
>  [verse]
>  'git mktag'
>  
> +OPTIONS
> +-------
> +
> +--no-strict::
> +	By default mktag turns on the equivalent of
> +	linkgit:git-fsck[1] `--strict` mode. This disables it.
> +
>  DESCRIPTION
>  -----------
>  
> diff --git a/builtin/mktag.c b/builtin/mktag.c
> index 9b04b61c2b..a6a4612247 100644
> --- a/builtin/mktag.c
> +++ b/builtin/mktag.c
> @@ -10,6 +10,7 @@ static char const * const builtin_mktag_usage[] = {
>  	N_("git mktag"),
>  	NULL
>  };
> +static int option_no_strict;
>  
>  static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
>  
> @@ -25,6 +26,12 @@ static int mktag_fsck_error_func(struct fsck_options *o,
>  {
>  	switch (msg_type) {
>  	case FSCK_WARN:
> +		if (option_no_strict) {
> +			fprintf_ln(stderr, _("warning: tag input does not pass fsck: %s"), message);
> +			return 0;
> +
> +		}
> +		/* fallthrough */
>  	case FSCK_ERROR:
>  		/*
>  		 * We treat both warnings and errors as errors, things
> @@ -67,6 +74,8 @@ static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
>  int cmd_mktag(int argc, const char **argv, const char *prefix)
>  {
>  	static struct option builtin_mktag_options[] = {
> +		OPT_NO_BOOL(0, "no-strict", &option_no_strict,
> +			    N_("don't do strict fsck checks")),
>  		OPT_END(),
>  	};
>  	struct strbuf buf = STRBUF_INIT;
> diff --git a/parse-options.h b/parse-options.h
> index 7030d8f3da..90d6a817d7 100644
> --- a/parse-options.h
> +++ b/parse-options.h
> @@ -166,6 +166,7 @@ struct option {
>  #define OPT_COUNTUP(s, l, v, h)     OPT_COUNTUP_F(s, l, v, h, 0)
>  #define OPT_SET_INT(s, l, v, h, i)  OPT_SET_INT_F(s, l, v, h, i, 0)
>  #define OPT_BOOL(s, l, v, h)        OPT_BOOL_F(s, l, v, h, 0)
> +#define OPT_NO_BOOL(s, l, v, h)     OPT_BOOL_F(s, l, v, h, PARSE_OPT_NONEG)
>  #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
>  				      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
>  #define OPT_CMDMODE(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \
> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index 2e8b718379..b436ae1e44 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -12,12 +12,16 @@ test_description='git mktag: tag object verify test'
>  # given in the expect.pat file.
>  
>  check_verify_failure () {
> -	expect="$2"
> -	test_expect_success "$1" '
> +	test_expect_success "$1" "
>  		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
>  			git mktag <tag.sig 2>message &&
> -		grep "$expect" message
> -	'
> +		grep '$2' message &&
> +		if test '$3' != '--no-strict'
> +		then
> +			test_must_fail git mktag --no-strict <tag.sig 2>message.no-strict &&
> +			grep '$2' message.no-strict
> +		fi
> +	"
>  }
>  
>  test_expect_mktag_success() {
> @@ -49,7 +53,8 @@ test_expect_success 'basic usage' '
>  	EOF
>  	git mktag <tag.sig &&
>  	git mktag --end-of-options <tag.sig &&
> -	test_expect_code 129 git mktag --unknown-option
> +	test_expect_code 129 git mktag --unknown-option &&
> +	test_expect_code 129 git mktag --strict
>  '
>  
>  ############################################################
> @@ -60,7 +65,7 @@ too short for a tag
>  EOF
>  
>  check_verify_failure 'Tag object length check' \
> -	'^error:.* missingObject:'
> +	'^error:.* missingObject:' 'strict'
>  
>  ############################################################
>  #  2. object line label check
> @@ -206,7 +211,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure 'verify tag-name check' \
> -	'^error:.* badTagName:'
> +	'^error:.* badTagName:' '--no-strict'
>  
>  ############################################################
>  # 11. tagger line label check #1
> @@ -220,7 +225,7 @@ This is filler
>  EOF
>  
>  check_verify_failure '"tagger" line label check #1' \
> -	'^error:.* missingTaggerEntry:'
> +	'^error:.* missingTaggerEntry:' '--no-strict'
>  
>  ############################################################
>  # 12. tagger line label check #2
> @@ -235,7 +240,7 @@ This is filler
>  EOF
>  
>  check_verify_failure '"tagger" line label check #2' \
> -	'^error:.* missingTaggerEntry:'
> +	'^error:.* missingTaggerEntry:' '--no-strict'
>  
>  ############################################################
>  # 13. allow missing tag author name like fsck
> @@ -264,7 +269,7 @@ tagger T A Gger <
>  EOF
>  
>  check_verify_failure 'disallow malformed tagger' \
> -	'^error:.* badEmail:'
> +	'^error:.* badEmail:' '--no-strict'
>  
>  ############################################################
>  # 15. allow empty tag email
> @@ -388,13 +393,21 @@ this line should not be here
>  EOF
>  
>  check_verify_failure 'detect invalid header entry' \
> -	'^error:.* extraHeaderEntry:'
> +	'^error:.* extraHeaderEntry:' '--no-strict'
>  
>  test_expect_success 'invalid header entry config & fsck' '
>  	test_must_fail git mktag <tag.sig &&
> +	git mktag --no-strict <tag.sig &&
> +
>  	test_must_fail git -c fsck.extraHeaderEntry=error mktag <tag.sig &&
> +	test_must_fail git -c fsck.extraHeaderEntry=error mktag --no-strict <tag.sig &&
> +
>  	test_must_fail git -c fsck.extraHeaderEntry=warn mktag <tag.sig &&
> +	git -c fsck.extraHeaderEntry=warn mktag --no-strict <tag.sig &&
> +
>  	git -c fsck.extraHeaderEntry=ignore mktag <tag.sig &&
> +	git -c fsck.extraHeaderEntry=ignore mktag --no-strict <tag.sig &&
> +
>  	git fsck &&
>  	env GIT_TEST_GETTEXT_POISON=false \
>  		git -c fsck.extraHeaderEntry=warn fsck 2>err &&

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 14/20] mktag: use fsck instead of custom verify_tag()
  2020-12-23  1:35               ` [PATCH v4 14/20] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
@ 2020-12-23 13:34                 ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23 13:34 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> +static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
>  {
> +	int ret;
> +	enum object_type type;
> +	unsigned long size;
> +	void *buffer;
> +	const struct object_id *repl;
> +
> +	buffer = read_object_file(tagged_oid, &type, &size);
> +	if (!buffer)
> +		die("could not read tagged object '%s'",
> +		    oid_to_hex(tagged_oid));
> +	if (type != *tagged_type)
> +		die("object '%s' tagged as '%s', but is a '%s' type",
> +		    oid_to_hex(tagged_oid),
> +		    type_name(*tagged_type), type_name(type));
> +
> +	repl = lookup_replace_object(the_repository, tagged_oid);
> +	ret = check_object_signature(the_repository, repl,
> +				     buffer, size, type_name(*tagged_type));
> +	free(buffer);

This is not new, but I wonder if the object whose name is repl can
be of different type than the object whose name is tagged_oid, and
what happens when such a replacement is defined.

> +	return ret;
>  }
> ...
> +/*
> + * fsck a tag, and pass info about it back to the caller. This is
> + * exposed fsck_object() internals for git-mktag(1).
> + */
> +int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
> +			unsigned long size, struct fsck_options *options,
> +			struct object_id *tagged_oid,
> +			int *tag_type);
> +

OK.

> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index c6826762d9..d20adf0544 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -47,7 +47,7 @@ too short for a tag
>  EOF

OK.  This seems to show rather nicely what checks got loosened
(and nothing got tightened it seems).

Thanks.  Looking good so far.

>  
>  check_verify_failure 'Tag object length check' \
> -	'^error: .*size wrong.*$'
> +	'^error:.* missingObject:'
>  
>  ############################################################
>  #  2. object line label check
> @@ -60,7 +60,7 @@ tagger . <> 0 +0000
>  
>  EOF
>  
> -check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
> +check_verify_failure '"object" line label check' '^error:.* missingObject:'
>  
>  ############################################################
>  #  3. object line hash check
> @@ -73,7 +73,7 @@ tagger . <> 0 +0000
>  
>  EOF
>  
> -check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
> +check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
>  
>  ############################################################
>  #  4. type line label check
> @@ -86,7 +86,7 @@ tagger . <> 0 +0000
>  
>  EOF
>  
> -check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
> +check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
>  
>  ############################################################
>  #  5. type line eol check
> @@ -94,7 +94,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
>  echo "object $head" >tag.sig
>  printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
>  
> -check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
> +check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
>  
>  ############################################################
>  #  6. tag line label check #1
> @@ -108,7 +108,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure '"tag" line label check #1' \
> -	'^error: char.*: no "tag " found$'
> +	'^error:.* missingTagEntry:'
>  
>  ############################################################
>  #  7. tag line label check #2
> @@ -120,7 +120,7 @@ tag
>  EOF
>  
>  check_verify_failure '"tag" line label check #2' \
> -	'^error: char.*: no "tag " found$'
> +	'^error:.* badType:'
>  
>  ############################################################
>  #  8. type line type-name length check
> @@ -132,7 +132,7 @@ tag mytag
>  EOF
>  
>  check_verify_failure '"type" line type-name length check' \
> -	'^error: char.*: type too long$'
> +	'^error:.* badType:'
>  
>  ############################################################
>  #  9. verify object (hash/type) check
> @@ -146,7 +146,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
> -	'^error: char7: could not verify object.*$'
> +	'^fatal: could not read tagged object'
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -157,7 +157,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
> -	'^fatal: invalid object type'
> +	'^error:.* badType:'
>  
>  cat >tag.sig <<EOF
>  object $(test_oid deadbeef)
> @@ -168,7 +168,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
> -	'^error: char7: could not verify object.*$'
> +	'^error:.* badType:'
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -179,7 +179,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
> -	'^error: char7: could not verify object'
> +	'^fatal: object.*tagged as.*tree.*but is.*commit'
>  
>  ############################################################
>  # 10. verify tag-name check
> @@ -193,7 +193,7 @@ tagger . <> 0 +0000
>  EOF
>  
>  check_verify_failure 'verify tag-name check' \
> -	'^error: char.*: could not verify tag name$'
> +	'^error:.* badTagName:'
>  
>  ############################################################
>  # 11. tagger line label check #1
> @@ -207,7 +207,7 @@ This is filler
>  EOF
>  
>  check_verify_failure '"tagger" line label check #1' \
> -	'^error: char.*: could not find "tagger "$'
> +	'^error:.* missingTaggerEntry:'
>  
>  ############################################################
>  # 12. tagger line label check #2
> @@ -222,10 +222,10 @@ This is filler
>  EOF
>  
>  check_verify_failure '"tagger" line label check #2' \
> -	'^error: char.*: could not find "tagger "$'
> +	'^error:.* missingTaggerEntry:'
>  
>  ############################################################
> -# 13. disallow missing tag author name
> +# 13. allow missing tag author name like fsck
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -236,8 +236,7 @@ tagger  <> 0 +0000
>  This is filler
>  EOF
>  
> -check_verify_failure 'disallow missing tag author name' \
> -	'^error: char.*: missing tagger name$'
> +test_expect_mktag_success 'allow missing tag author name'
>  
>  ############################################################
>  # 14. disallow missing tag author name
> @@ -252,7 +251,7 @@ tagger T A Gger <
>  EOF
>  
>  check_verify_failure 'disallow malformed tagger' \
> -	'^error: char.*: malformed tagger field$'
> +	'^error:.* badEmail:'
>  
>  ############################################################
>  # 15. allow empty tag email
> @@ -268,7 +267,7 @@ EOF
>  test_expect_mktag_success 'allow empty tag email'
>  
>  ############################################################
> -# 16. disallow spaces in tag email
> +# 16. allow spaces in tag email like fsck
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -278,8 +277,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000
>  
>  EOF
>  
> -check_verify_failure 'disallow spaces in tag email' \
> -	'^error: char.*: malformed tagger field$'
> +test_expect_mktag_success 'allow spaces in tag email like fsck'
>  
>  ############################################################
>  # 17. disallow missing tag timestamp
> @@ -293,7 +291,7 @@ tagger T A Gger <tagger@example.com>__
>  EOF
>  
>  check_verify_failure 'disallow missing tag timestamp' \
> -	'^error: char.*: missing tag timestamp$'
> +	'^error:.* badDate:'
>  
>  ############################################################
>  # 18. detect invalid tag timestamp1
> @@ -307,7 +305,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
>  EOF
>  
>  check_verify_failure 'detect invalid tag timestamp1' \
> -	'^error: char.*: missing tag timestamp$'
> +	'^error:.* badDate:'
>  
>  ############################################################
>  # 19. detect invalid tag timestamp2
> @@ -321,7 +319,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
>  EOF
>  
>  check_verify_failure 'detect invalid tag timestamp2' \
> -	'^error: char.*: malformed tag timestamp$'
> +	'^error:.* badDate:'
>  
>  ############################################################
>  # 20. detect invalid tag timezone1
> @@ -335,7 +333,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT
>  EOF
>  
>  check_verify_failure 'detect invalid tag timezone1' \
> -	'^error: char.*: malformed tag timezone$'
> +	'^error:.* badTimezone:'
>  
>  ############################################################
>  # 21. detect invalid tag timezone2
> @@ -349,10 +347,10 @@ tagger T A Gger <tagger@example.com> 1206478233 +  30
>  EOF
>  
>  check_verify_failure 'detect invalid tag timezone2' \
> -	'^error: char.*: malformed tag timezone$'
> +	'^error:.* badTimezone:'
>  
>  ############################################################
> -# 22. detect invalid tag timezone3
> +# 22. allow invalid tag timezone3 (the maximum is -1200/+1400)
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -362,8 +360,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430
>  
>  EOF
>  
> -check_verify_failure 'detect invalid tag timezone3' \
> -	'^error: char.*: malformed tag timezone$'
> +test_expect_mktag_success 'allow invalid tag timezone'
>  
>  ############################################################
>  # 23. detect invalid header entry
> @@ -378,7 +375,7 @@ this line should not be here
>  EOF
>  
>  check_verify_failure 'detect invalid header entry' \
> -	'^error: char.*: trailing garbage in tag header$'
> +	'^error:.* extraHeaderEntry:'
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -412,7 +409,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500$space
>  EOF
>  
>  check_verify_failure 'extra whitespace at end of headers' \
> -	'^error: char.*: malformed tag timezone$'
> +	'^error:.* badTimezone:'
>  
>  cat >tag.sig <<EOF
>  object $head
> @@ -422,7 +419,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
>  EOF
>  
>  check_verify_failure 'disallow no header / body newline separator' \
> -	'^error: char.*: trailing garbage in tag header$'
> +	'^error:.* extraHeaderEntry:'
>  
>  ############################################################
>  # 24. create valid tag

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 00/20] make "mktag" use fsck_tag() & more
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
@ 2020-12-23 13:54                 ` Junio C Hamano
  2020-12-24  9:16                   ` Junio C Hamano
  2021-01-05 19:42                 ` [PATCH v5 00/23] " Ævar Arnfjörð Bjarmason
                                   ` (23 subsequent siblings)
  24 siblings, 1 reply; 185+ messages in thread
From: Junio C Hamano @ 2020-12-23 13:54 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Jeff King, brian m . carlson, Eric Sunshine, Johannes Schindelin

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> So, when re-rolling this with Junio's small fixup this grew in scope a
> bit, but should paradoxically be easier to deal with even though it's
> 2x the size now. Read on:

The core part didn't change all that much, which made it a bit
easier to see.  I left comments here and there, but the series
mostly looked sensible in general.

Thanks.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 16/20] mktag: allow turning off fsck.extraHeaderEntry
  2020-12-23  1:36               ` [PATCH v4 16/20] mktag: allow turning off fsck.extraHeaderEntry Ævar Arnfjörð Bjarmason
@ 2020-12-23 22:09                 ` SZEDER Gábor
  0 siblings, 0 replies; 185+ messages in thread
From: SZEDER Gábor @ 2020-12-23 22:09 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Wed, Dec 23, 2020 at 02:36:01AM +0100, Ævar Arnfjörð Bjarmason wrote:
> In earlier commits mktag learned to use the fsck machinery, at which
> point we needed to add fsck.extraHeaderEntry so it could be as strict
> about extra headers as it's been ever since it was implemented.
> 
> But it's not nice to need to switch away from "mktag" to "hash-object"
> + manual "fsck" just because you'd like to have an extra header. So
> let's support turning it off by getting "fsck.*" variables from the
> config.
> 
> Pedantically speaking it's still not possible to make "mktag" behave
> just like "hash-object -t tag" does, since we're unconditionally going
> to check the referenced object in verify_object_in_tag(), which is our
> own check, and not one that exists in fsck.c.
> 
> But the spirit of "this works like fsck" is preserved, in that if you
> created such a tag with "hash-object" and did a full "fsck" on the
> repository it would also error out about that invalid object, it just
> wouldn't emit the same message as fsck does.
> 
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---

> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index d20adf0544..1019b42378 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -377,6 +377,20 @@ EOF
>  check_verify_failure 'detect invalid header entry' \
>  	'^error:.* extraHeaderEntry:'
>  
> +test_expect_success 'invalid header entry config & fsck' '
> +	test_must_fail git mktag <tag.sig &&
> +	test_must_fail git -c fsck.extraHeaderEntry=error mktag <tag.sig &&
> +	test_must_fail git -c fsck.extraHeaderEntry=warn mktag <tag.sig &&
> +	git -c fsck.extraHeaderEntry=ignore mktag <tag.sig &&
> +	git fsck &&
> +	env GIT_TEST_GETTEXT_POISON=false \

Why this 'env GIT_TEST_GETTEXT_POISON=false' here...

> +		git -c fsck.extraHeaderEntry=warn fsck 2>err &&
> +	grep "warning .*extraHeaderEntry:" err &&

... instead of test_i18ngrep here?

> +	test_must_fail env GIT_TEST_GETTEXT_POISON=false \
> +		git -c fsck.extraHeaderEntry=error 2>err fsck &&
> +	grep "error .* extraHeaderEntry:" err
> +'
> +
>  cat >tag.sig <<EOF
>  object $head
>  type commit
> -- 
> 2.29.2.222.g5d2a92d10f8
> 

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 20/20] mktag: add a --no-strict option
  2020-12-23  1:36               ` [PATCH v4 20/20] mktag: add a --no-strict option Ævar Arnfjörð Bjarmason
  2020-12-23 11:54                 ` Junio C Hamano
@ 2020-12-23 22:20                 ` SZEDER Gábor
  1 sibling, 0 replies; 185+ messages in thread
From: SZEDER Gábor @ 2020-12-23 22:20 UTC (permalink / raw)
  To: Ævar Arnfjörð Bjarmason
  Cc: git, Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin

On Wed, Dec 23, 2020 at 02:36:05AM +0100, Ævar Arnfjörð Bjarmason wrote:
> Now that mktag has been migrated to use the fsck machinery to check
> its input, it makes sense to teach it to run in the equivalent of "git
> fsck"'s default mode, instead of hardcoding "git fsck --strict". Let's
> do that and support the "--no-strict" option.
> 
> Since this is a new option we don't need to cater to parse-option.c's
> default of automatically supporting --strict. So let's use
> PARSE_OPT_NONEG, using a new trivial helper macro.
> 
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

> diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
> index 2e8b718379..b436ae1e44 100755
> --- a/t/t3800-mktag.sh
> +++ b/t/t3800-mktag.sh
> @@ -12,12 +12,16 @@ test_description='git mktag: tag object verify test'
>  # given in the expect.pat file.
>  
>  check_verify_failure () {
> -	expect="$2"
> -	test_expect_success "$1" '
> +	test_expect_success "$1" "
>  		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
>  			git mktag <tag.sig 2>message &&

So this 'git mktag' is always invoked with
GIT_TEST_GETTEXT_POISON=false (instead of, for some reason, using
test_i18ngrep on the next line)...

> -		grep "$expect" message
> -	'
> +		grep '$2' message &&
> +		if test '$3' != '--no-strict'
> +		then
> +			test_must_fail git mktag --no-strict <tag.sig 2>message.no-strict &&

Wouldn't a GIT_TEST_GETTEXT_POISON=false be necessary for this 'git
mktag' as well?  Or, alternatively (preferably?), a test_i18ngrep
below.

> +			grep '$2' message.no-strict
> +		fi
> +	"
>  }
>  
>  test_expect_mktag_success() {

^ permalink raw reply	[flat|nested] 185+ messages in thread

* Re: [PATCH v4 00/20] make "mktag" use fsck_tag() & more
  2020-12-23 13:54                 ` Junio C Hamano
@ 2020-12-24  9:16                   ` Junio C Hamano
  0 siblings, 0 replies; 185+ messages in thread
From: Junio C Hamano @ 2020-12-24  9:16 UTC (permalink / raw)
  To: git
  Cc: Ævar Arnfjörð Bjarmason, Jeff King,
	brian m . carlson, Eric Sunshine, Johannes Schindelin

Junio C Hamano <gitster@pobox.com> writes:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> So, when re-rolling this with Junio's small fixup this grew in scope a
>> bit, but should paradoxically be easier to deal with even though it's
>> 2x the size now. Read on:
>
> The core part didn't change all that much, which made it a bit
> easier to see.  I left comments here and there, but the series
> mostly looked sensible in general.

This failure is likely from the "mktag" series:

  https://github.com/git/git/runs/1602776090#step:4:1622 (summary)
  https://github.com/git/git/runs/1602776090#step:5:158 (the first one of them)

Thanks.

^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 00/23] make "mktag" use fsck_tag() & more
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
  2020-12-23 13:54                 ` Junio C Hamano
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 01/23] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
                                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

A late re-roll due to the holidays. Thanks all for the feedback on v4,
this should address all of it.

Brief comments on each patch below, and then the range-diff.

Ævar Arnfjörð Bjarmason (23):
  mktag doc: say <hash> not <sha1>
  mktag doc: grammar fix, when exists -> when it exists

No changes.

  mktag doc: update to explain why to use this

Got rid of the cross-linking of mktag and hash-object manpages as
suggested by Junio.

  mktag tests: don't needlessly use a subshell

no changes.

  mktag tests: use "test_commit" helper

NEW: Another trivial mktag test cleanup, make it use test_commit
instead of 3 boilerplate lines in its test. Made a later change
smaller.

  mktag tests: remove needless SHA-1 hardcoding

no changes.

  mktag tests: don't redirect stderr to a file needlessly

Reworded the commit message, and fixed another copy/pasted mktag test
(in the git-replace test file) that used the same pattern.

  mktag tests: don't create "mytag" twice

The commit message notes that testing the tag at the end is pointless,
but now later we'll do something with it...

  mktag tests: run "fsck" after creating "mytag"

...i.e. run fsck to (potentially in the future) check the envelope
v.s. refname.

  mktag tests: stress test whitespace handling

Reworded commit message & test descriptions to make more sense, got
rid of the one $space test, which didn't really add anything.

  mktag tests: test "hash-object" compatibility

Gets rid of the "create tag refname" special case at the end of the
tests by now doing it for every successful tag creation.

  mktag tests: improve verify_object() test coverage

Commit message update, notes that we don't do "git replace" tests.

  mktag tests: test verify_object() with replaced objects

NEW: test mktag with git-replace'd objects.

  mktag: use default strbuf_read() hint
  mktag: remove redundant braces in one-line body "if"
  mktag: use puts(str) instead of printf("%s\n", str)

no changes.

  mktag: use fsck instead of custom verify_tag()

only carried-forward changes from rebasing on the changes above.

  fsck: make fsck_config() re-usable
  mktag: allow turning off fsck.extraHeaderEntry

no changes.

  mktag: allow omitting the header/body \n separator
  mktag: convert to parse-options

ditto carried-forward changes.

  mktag: mark strings for translation
  mktag: add a --no-strict option

Use the more normal OPT_BOOL pattern, and fix a stupid error in
GIT_TEST_GETTEXT_POISON=true testing that broke the CI.

 Documentation/git-mktag.txt |  39 +++++-
 builtin/fsck.c              |  20 +--
 builtin/mktag.c             | 235 +++++++++++++----------------------
 fsck.c                      |  59 ++++++++-
 fsck.h                      |  16 +++
 t/t1006-cat-file.sh         |   2 +-
 t/t3800-mktag.sh            | 236 ++++++++++++++++++++++++++++--------
 t/t6050-replace.sh          |   2 +-
 8 files changed, 375 insertions(+), 234 deletions(-)

Range-diff:
 1:  a31c305cfc6 =  1:  74b035fb842 mktag doc: say <hash> not <sha1>
 2:  81cb4cba5c0 =  2:  202bd33533f mktag doc: grammar fix, when exists -> when it exists
 3:  b4bc6f894cb !  3:  d1f650b6c4c mktag doc: update to explain why to use this
    @@ Commit message
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    - ## Documentation/git-hash-object.txt ##
    -@@ Documentation/git-hash-object.txt: OPTIONS
    - 	stress-testing Git itself or reproducing characteristics of corrupt or
    - 	bogus objects encountered in the wild.
    - 
    -+SEE ALSO
    -+--------
    -+linkgit:git-mktag[1]
    -+
    - GIT
    - ---
    - Part of the linkgit:git[1] suite
    -
      ## Documentation/git-mktag.txt ##
     @@ Documentation/git-mktag.txt: git-mktag(1)
      
    @@ Documentation/git-mktag.txt: SYNOPSIS
      
      Tag Format
      ----------
    -@@ Documentation/git-mktag.txt: exists, is separated by a blank line from the header.  The
    - message part may contain a signature that Git itself doesn't
    - care about, but that can be verified with gpg.
    - 
    -+SEE ALSO
    -+--------
    -+linkgit:git-hash-object[1],
    -+
    - GIT
    - ---
    - Part of the linkgit:git[1] suite
 4:  acb94e02895 =  4:  64432d22952 mktag tests: don't needlessly use a subshell
 -:  ----------- >  5:  57c7bdde80b mktag tests: use "test_commit" helper
 5:  4ae76ec5e3f =  6:  ba581a99c89 mktag tests: remove needless SHA-1 hardcoding
 7:  b81d31a917c !  7:  974d1b9c6ec mktag tests: don't pipe to stderr needlessly
    @@ Metadata
     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## Commit message ##
    -    mktag tests: don't pipe to stderr needlessly
    +    mktag tests: don't redirect stderr to a file needlessly
     
    -    Remove the piping of stderr to "message" in the valid tag test. This
    -    pattern seems to have been copy/pasted from the failure case in
    -    446c6faec6 (New tests and en-passant modifications to mktag.,
    +    Remove the redirection of stderr to "message" in the valid tag
    +    test. This pattern seems to have been copy/pasted from the failure
    +    case in 446c6faec6 (New tests and en-passant modifications to mktag.,
         2006-07-29).
     
    -    Nothing is piped to "message" here, and in the event of the test
    -    failing it only serves to hide the error.
    +    While I'm at it do the same for the "replace" tests. The tag creation
    +    I'm changing here seems to have been copy/pasted from the "mktag"
    +    tests to those tests in cc400f50112 (mktag: call
    +    "check_sha1_signature" with the replacement sha1, 2009-01-23).
    +
    +    Nobody examines the contents of the resulting "message" file, so the
    +    net result is that error messages cannot be seen in "sh t3800-mktag.sh
    +    -v" output.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ t/t3800-mktag.sh: EOF
      
      ############################################################
      # 25. check mytag
    +
    + ## t/t6050-replace.sh ##
    +@@ t/t6050-replace.sh: tagger T A Gger <> 0 +0000
    + EOF
    + 
    + test_expect_success 'tag replaced commit' '
    +-     git mktag <tag.sig >.git/refs/tags/mytag 2>message
    ++     git mktag <tag.sig >.git/refs/tags/mytag
    + '
    + 
    + test_expect_success '"git fsck" works' '
 8:  11f59718b4b !  8:  73d82dbca24 mktag tests: don't create "mytag" twice
    @@ Commit message
         it. Let's do this by moving the test to use "update-ref", instead of
         our own homebrew ad-hoc refstore update.
     
    +    We're not really testing for anything yet by creating the tag at the
    +    end here. A subsequent commit will change that.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## t/t3800-mktag.sh ##
 -:  ----------- >  9:  0aa8190f404 mktag tests: run "fsck" after creating "mytag"
 9:  dd6b012b0c6 ! 10:  078e73c4221 mktag tests: stress test whitespace handling
    @@ Metadata
      ## Commit message ##
         mktag tests: stress test whitespace handling
     
    -    Add tests for various whitespace edge cases around the header/body
    -    boundary, such as two newlines separating the header and body, a space
    -    at the end of the "tagger" line before the header etc.
    +    Add tests for a couple of whitespace edge cases around the header/body
    +    boundary.
     
    -    Add a test showing that we insist that an empty body must be preceded
    -    by an empty line. This test for a long-standing regression which goes
    -    against the command's documented behavior. It'll be addressed in a
    -    follow-up change.
    +    I consider the requirement for a blank line before the empty body a
    +    bug, it's a long-standing regression which goes against the command's
    +    documented behavior. This bug will be addressed in a follow-up change.
     
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
    @@ t/t3800-mktag.sh: EOF
     +
     +EOF
     +
    -+test_expect_success 'allow extra newlines at end of headers' '
    ++test_expect_success 'require a blank line before an empty body (1)' '
     +	git mktag <tag.sig
     +'
     +
    -+space=' '
    -+cat >tag.sig <<EOF
    -+object $head
    -+type commit
    -+tag mytag
    -+tagger T A Gger <tagger@example.com> 1206478233 -0500$space
    -+
    -+EOF
    -+
    -+check_verify_failure 'extra whitespace at end of headers' \
    -+	'^error: char.*: malformed tag timezone$'
    -+
     +cat >tag.sig <<EOF
     +object $head
     +type commit
    @@ t/t3800-mktag.sh: EOF
     +tagger T A Gger <tagger@example.com> 1206478233 -0500
     +EOF
     +
    -+check_verify_failure 'disallow no header / body newline separator' \
    ++check_verify_failure 'require a blank line before an empty body (2)' \
     +	'^error: char.*: trailing garbage in tag header$'
     +
      ############################################################
10:  56c6b562fd5 ! 11:  83d7ca86b8f mktag tests: test "hash-object" compatibility
    @@ Commit message
         This tests e.g. that "mktag" doesn't trim its input or otherwise munge
         it in a way that "hash-object" doesn't.
     
    +    Since we're doing an "fsck --strict" here at the end let's incorporate
    +    the creation of the "mytag" name into this test, removing the
    +    special-case at the end of the file.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## t/t3800-mktag.sh ##
    @@ t/t3800-mktag.sh: check_verify_failure () {
     +	test_expect_success "$1" '
     +		git hash-object -t tag -w --stdin <tag.sig >expected &&
     +		git fsck --strict &&
    ++
     +		git mktag <tag.sig >hash &&
    -+		git fsck --strict &&
    -+		test_cmp expected hash
    ++		test_cmp expected hash &&
    ++		test_when_finished "git update-ref -d refs/tags/mytag $(cat hash)" &&
    ++		git update-ref refs/tags/mytag $(cat hash) $(test_oid zero) &&
    ++		git fsck --strict	
     +	'
     +}
     +
    @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500
      
      EOF
      
    --test_expect_success 'allow extra newlines at end of headers' '
    +-test_expect_success 'require a blank line before an empty body (1)' '
     -	git mktag <tag.sig
     -'
    -+test_expect_mktag_success 'allow extra newlines at end of headers'
    ++test_expect_mktag_success 'require a blank line before an empty body (1)'
      
    - space=' '
      cat >tag.sig <<EOF
    + object $head
     @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500
      
      EOF
      
     -test_expect_success 'create valid tag' '
     -	git mktag <tag.sig >hash &&
    +-	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero) &&
    +-	git fsck --strict
    +-'
     +test_expect_mktag_success 'create valid tag object'
    -+test_expect_success 'create valid tag name' '
    - 	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero)
    - '
      
    + test_done
 6:  9effb4532bc ! 12:  6cbf9176c35 mktag tests: improve verify_object() test coverage
    @@ Commit message
         Let's split these tests up, so we're testing all combinations of a
         non-existing object and in invalid/wrong "type" lines.
     
    +    We need to provide GIT_TEST_GETTEXT_POISON=false here because the
    +    "invalid object type" error is emitted by
    +    parse_loose_header_extended(), which has that message already marked
    +    for translation. Another option would be to use test_i18ngrep, but I
    +    prefer always running the test, not skipping it under gettext poison
    +    testing.
    +
    +    I'm not testing this in combination with "git replace". That'll be
    +    done in a subsequent commit.
    +
         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
     
      ## t/t3800-mktag.sh ##
    +@@ t/t3800-mktag.sh: test_description='git mktag: tag object verify test'
    + check_verify_failure () {
    + 	expect="$2"
    + 	test_expect_success "$1" '
    +-		test_must_fail git mktag <tag.sig 2>message &&
    ++		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
    ++			git mktag <tag.sig 2>message &&
    + 		grep "$expect" message
    + 	'
    + }
     @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
      	'^error: char.*: type too long$'
      
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
      EOF
      
     -check_verify_failure 'verify object (SHA1/type) check' \
    -+check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
    ++check_verify_failure 'verify object (hash/type) check -- made-up type, valid object' \
     +	'^fatal: invalid object type'
     +
     +cat >tag.sig <<EOF
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
     +
     +EOF
     +
    -+check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
    ++check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
      	'^error: char7: could not verify object.*$'
      
     +cat >tag.sig <<EOF
    @@ t/t3800-mktag.sh: check_verify_failure '"type" line type-name length check' \
     +
     +EOF
     +
    -+check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
    ++check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
     +	'^error: char7: could not verify object'
     +
      ############################################################
 -:  ----------- > 13:  ca1567866b0 mktag tests: test verify_object() with replaced objects
11:  1e2e4ec2697 = 14:  ac31d8658f3 mktag: use default strbuf_read() hint
12:  be2ab3edab0 = 15:  e32292af8b4 mktag: remove redundant braces in one-line body "if"
13:  d8514df970c = 16:  405fd2c747d mktag: use puts(str) instead of printf("%s\n", str)
14:  346d73cc972 ! 17:  6edaa992a25 mktag: use fsck instead of custom verify_tag()
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
    + check_verify_failure 'verify object (hash/type) check -- made-up type, valid object' \
     -	'^fatal: invalid object type'
     +	'^error:.* badType:'
      
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
    + check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
     -	'^error: char7: could not verify object.*$'
     +	'^error:.* badType:'
      
    @@ t/t3800-mktag.sh: tagger . <> 0 +0000
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
      EOF
      
    - check_verify_failure 'verify object (hash/type) check -- incorrect type, valid object' \
    + check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
     -	'^error: char7: could not verify object'
     +	'^fatal: object.*tagged as.*tree.*but is.*commit'
      
    + ############################################################
    + #  9.5. verify object (hash/type) check -- replacement
    +@@ t/t3800-mktag.sh: tagger . <> 0 +0000
    + EOF
    + 
    + check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
    +-	'^error: char7: could not verify object'
    ++	'^fatal: object.*tagged as.*tree.*but is.*blob'
    + 
      ############################################################
      # 10. verify tag-name check
     @@ t/t3800-mktag.sh: tagger . <> 0 +0000
    @@ t/t3800-mktag.sh: this line should not be here
     -	'^error: char.*: trailing garbage in tag header$'
     +	'^error:.* extraHeaderEntry:'
      
    - cat >tag.sig <<EOF
    - object $head
    -@@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500$space
    - EOF
    - 
    - check_verify_failure 'extra whitespace at end of headers' \
    --	'^error: char.*: malformed tag timezone$'
    -+	'^error:.* badTimezone:'
    - 
      cat >tag.sig <<EOF
      object $head
     @@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500
      EOF
      
    - check_verify_failure 'disallow no header / body newline separator' \
    + check_verify_failure 'require a blank line before an empty body (2)' \
     -	'^error: char.*: trailing garbage in tag header$'
     +	'^error:.* extraHeaderEntry:'
      
15:  0e7994d8fc3 = 18:  4c3fbb7ed58 fsck: make fsck_config() re-usable
16:  5e8046022b6 = 19:  32fc2264ec1 mktag: allow turning off fsck.extraHeaderEntry
17:  32698e1d005 ! 20:  32922a42dda mktag: allow omitting the header/body \n separator
    @@ fsck.c: int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
      		/*
     
      ## t/t3800-mktag.sh ##
    +@@ t/t3800-mktag.sh: tagger T A Gger <tagger@example.com> 1206478233 -0500
    + 
    + EOF
    + 
    +-test_expect_mktag_success 'require a blank line before an empty body (1)'
    ++test_expect_mktag_success 'allow a blank line before an empty body (1)'
    + 
    + cat >tag.sig <<EOF
    + object $head
     @@ t/t3800-mktag.sh: tag mytag
      tagger T A Gger <tagger@example.com> 1206478233 -0500
      EOF
      
    --check_verify_failure 'disallow no header / body newline separator' \
    +-check_verify_failure 'require a blank line before an empty body (2)' \
     -	'^error:.* extraHeaderEntry:'
    -+test_expect_success 'allow no header / body newline separator' '
    -+	git mktag <tag.sig
    -+'
    ++test_expect_mktag_success 'allow no blank line before an empty body (2)'
      
      ############################################################
      # 24. create valid tag
18:  b6a22f2f992 ! 21:  3c991dda02b mktag: convert to parse-options
    @@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, i
     
      ## t/t3800-mktag.sh ##
     @@ t/t3800-mktag.sh: test_expect_success 'setup' '
    - 	head=$(git rev-parse --verify HEAD)
    + 	blob=$(git rev-parse --verify HEAD:B.t)
      '
      
     +test_expect_success 'basic usage' '
19:  7fc0b81df7d ! 22:  16db5858a08 mktag: mark strings for translation
    @@ builtin/mktag.c: int cmd_mktag(int argc, const char **argv, const char *prefix)
      
      	strbuf_release(&buf);
      	puts(oid_to_hex(&result));
    -
    - ## t/t3800-mktag.sh ##
    -@@ t/t3800-mktag.sh: test_description='git mktag: tag object verify test'
    - check_verify_failure () {
    - 	expect="$2"
    - 	test_expect_success "$1" '
    --		test_must_fail git mktag <tag.sig 2>message &&
    -+		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
    -+			git mktag <tag.sig 2>message &&
    - 		grep "$expect" message
    - 	'
    - }
20:  6fa443d528c ! 23:  94d6aca6962 mktag: add a --no-strict option
    @@ Documentation/git-mktag.txt: SYNOPSIS
     +OPTIONS
     +-------
     +
    -+--no-strict::
    ++--strict::
     +	By default mktag turns on the equivalent of
    -+	linkgit:git-fsck[1] `--strict` mode. This disables it.
    ++	linkgit:git-fsck[1] `--strict` mode. Use `--no-strict` to
    ++	disable it.
     +
      DESCRIPTION
      -----------
    @@ builtin/mktag.c: static char const * const builtin_mktag_usage[] = {
      	N_("git mktag"),
      	NULL
      };
    -+static int option_no_strict;
    ++static int option_strict = 1;
      
      static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
      
    @@ builtin/mktag.c: static int mktag_fsck_error_func(struct fsck_options *o,
      {
      	switch (msg_type) {
      	case FSCK_WARN:
    -+		if (option_no_strict) {
    ++		if (!option_strict) {
     +			fprintf_ln(stderr, _("warning: tag input does not pass fsck: %s"), message);
     +			return 0;
     +
    @@ builtin/mktag.c: static int verify_object_in_tag(struct object_id *tagged_oid, i
      int cmd_mktag(int argc, const char **argv, const char *prefix)
      {
      	static struct option builtin_mktag_options[] = {
    -+		OPT_NO_BOOL(0, "no-strict", &option_no_strict,
    -+			    N_("don't do strict fsck checks")),
    ++		OPT_BOOL(0, "strict", &option_strict,
    ++			 N_("enable more strict checking")),
      		OPT_END(),
      	};
      	struct strbuf buf = STRBUF_INIT;
     
    - ## parse-options.h ##
    -@@ parse-options.h: struct option {
    - #define OPT_COUNTUP(s, l, v, h)     OPT_COUNTUP_F(s, l, v, h, 0)
    - #define OPT_SET_INT(s, l, v, h, i)  OPT_SET_INT_F(s, l, v, h, i, 0)
    - #define OPT_BOOL(s, l, v, h)        OPT_BOOL_F(s, l, v, h, 0)
    -+#define OPT_NO_BOOL(s, l, v, h)     OPT_BOOL_F(s, l, v, h, PARSE_OPT_NONEG)
    - #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
    - 				      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
    - #define OPT_CMDMODE(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \
    -
      ## t/t3800-mktag.sh ##
     @@ t/t3800-mktag.sh: test_description='git mktag: tag object verify test'
      # given in the expect.pat file.
    @@ t/t3800-mktag.sh: test_description='git mktag: tag object verify test'
     +		grep '$2' message &&
     +		if test '$3' != '--no-strict'
     +		then
    -+			test_must_fail git mktag --no-strict <tag.sig 2>message.no-strict &&
    ++			test_must_fail env GIT_TEST_GETTEXT_POISON=false \
    ++				git mktag --no-strict <tag.sig 2>message.no-strict &&
     +			grep '$2' message.no-strict
     +		fi
     +	"
      }
      
      test_expect_mktag_success() {
    -@@ t/t3800-mktag.sh: test_expect_success 'basic usage' '
    - 	EOF
    - 	git mktag <tag.sig &&
    - 	git mktag --end-of-options <tag.sig &&
    --	test_expect_code 129 git mktag --unknown-option
    -+	test_expect_code 129 git mktag --unknown-option &&
    -+	test_expect_code 129 git mktag --strict
    - '
    - 
    - ############################################################
     @@ t/t3800-mktag.sh: too short for a tag
      EOF
      
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 01/23] mktag doc: say <hash> not <sha1>
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
  2020-12-23 13:54                 ` Junio C Hamano
  2021-01-05 19:42                 ` [PATCH v5 00/23] " Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 02/23] mktag doc: grammar fix, when exists -> when it exists Ævar Arnfjörð Bjarmason
                                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change the "mktag" documentation to refer to the input hash as just
"hash", not "sha1". This command has supported SHA-256 for a while
now.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index fa6a7561236..a158428eb9f 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -23,7 +23,7 @@ Tag Format
 A tag signature file, to be fed to this command's standard input,
 has a very simple fixed format: four lines of
 
-  object <sha1>
+  object <hash>
   type <typename>
   tag <tagname>
   tagger <tagger>
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 02/23] mktag doc: grammar fix, when exists -> when it exists
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (2 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 01/23] mktag doc: say <hash> not <sha1> Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 03/23] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
                                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Amend the wording of documentation added in 6cfec03680 (mktag:
minimally update the description., 2007-06-10). It makes more sense to
say "when it exists" here, as we're referring to "the message".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index a158428eb9f..1b0667e372a 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -29,7 +29,7 @@ has a very simple fixed format: four lines of
   tagger <tagger>
 
 followed by some 'optional' free-form message (some tags created
-by older Git may not have `tagger` line).  The message, when
+by older Git may not have `tagger` line).  The message, when it
 exists, is separated by a blank line from the header.  The
 message part may contain a signature that Git itself doesn't
 care about, but that can be verified with gpg.
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 03/23] mktag doc: update to explain why to use this
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (3 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 02/23] mktag doc: grammar fix, when exists -> when it exists Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 04/23] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
                                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change the mktag documentation to compare itself to the similar
"hash-object -t tag" command. Before this someone reading the
documentation wouldn't have much of an idea what the difference
was.

Let's allude to our own validation logic, and cross-link the "mktag"
and "hash-object" documentation to aid discover-ability. A follow-up
change to migrate "mktag" to use "fsck" validation will make the part
about validation logic clearer.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 1b0667e372a..20af1915e9e 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -3,7 +3,7 @@ git-mktag(1)
 
 NAME
 ----
-git-mktag - Creates a tag object
+git-mktag - Creates a tag object with extra validation
 
 
 SYNOPSIS
@@ -13,10 +13,19 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Reads a tag contents on standard input and creates a tag object
-that can also be used to sign other objects.
 
-The output is the new tag's <object> identifier.
+Reads a tag contents on standard input and creates a tag object. The
+output is the new tag's <object> identifier.
+
+This command is mostly equivalent to linkgit:git-hash-object[1]
+invoked with `-t tag -w --stdin`. I.e. both of these will create and
+write a tag found in `my-tag`:
+
+    git mktag <my-tag
+    git hash-object -t tag -w --stdin <my-tag
+
+The difference is that mktag will die before writing the tag if the
+tag doesn't pass a sanity check.
 
 Tag Format
 ----------
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 04/23] mktag tests: don't needlessly use a subshell
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (4 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 03/23] mktag doc: update to explain why to use this Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 05/23] mktag tests: use "test_commit" helper Ævar Arnfjörð Bjarmason
                                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

The use of a subshell dates back to e9b20943b77 (t/t3800: do not use a
temporary file to hold expected result., 2008-01-04). It's not needed
anymore, if it ever was.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index d696aa4e52e..0e411e3c45f 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,7 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		( test_must_fail git mktag <tag.sig 2>message ) &&
+		test_must_fail git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 05/23] mktag tests: use "test_commit" helper
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (5 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 04/23] mktag tests: don't needlessly use a subshell Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 06/23] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
                                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Replace ad-hoc setup of a single commit in the "mktag" tests with our
standard helper pattern. The old setup dated back to 446c6faec69 (New
tests and en-passant modifications to mktag., 2006-07-29) before the
helper existed.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 0e411e3c45f..dd21a1247a2 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -23,9 +23,7 @@ check_verify_failure () {
 # first create a commit, so we have a valid object/type
 # for the tag.
 test_expect_success 'setup' '
-	echo Hello >A &&
-	git update-index --add A &&
-	git commit -m "Initial commit" &&
+	test_commit A &&
 	head=$(git rev-parse --verify HEAD)
 '
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 06/23] mktag tests: remove needless SHA-1 hardcoding
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (6 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 05/23] mktag tests: use "test_commit" helper Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 07/23] mktag tests: don't redirect stderr to a file needlessly Ævar Arnfjörð Bjarmason
                                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change the tests amended in acb49d1cc8b (t3800: make hash-size
independent, 2019-08-18) even more to make them independent of either
SHA-1 or SHA-256.

Some of these tests were failing for the wrong reasons. The first one
being modified here would fail because the line starts with "xxxxxx"
instead of "object", the rest of the line doesn't matter.

Let's just put a valid hash on the rest of the line anyway to narrow
the test down for just the s/object/xxxxxx/ case.

The second one being modified here would fail under
GIT_TEST_DEFAULT_HASH=sha256 because <some sha-1 length garbage> is an
invalid SHA-256, but we should really be testing <some sha-256 length
garbage> when under SHA-256.

This doesn't really matter since we should be able to trust other
parts of the code to validate things in the 0-9a-f range, but let's
keep it for good measure.

There's a later test which tests an invalid SHA which looks like a
valid one, to stress the "We refuse to tag something we can't
verify[...]" logic in mktag.c.

But here we're testing for a SHA-length string which contains
characters outside of the /[0-9a-f]/i set.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index dd21a1247a2..e1a2892f58b 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -41,7 +41,7 @@ check_verify_failure 'Tag object length check' \
 #  2. object line label check
 
 cat >tag.sig <<EOF
-xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
+xxxxxx $head
 type tag
 tag mytag
 tagger . <> 0 +0000
@@ -51,10 +51,10 @@ EOF
 check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
 
 ############################################################
-#  3. object line SHA1 check
+#  3. object line hash check
 
 cat >tag.sig <<EOF
-object zz9e9b33986b1c2670fff52c5067603117b3e895
+object $(echo $head | tr 0-9a-f z)
 type tag
 tag mytag
 tagger . <> 0 +0000
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 07/23] mktag tests: don't redirect stderr to a file needlessly
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (7 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 06/23] mktag tests: remove needless SHA-1 hardcoding Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 08/23] mktag tests: don't create "mytag" twice Ævar Arnfjörð Bjarmason
                                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Remove the redirection of stderr to "message" in the valid tag
test. This pattern seems to have been copy/pasted from the failure
case in 446c6faec6 (New tests and en-passant modifications to mktag.,
2006-07-29).

While I'm at it do the same for the "replace" tests. The tag creation
I'm changing here seems to have been copy/pasted from the "mktag"
tests to those tests in cc400f50112 (mktag: call
"check_sha1_signature" with the replacement sha1, 2009-01-23).

Nobody examines the contents of the resulting "message" file, so the
net result is that error messages cannot be seen in "sh t3800-mktag.sh
-v" output.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh   | 4 ++--
 t/t6050-replace.sh | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e1a2892f58b..c542c3e1a8e 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -222,7 +222,7 @@ EOF
 
 test_expect_success \
     'allow empty tag email' \
-    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
+    'git mktag <tag.sig >.git/refs/tags/mytag'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -350,7 +350,7 @@ EOF
 
 test_expect_success \
     'create valid tag' \
-    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
+    'git mktag <tag.sig >.git/refs/tags/mytag'
 
 ############################################################
 # 25. check mytag
diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh
index c80dc10b8f1..0dbe086118a 100755
--- a/t/t6050-replace.sh
+++ b/t/t6050-replace.sh
@@ -129,7 +129,7 @@ tagger T A Gger <> 0 +0000
 EOF
 
 test_expect_success 'tag replaced commit' '
-     git mktag <tag.sig >.git/refs/tags/mytag 2>message
+     git mktag <tag.sig >.git/refs/tags/mytag
 '
 
 test_expect_success '"git fsck" works' '
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 08/23] mktag tests: don't create "mytag" twice
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (8 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 07/23] mktag tests: don't redirect stderr to a file needlessly Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 09/23] mktag tests: run "fsck" after creating "mytag" Ævar Arnfjörð Bjarmason
                                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change a test added in e0aaf781f6 (mktag.c: improve verification of
tagger field and tests, 2008-03-27) to not create "mytag", which
should only be created and verified at the end in an earlier test
added in 446c6faec6 (New tests and en-passant modifications to mktag.,
2006-07-29).

While we're at it let's prevent a similar logic error from creeping
into the test by asserting that "mytag" doesn't exist before we create
it. Let's do this by moving the test to use "update-ref", instead of
our own homebrew ad-hoc refstore update.

We're not really testing for anything yet by creating the tag at the
end here. A subsequent commit will change that.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index c542c3e1a8e..bb300d567db 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -222,7 +222,7 @@ EOF
 
 test_expect_success \
     'allow empty tag email' \
-    'git mktag <tag.sig >.git/refs/tags/mytag'
+    'git mktag <tag.sig'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -348,16 +348,9 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 
 EOF
 
-test_expect_success \
-    'create valid tag' \
-    'git mktag <tag.sig >.git/refs/tags/mytag'
-
-############################################################
-# 25. check mytag
-
-test_expect_success \
-    'check mytag' \
-    'git tag -l | grep mytag'
-
+test_expect_success 'create valid tag' '
+	git mktag <tag.sig >hash &&
+	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero)
+'
 
 test_done
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 09/23] mktag tests: run "fsck" after creating "mytag"
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (9 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 08/23] mktag tests: don't create "mytag" twice Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 10/23] mktag tests: stress test whitespace handling Ævar Arnfjörð Bjarmason
                                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change the last test in the file to run an "fsck --strict" after
creating the tag at the end.

We're just doing this for good measure to check that fsck behaves as
expected now that there's finally a reference for our valid tag. Other
tests going to be checking this elsewhere, but it's nice to cover all
the edge cases in this test to make it as self-contained as possible.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index bb300d567db..048000cda9a 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -350,7 +350,8 @@ EOF
 
 test_expect_success 'create valid tag' '
 	git mktag <tag.sig >hash &&
-	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero)
+	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero) &&
+	git fsck --strict
 '
 
 test_done
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 10/23] mktag tests: stress test whitespace handling
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (10 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 09/23] mktag tests: run "fsck" after creating "mytag" Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 11/23] mktag tests: test "hash-object" compatibility Ævar Arnfjörð Bjarmason
                                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Add tests for a couple of whitespace edge cases around the header/body
boundary.

I consider the requirement for a blank line before the empty body a
bug, it's a long-standing regression which goes against the command's
documented behavior. This bug will be addressed in a follow-up change.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 048000cda9a..661b62f0912 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -337,6 +337,42 @@ EOF
 check_verify_failure 'detect invalid header entry' \
 	'^error: char.*: trailing garbage in tag header$'
 
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+
+this line comes after an extra newline
+EOF
+
+test_expect_success 'allow extra newlines at start of body' '
+	git mktag <tag.sig
+'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+
+EOF
+
+test_expect_success 'require a blank line before an empty body (1)' '
+	git mktag <tag.sig
+'
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+tagger T A Gger <tagger@example.com> 1206478233 -0500
+EOF
+
+check_verify_failure 'require a blank line before an empty body (2)' \
+	'^error: char.*: trailing garbage in tag header$'
+
 ############################################################
 # 24. create valid tag
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 11/23] mktag tests: test "hash-object" compatibility
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (11 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 10/23] mktag tests: stress test whitespace handling Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 12/23] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
                                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change all the successful "mktag" tests to test that "hash-object"
produces the same hash for the input, and that fsck passes for
both.

This tests e.g. that "mktag" doesn't trim its input or otherwise munge
it in a way that "hash-object" doesn't.

Since we're doing an "fsck --strict" here at the end let's incorporate
the creation of the "mytag" name into this test, removing the
special-case at the end of the file.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 661b62f0912..47380292223 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -19,6 +19,19 @@ check_verify_failure () {
 	'
 }
 
+test_expect_mktag_success() {
+	test_expect_success "$1" '
+		git hash-object -t tag -w --stdin <tag.sig >expected &&
+		git fsck --strict &&
+
+		git mktag <tag.sig >hash &&
+		test_cmp expected hash &&
+		test_when_finished "git update-ref -d refs/tags/mytag $(cat hash)" &&
+		git update-ref refs/tags/mytag $(cat hash) $(test_oid zero) &&
+		git fsck --strict	
+	'
+}
+
 ###########################################################
 # first create a commit, so we have a valid object/type
 # for the tag.
@@ -220,9 +233,7 @@ tagger T A Gger <> 0 +0000
 
 EOF
 
-test_expect_success \
-    'allow empty tag email' \
-    'git mktag <tag.sig'
+test_expect_mktag_success 'allow empty tag email'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -347,9 +358,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 this line comes after an extra newline
 EOF
 
-test_expect_success 'allow extra newlines at start of body' '
-	git mktag <tag.sig
-'
+test_expect_mktag_success 'allow extra newlines at start of body'
 
 cat >tag.sig <<EOF
 object $head
@@ -359,9 +368,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 
 EOF
 
-test_expect_success 'require a blank line before an empty body (1)' '
-	git mktag <tag.sig
-'
+test_expect_mktag_success 'require a blank line before an empty body (1)'
 
 cat >tag.sig <<EOF
 object $head
@@ -384,10 +391,6 @@ tagger T A Gger <tagger@example.com> 1206478233 -0500
 
 EOF
 
-test_expect_success 'create valid tag' '
-	git mktag <tag.sig >hash &&
-	git update-ref refs/tags/mytag $(cat hash) $(test_oid zero) &&
-	git fsck --strict
-'
+test_expect_mktag_success 'create valid tag object'
 
 test_done
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 12/23] mktag tests: improve verify_object() test coverage
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (12 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 11/23] mktag tests: test "hash-object" compatibility Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-10 13:21                   ` SZEDER Gábor
  2021-01-05 19:42                 ` [PATCH v5 13/23] mktag tests: test verify_object() with replaced objects Ævar Arnfjörð Bjarmason
                                   ` (10 subsequent siblings)
  24 siblings, 1 reply; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

The verify_object() function in "mktag.c" is tasked with ensuring that
our tag refers to a valid object.

The existing test for this might fail because it was also testing that
"type taggg" didn't refer to a valid object type (it should be "type
tag"), or because we referred to a valid object but got the type
wrong.

Let's split these tests up, so we're testing all combinations of a
non-existing object and in invalid/wrong "type" lines.

We need to provide GIT_TEST_GETTEXT_POISON=false here because the
"invalid object type" error is emitted by
parse_loose_header_extended(), which has that message already marked
for translation. Another option would be to use test_i18ngrep, but I
prefer always running the test, not skipping it under gettext poison
testing.

I'm not testing this in combination with "git replace". That'll be
done in a subsequent commit.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 40 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 47380292223..ced540035d4 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -14,7 +14,8 @@ test_description='git mktag: tag object verify test'
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		test_must_fail git mktag <tag.sig 2>message &&
+		test_must_fail env GIT_TEST_GETTEXT_POISON=false \
+			git mktag <tag.sig 2>message &&
 		grep "$expect" message
 	'
 }
@@ -136,19 +137,52 @@ check_verify_failure '"type" line type-name length check' \
 	'^error: char.*: type too long$'
 
 ############################################################
-#  9. verify object (SHA1/type) check
+#  9. verify object (hash/type) check
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
+type tag
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
+	'^error: char7: could not verify object.*$'
+
+cat >tag.sig <<EOF
+object $head
 type tagggg
 tag mytag
 tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure 'verify object (SHA1/type) check' \
+check_verify_failure 'verify object (hash/type) check -- made-up type, valid object' \
+	'^fatal: invalid object type'
+
+cat >tag.sig <<EOF
+object $(test_oid deadbeef)
+type tagggg
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
 	'^error: char7: could not verify object.*$'
 
+cat >tag.sig <<EOF
+object $head
+type tree
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
+	'^error: char7: could not verify object'
+
 ############################################################
 # 10. verify tag-name check
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 13/23] mktag tests: test verify_object() with replaced objects
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (13 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 12/23] mktag tests: improve verify_object() test coverage Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 14/23] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
                                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Add tests to demonstrate what "mktag" does in the face of replaced
objects.

There was an existing test for replaced objects fed to "mktag" added
in cc400f50112 (mktag: call "check_sha1_signature" with the
replacement sha1, 2009-01-23), but that one only tests a
commit->commit mapping. Not a mapping to a different type as like
we're also testing for here. We could remove the "mktag" test in
t6050-replace.sh now if the created tag wasn't being used by a
subsequent "fsck" test.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3800-mktag.sh | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index ced540035d4..fbaf648491f 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -38,7 +38,11 @@ test_expect_mktag_success() {
 # for the tag.
 test_expect_success 'setup' '
 	test_commit A &&
-	head=$(git rev-parse --verify HEAD)
+	test_commit B &&
+	head=$(git rev-parse --verify HEAD) &&
+	head_parent=$(git rev-parse --verify HEAD~) &&
+	tree=$(git rev-parse HEAD^{tree}) &&
+	blob=$(git rev-parse --verify HEAD:B.t)
 '
 
 ############################################################
@@ -180,6 +184,35 @@ tagger . <> 0 +0000
 
 EOF
 
+check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
+	'^error: char7: could not verify object'
+
+############################################################
+#  9.5. verify object (hash/type) check -- replacement
+
+test_expect_success 'setup replacement of commit -> commit and tree -> blob' '
+	git replace $head_parent $head &&
+	git replace -f $tree $blob
+'
+
+cat >tag.sig <<EOF
+object $head_parent
+type commit
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
+test_expect_mktag_success 'tag to a commit replaced by another commit'
+
+cat >tag.sig <<EOF
+object $tree
+type tree
+tag mytag
+tagger . <> 0 +0000
+
+EOF
+
 check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
 	'^error: char7: could not verify object'
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 14/23] mktag: use default strbuf_read() hint
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (14 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 13/23] mktag tests: test verify_object() with replaced objects Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 15/23] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
                                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change the hardcoded hint of 2^12 to 0. The default strbuf hint is
perfectly fine here, and the only reason we were hardcoding it is
because it survived migration from a pre-strbuf fixed-sized buffer.

See fd17f5b5f77 (Replace all read_fd use with strbuf_read, and get rid
of it., 2007-09-10) for that migration.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 4982d3a93ef..ff7ac8e0e5d 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,7 +161,7 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 4096) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0) {
 		die_errno("could not read from stdin");
 	}
 
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 15/23] mktag: remove redundant braces in one-line body "if"
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (15 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 14/23] mktag: use default strbuf_read() hint Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 16/23] mktag: use puts(str) instead of printf("%s\n", str) Ævar Arnfjörð Bjarmason
                                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

This minor stylistic churn is usually something we'd avoid, but if we
don't do this then the file after changes in subsequent commits will
only have this minor style inconsistency, so let's change this while
we're at it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index ff7ac8e0e5d..97ca5f28b1b 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -161,9 +161,8 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (argc != 1)
 		usage("git mktag");
 
-	if (strbuf_read(&buf, 0, 0) < 0) {
+	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
-	}
 
 	/* Verify it for some basic sanity: it needs to start with
 	   "object <sha1>\ntype\ntagger " */
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 16/23] mktag: use puts(str) instead of printf("%s\n", str)
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (16 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 15/23] mktag: remove redundant braces in one-line body "if" Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 17/23] mktag: use fsck instead of custom verify_tag() Ævar Arnfjörð Bjarmason
                                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

This introduces no functional change, but refactors the print-out of
the hash at the end to do the same thing with less code.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 builtin/mktag.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/mktag.c b/builtin/mktag.c
index 97ca5f28b1b..d89a3c201de 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -173,6 +173,6 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 		die("unable to write tag file");
 
 	strbuf_release(&buf);
-	printf("%s\n", oid_to_hex(&result));
+	puts(oid_to_hex(&result));
 	return 0;
 }
-- 
2.29.2.222.g5d2a92d10f8


^ permalink raw reply	[flat|nested] 185+ messages in thread

* [PATCH v5 17/23] mktag: use fsck instead of custom verify_tag()
  2020-12-23  1:35               ` [PATCH v4 00/20] make "mktag" use fsck_tag() & more Ævar Arnfjörð Bjarmason
                                   ` (17 preceding siblings ...)
  2021-01-05 19:42                 ` [PATCH v5 16/23] mktag: use puts(str) instead of printf("%s\n", str) Ævar Arnfjörð Bjarmason
@ 2021-01-05 19:42                 ` Ævar Arnfjörð Bjarmason
  2021-01-05 19:42                 ` [PATCH v5 18/23] fsck: make fsck_config() re-usable Ævar Arnfjörð Bjarmason
                                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 185+ messages in thread
From: Ævar Arnfjörð Bjarmason @ 2021-01-05 19:42 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, brian m . carlson, Eric Sunshine,
	Johannes Schindelin, SZEDER Gábor,
	Ævar Arnfjörð Bjarmason

Change the validation logic in "mktag" to use fsck's fsck_tag()
instead of its own custom parser. Curiously the logic for both dates
back to the same commit[1]. Let's unify them so we're not maintaining
two sets functions to verify that a tag is OK.

The behavior of fsck_tag() and the old "mktag" code being removed here
is different in few aspects.

I think it makes sense to remove some of those checks, namely:

 A. fsck only cares that the timezone matches [-+][0-9]{4}. The mktag
    code disallowed values larger than 1400.

    Yes there's currently no timezone with a greater offset[2], but
    since we allow any number of non-offical timezones (e.g. +1234)
    passing this through seems fine. Git also won't break in the
    future if e.g. French Polynesia decides it needs to outdo the Line
    Islands when it comes to timezone extravagance.

 B. fsck allows missing author names such as "tagger <email>", mktag
    wouldn't, but would allow e.g. "tagger [2 spaces] <email>" (but
    not "tagger [1 space] <email>"). Now we allow all of these.

 C. Like B, but "mktag" disallowed spaces in the <email> part, fsck
    allows it.

In some ways fsck_tag() is stricter than "mktag" was, namely:

 D. fsck disallows zero-padded dates, but mktag didn't care. So
    e.g. the timestamp "0000000000 +0000" produces an error now. A
    test in "t1006-cat-file.sh" relied on this, it's been changed to
    use "hash-object" (without fsck) instead.

There was one check I deemed worth keeping by porting it over to
fsck_tag():

 E. "mktag" did not allow any custom headers, and by extension (as an
    empty commit is allowed) also forbade an extra stray trailing
    newline after the headers it knew about.

    Add a new check in the "ignore" category to fsck and use it. This
    somewhat abuses the facility added in efaba7cc77f (fsck:
    optionally ignore specific fsck issues completely, 2015-06-22).

    This is somewhat of hack, but probably the least invasive change
    we can make here. The fsck command will shuffle these categories
    around, e.g. under --strict the "info" becomes a "warn" and "warn"
    becomes "error". Existing users of fsck's (and others,
    e.g. index-pack) --strict option rely on this.

    So we need to put something into a category that'll be ignored by
    all existing users of the API. Pretending that
    fsck.extraHeaderEntry=error ("ignore" by default) was set serves
    to do this for us.

1. ec4465adb38 (Add "tag" objects that can be used to sign other
   objects., 2005-04-25)

2. https://en.wikipedia.org/wiki/List_of_UTC_time_offsets

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 Documentation/git-mktag.txt |   9 +-
 builtin/mktag.c             | 196 +++++++++---------------------------
 fsck.c                      |  32 +++++-
 fsck.h                      |   9 ++
 t/t1006-cat-file.sh         |   2 +-
 t/t3800-mktag.sh            |  63 ++++++------
 6 files changed, 127 insertions(+), 184 deletions(-)

diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 20af1915e9e..fa070e21a0b 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -25,7 +25,14 @@ write a tag found in `my-tag`:
     git hash-object -t tag -w --stdin <my-tag
 
 The difference is that mktag will die before writing the tag if the
-tag doesn't pass a sanity check.
+tag doesn't pass a linkgit:git-fsck[1] check.
+
+The "fsck" check done mktag is stricter than what linkgit:git-fsck[1]
+would run by default in that all `fsck.<msg-id>` messages are promoted
+from warnings to errors (so e.g. a missing "tagger" line is an error).
+
+Extra headers in the object are also an error under mktag, but ignored
+by linkgit:git-fsck[1]
 
 Tag Format
 ----------
diff --git a/builtin/mktag.c b/builtin/mktag.c
index d89a3c201de..4dd35bc79e2 100644
--- a/builtin/mktag.c
+++ b/builtin/mktag.c
@@ -2,160 +2,60 @@
 #include "tag.h"
 #include "replace-object.h"
 #include "object-store.h"
+#include "fsck.h"
 
-/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
- * "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
- *
- * The first four lines are guaranteed to be at least 83 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, "tag .\n" at 6 bytes is the shortest
- * single-character-tag line, and "tagger . <> 0 +0000\n" at 20 bytes is
- * the shortest possible tagger-line.
- */
-
-/*
- * We refuse to tag something we can't verify. Just because.
- */
-static int verify_object(const struct object_id *oid, const char *expected_type)
+static int mktag_fsck_error_func(struct fsck_options *o,
+				 const struct object_id *oid,
+				 enum object_type object_type,
+				 int msg_type, const char *message)
 {
-	int ret = -1;
-	enum object_type type;
-	unsigned long size;
-	void *buffer = read_object_file(oid, &type, &size);
-	const struct object_id *repl = lookup_replace_object(the_repository, oid);
-
-	if (buffer) {
-		if (type == type_from_string(expected_type)) {
-			ret = check_object_signature(the_repository, repl,
-						     buffer, size,
-						     expected_type);
-		}
-		free(buffer);
+	switch (msg_type) {
+	case FSCK_WARN:
+	case FSCK_ERROR:
+		/*
+		 * We treat both warnings and errors as errors, things
+		 * like missing "tagger" lines are "only" warnings
+		 * under fsck, we've always considered them an error.
+		 */
+		fprintf_ln(stderr, "error: tag input does not pass fsck: %s", message);
+		return 1;
+	default:
+		BUG("%d (FSCK_IGNORE?) should never trigger this callback",
+		    msg_type);
 	}
-	return ret;
 }
 
-static int verify_tag(char *buffer, unsigned long size)
+static int verify_object_in_tag(struct object_id *tagged_oid, int *tagged_type)
 {
-	int typelen;
-	char type[20];
-	struct object_id oid;
-	const char *object, *type_line, *tag_line, *tagger_line, *lb, *rb, *p;
-	size_t len;
-
-	if (size < 84)
-		return error("wanna fool me ? you obviously got the size wrong !");
-
-	buffer[size] = 0;
-
-	/* Verify object line */
-	object = buffer;
-	if (memcmp(object, "object ", 7))
-		return error("char%d: does not start with \"object \"", 0);
-
-	if (parse_oid_hex(object + 7, &oid, &p))
-		return error("char%d: could not get SHA1 hash", 7);
-
-	/* Verify type line */
-	type_line = p + 1;
-	if (memcmp(type_line - 1, "\ntype ", 6))
-		return error("char%d: could not find \"\\ntype \"", 47);
-
-	/* Verify tag-line */
-	tag_line = strchr(type_line, '\n');
-	if (!tag_line)
-		return error("char%"PRIuMAX": could not find next \"\\n\"",
-				(uintmax_t) (type_line - buffer));
-	tag_line++;
-	if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
-		return error("char%"PRIuMAX": no \"tag \" found",
-				(uintmax_t) (tag_line - buffer));
-
-	/* Get the actual type */
-	typelen = tag_line - type_line - strlen("type \n");
-	if (typelen >= sizeof(type))
-		return error("char%"PRIuMAX": type too long",
-				(uintmax_t) (type_line+5 - buffer));
-
-	memcpy(type, type_line+5, typelen);
-	type[typelen] = 0;
-
-	/* Verify that the object matches */
-	if (verify_object(&oid, type))
-		return error("char%d: could not verify object %s", 7, oid_to_hex(&oid));
-
-	/* Verify the tag-name: we don't allow control characters or spaces in it */
-	tag_line += 4;
-	for (;;) {
-		unsigned char c = *tag_line++;
-		if (c == '\n')
-			break;
-		if (c > ' ')
-			continue;
-		return error("char%"PRIuMAX": could not verify tag name",
-				(uintmax_t) (tag_line - buffer));
-	}
-
-	/* Verify the tagger line */
-	tagger_line = tag_line;
-
-	if (memcmp(tagger_line, "tagger ", 7))
-		return error("char%"PRIuMAX": could not find \"tagger \"",
-			(uintmax_t) (tagger_line - buffer));
-
-	/*
-	 * Check for correct form for name and email
-	 * i.e. " <" followed by "> " on _this_ line
-	 * No angle brackets within the name or email address fields.
-	 * No spaces within the email address field.
-	 */
-	tagger_line += 7;
-	if (!(lb = strstr(tagger_line, " <")) || !(rb = strstr(lb+2, "> ")) ||
-		strpbrk(tagger_line, "<>\n") != lb+1 ||
-		strpbrk(lb+2, "><\n ") != rb)
-		return error("char%"PRIuMAX": malformed tagger field",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* Check for author name, at least one character, space is acceptable */
-	if (lb == tagger_line)
-		return error("char%"PRIuMAX": missing tagger name",
-			(uintmax_t) (tagger_line - buffer));
-
-	/* timestamp, 1 or more digits followed by space */
-	tagger_line = rb + 2;
-	if (!(len = strspn(tagger_line, "0123456789")))
-		return error("char%"PRIuMAX": missing tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += len;
-	if (*tagger_line != ' ')
-		return error("char%"PRIuMAX": malformed tag timestamp",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line++;
-
-	/* timezone, 5 digits [+-]hhmm, max. 1400 */
-	if (!((tagger_line[0] == '+' || tagger_line[0] == '-') &&
-	      strspn(tagger_line+1, "0123456789") == 4 &&
-	      tagger_line[5] == '\n' && atoi(tagger_line+1) <= 1400))
-		return error("char%"PRIuMAX": malformed tag timezone",
-			(uintmax_t) (tagger_line - buffer));
-	tagger_line += 6;
-
-	/* Verify the blank line separating the header from the body */
-	if (*tagger_line != '\n')
-		return error("char%"PRIuMAX": trailing garbage in tag header",
-			(uintmax_t) (tagger_line - buffer));
+	int ret;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+	const struct object_id *repl;
+
+	buffer = read_object_file(tagged_oid, &type, &size);
+	if (!buffer)
+		die("could not read tagged object '%s'",
+		    oid_to_hex(tagged_oid));
+	if (type != *tagged_type)
+		die("object '%s' tagged as '%s', but is a '%s' type",
+		    oid_to_hex(tagged_oid),
+		    type_name(*tagged_type), type_name(type));
+
+	repl = lookup_replace_object(the_repository, tagged_oid);
+	ret = check_object_signature(the_repository, repl,
+				     buffer, size, type_name(*tagged_type));
+	free(buffer);
 
-	/* The actual stuff afterwards we don't care about.. */
-	return 0;
+	return ret;
 }
 
 int cmd_mktag(int argc, const char **argv, const char *prefix)
 {
 	struct strbuf buf = STRBUF_INIT;
+	struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
+	struct object_id tagged_oid;
+	int tagged_type;
 	struct object_id result;
 
 	if (argc != 1)
@@ -164,10 +64,14 @@ int cmd_mktag(int argc, const char **argv, const char *prefix)
 	if (strbuf_read(&buf, 0, 0) < 0)
 		die_errno("could not read from stdin");
 
-	/* Verify it for some basic sanity: it needs to start with
-	   "object <sha1>\ntype\ntagger " */
-	if (verify_tag(buf.buf, buf.len) < 0)
-		die("invalid tag signature file");
+	fsck_options.error_func = mktag_fsck_error_func;
+	fsck_set_msg_type(&fsck_options, "extraheaderentry", "warn");
+	if (fsck_tag_standalone(NULL, buf.buf, buf.len, &fsck_options,
+				&tagged_oid, &tagged_type))
+		die("tag on stdin did not pass our strict fsck check");
+
+	if (verify_object_in_tag(&tagged_oid, &tagged_type))
+		die("tag on stdin did not refer to a valid object");
 
 	if (write_object_file(buf.buf, buf.len, tag_type, &result) < 0)
 		die("unable to write tag file");
diff --git a/fsck.c b/fsck.c
index f82e2fe9e30..bed5e20e03b 100644
--- a/fsck.c
+++ b/fsck.c
@@ -80,7 +80,9 @@ static struct oidset gitmodules_done = OIDSET_INIT;
 	/* infos (reported as warnings, but ignored by default) */ \
 	FUNC(GITMODULES_PARSE, INFO) \
 	FUNC(BAD_TAG_NAME, INFO) \
-	FUNC(MISSING_TAGGER_ENTRY, INFO)
+	FUNC(MISSING_TAGGER_ENTRY, INFO) \
+	/* ignored (elevated when requested) */ \
+	FUNC(EXTRA_HEADER_ENTRY, IGNORE)
 
 #define MSG_ID(id, msg_type) FSCK_MSG_##id,
 enum fsck_msg_id {
@@ -911,6 +913,16 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		    unsigned long size, struct fsck_options *options)
 {
 	struct object_id tagged_oid;
+	int tagged_type;
+	return fsck_tag_standalone(oid, buffer, size, options, &tagged_oid,
+				   &tagged_type);
+}
+
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tagged_type)
+{
 	int ret = 0;
 	char *eol;
 	struct strbuf sb = STRBUF_INIT;
@@ -924,7 +936,7 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_OBJECT, "invalid format - expected 'object' line");
 		goto done;
 	}
-	if (parse_oid_hex(buffer, &tagged_oid, &p) || *p != '\n') {
+	if (parse_oid_hex(buffer, tagged_oid, &p) || *p != '\n') {
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_OBJECT_SHA1, "invalid 'object' line format - bad sha1");
 		if (ret)
 			goto done;
@@ -940,7 +952,8 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_MISSING_TYPE, "invalid format - unexpected end after 'type' line");
 		goto done;
 	}
-	if (type_from_string_gently(buffer, eol - buffer, 1) < 0)
+	*tagged_type = type_from_string_gently(buffer, eol - buffer, 1);
+	if (*tagged_type < 0)
 		ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_TYPE, "invalid 'type' value");
 	if (ret)
 		goto done;
@@ -975,6 +988,19 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
 	else
 		ret = fsck_ident(&buffer, oid, OBJ_TAG, options);
 
+	if (!starts_with(buffer, "\n")) {
+		/*
+		 * The verify_headers() check will allow
+		 * e.g. "[...]tagger <tagger>\nsome
+		 * garbage\n\nmessage" to pass, thinking "some
+		 * garbage" could be a custom header. E.g. "mktag"
+		 * doesn't want any unknown headers.
+		 */
+		ret = report(options, oid, OBJ_TAG, FSCK_MSG_EXTRA_HEADER_ENTRY, "invalid format - extra header(s) after 'tagger'");
+		if (ret)
+			goto done;
+	}
+
 done:
 	strbuf_release(&sb);
 	return ret;
diff --git a/fsck.h b/fsck.h
index 69cf715e798..29ee4c45e87 100644
--- a/fsck.h
+++ b/fsck.h
@@ -62,6 +62,15 @@ int fsck_walk(struct object *obj, void *data, struct fsck_options *options);
 int fsck_object(struct object *obj, void *data, unsigned long size,
 	struct fsck_options *options);
 
+/*
+ * fsck a tag, and pass info about it back to the caller. This is
+ * exposed fsck_object() internals for git-mktag(1).
+ */
+int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
+			unsigned long size, struct fsck_options *options,
+			struct object_id *tagged_oid,
+			int *tag_type);
+
 /*
  * Some fsck checks are context-dependent, and may end up queued; run this
  * after completing all fsck_object() calls in order to resolve any remaining
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 2f501d2dc94..5d2dc99b74a 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -166,7 +166,7 @@ tag_content="$tag_header_without_timestamp 0000000000 +0000
 
 $tag_description"
 
-tag_sha1=$(echo_without_newline "$tag_content" | git mktag)
+tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w)
 tag_size=$(strlen "$tag_content")
 
 run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index fbaf648491f..0e2a9a883ba 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -53,7 +53,7 @@ too short for a tag
 EOF
 
 check_verify_failure 'Tag object length check' \
-	'^error: .*size wrong.*$'
+	'^error:.* missingObject:'
 
 ############################################################
 #  2. object line label check
@@ -66,7 +66,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line label check' '^error: char0: .*"object "$'
+check_verify_failure '"object" line label check' '^error:.* missingObject:'
 
 ############################################################
 #  3. object line hash check
@@ -79,7 +79,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$'
+check_verify_failure '"object" line check' '^error:.* badObjectSha1:'
 
 ############################################################
 #  4. type line label check
@@ -92,7 +92,7 @@ tagger . <> 0 +0000
 
 EOF
 
-check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
+check_verify_failure '"type" line label check' '^error:.* missingTypeEntry:'
 
 ############################################################
 #  5. type line eol check
@@ -100,7 +100,7 @@ check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$'
 echo "object $head" >tag.sig
 printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
 
-check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$'
+check_verify_failure '"type" line eol check' '^error:.* unterminatedHeader:'
 
 ############################################################
 #  6. tag line label check #1
@@ -114,7 +114,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure '"tag" line label check #1' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* missingTagEntry:'
 
 ############################################################
 #  7. tag line label check #2
@@ -126,7 +126,7 @@ tag
 EOF
 
 check_verify_failure '"tag" line label check #2' \
-	'^error: char.*: no "tag " found$'
+	'^error:.* badType:'
 
 ############################################################
 #  8. type line type-name length check
@@ -138,7 +138,7 @@ tag mytag
 EOF
 
 check_verify_failure '"type" line type-name length check' \
-	'^error: char.*: type too long$'
+	'^error:.* badType:'
 
 ############################################################
 #  9. verify object (hash/type) check
@@ -152,7 +152,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- correct type, nonexisting object' \
-	'^error: char7: could not verify object.*$'
+	'^fatal: could not read tagged object'
 
 cat >tag.sig <<EOF
 object $head
@@ -163,7 +163,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- made-up type, valid object' \
-	'^fatal: invalid object type'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $(test_oid deadbeef)
@@ -174,7 +174,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- made-up type, nonexisting object' \
-	'^error: char7: could not verify object.*$'
+	'^error:.* badType:'
 
 cat >tag.sig <<EOF
 object $head
@@ -185,7 +185,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
-	'^error: char7: could not verify object'
+	'^fatal: object.*tagged as.*tree.*but is.*commit'
 
 ############################################################
 #  9.5. verify object (hash/type) check -- replacement
@@ -214,7 +214,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify object (hash/type) check -- mismatched type, valid object' \
-	'^error: char7: could not verify object'
+	'^fatal: object.*tagged as.*tree.*but is.*blob'
 
 ############################################################
 # 10. verify tag-name check
@@ -228,7 +228,7 @@ tagger . <> 0 +0000
 EOF
 
 check_verify_failure 'verify tag-name check' \
-	'^error: char.*: could not verify tag name$'
+	'^error:.* badTagName:'
 
 ############################################################
 # 11. tagger line label check #1
@@ -242,7 +242,7 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #1' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
 # 12. tagger line label check #2
@@ -257,10 +257,10 @@ This is filler
 EOF
 
 check_verify_failure '"tagger" line label check #2' \
-	'^error: char.*: could not find "tagger "$'
+	'^error:.* missingTaggerEntry:'
 
 ############################################################
-# 13. disallow missing tag author name
+# 13. allow missing tag author name like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -271,8 +271,7 @@ tagger  <> 0 +0000
 This is filler
 EOF
 
-check_verify_failure 'disallow missing tag author name' \
-	'^error: char.*: missing tagger name$'
+test_expect_mktag_success 'allow missing tag author name'
 
 ############################################################
 # 14. disallow missing tag author name
@@ -287,7 +286,7 @@ tagger T A Gger <
 EOF
 
 check_verify_failure 'disallow malformed tagger' \
-	'^error: char.*: malformed tagger field$'
+	'^error:.* badEmail:'
 
 ############################################################
 # 15. allow empty tag email
@@ -303,7 +302,7 @@ EOF
 test_expect_mktag_success 'allow empty tag email'
 
 ############################################################
-# 16. disallow spaces in tag email
+# 16. allow spaces in tag email like fsck
 
 cat >tag.sig <<EOF
 object $head
@@ -313,8 +312,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000
 
 EOF
 
-check_verify_failure 'disallow spaces in tag email' \
-	'^error: char.*: malformed tagger field$'
+test_expect_mktag_success 'allow spaces in tag email like fsck'
 
 ############################################################
 # 17. disallow missing tag timestamp
@@ -328,7 +326,7 @@ tagger T A Gger <tagger@example.com>__
 EOF
 
 check_verify_failure 'disallow missing tag timestamp' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 18. detect invalid tag timestamp1
@@ -342,7 +340,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008
 EOF
 
 check_verify_failure 'detect invalid tag timestamp1' \
-	'^error: char.*: missing tag timestamp$'
+	'^error:.* badDate:'
 
 ############################################################
 # 19. detect invalid tag timestamp2
@@ -356,7 +354,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500
 EOF
 
 check_verify_failure 'detect invalid tag timestamp2' \
-	'^error: char.*: malformed tag timestamp$'
+	'^error:.* badDate:'
 
 ###