threads / patch / 15137

patchfilter-branch: Grok special characters in tag names

Subject: [PATCH] filter-branch: Grok special characters in tag names

## tl;dr

6 messages between Aug 21, 2008 and Aug 21, 2008. Diffs are folded; open one to read it.

replies: 5people: 3as markdown or json

Johannes Sixt· Aug 21, 2008, 14:45 UTC · lore

The tag rewriting code used a 'sed' expression to substitute the new tag name into the corresponding field of the annotated tag object. But this is problematic if the tag name contains special characters. In particular, if the tag name contained a slash, then the 'sed' expression had a syntax error. We now protect against this by using 'printf' to assemble the tag header.

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
---
 git-filter-branch.sh     |   12 +++++++-----
 t/t7003-filter-branch.sh |    8 ++++++++
 2 files changed, 15 insertions(+), 5 deletions(-)
Show changes to 2 files +15 −5

git-filter-branch.sh, t/t7003-filter-branch.sh

diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 2688254..81392ad 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -412,15 +412,17 @@ if [ "$filter_tag_name" ]; then
 		echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
 
 		if [ "$type" = "tag" ]; then
-			new_sha1=$(git cat-file tag "$ref" |
+			new_sha1=$( ( printf 'object %s\ntype commit\ntag %s\n' \
+						"$new_sha1" "$new_ref"
+				git cat-file tag "$ref" |
 				sed -n \
 				    -e "1,/^$/{
-					  s/^object .*/object $new_sha1/
-					  s/^type .*/type commit/
-					  s/^tag .*/tag $new_ref/
+					  /^object /d
+					  /^type /d
+					  /^tag /d
 					}" \
 				    -e '/^-----BEGIN PGP SIGNATURE-----/q' \
-				    -e 'p' |
+				    -e 'p' ) |
 				git mktag) ||
 				die "Could not create new tag object for $ref"
 			if git cat-file tag "$ref" | \
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 233254f..95f13a8 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -254,4 +254,12 @@ test_expect_success 'Tag name filtering strips gpg signature' '
 	test_cmp expect actual
 '
 
+test_expect_success 'Tag name filtering allows slashes in tag names' '
+	git tag -m tag-with-slash X/1 &&
+	git cat-file tag X/1 | sed -e s,X/1,X/2, > expect &&
+	git filter-branch -f --tag-name-filter "echo X/2" &&
+	git cat-file tag X/2 > actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.6.0.137.g19b5f8c
Brandon Casey· Aug 21, 2008, 16:38 UTC · re: Johannes Sixt · lore

Re: [PATCH] filter-branch: Grok special characters in tag names

Johannes Sixt wrote:
Show 20 quoted lines
> diff --git a/git-filter-branch.sh b/git-filter-branch.sh
> index 2688254..81392ad 100755
> --- a/git-filter-branch.sh
> +++ b/git-filter-branch.sh
> @@ -412,15 +412,17 @@ if [ "$filter_tag_name" ]; then
>  		echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
>  
>  		if [ "$type" = "tag" ]; then
> -			new_sha1=$(git cat-file tag "$ref" |
> +			new_sha1=$( ( printf 'object %s\ntype commit\ntag %s\n' \
> +						"$new_sha1" "$new_ref"
> +				git cat-file tag "$ref" |
>  				sed -n \
>  				    -e "1,/^$/{
> -					  s/^object .*/object $new_sha1/
> -					  s/^type .*/type commit/
> -					  s/^tag .*/tag $new_ref/
> +					  /^object /d
> +					  /^type /d
> +					  /^tag /d

Junio complained that my initial version of this was fragile which has similarities with the above. Initially, I was blindly changing the first line to contain "object...", second line to "type...", etc.

Would something like the following be equivalent _and_ clearer? Emphasis on "and" because both are necessary, not because I strongly feel it to be so.

Show changes to git-filter-branch.sh +6 −4
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index a324cf0..11c5c04 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -419,9 +419,12 @@ if [ "$filter_tag_name" ]; then
 			new_sha1=$(git cat-file tag "$ref" |
 				sed -n \
 				    -e "1,/^$/{
-					  s/^object .*/object $new_sha1/
-					  s/^type .*/type commit/
-					  s/^tag .*/tag $new_ref/
+					  /^object .*/c\\
+object $new_sha1
+					  /^type .*/c\\
+type commit
+					  /^tag .*/c\\
+tag $new_ref
 					}" \
 				    -e '/^-----BEGIN PGP SIGNATURE-----/q' \
 				    -e 'p' |


-brandon
Johannes Sixt· Aug 21, 2008, 19:07 UTC · re: Brandon Casey · lore

Re: [PATCH] filter-branch: Grok special characters in tag names

On Donnerstag, 21. August 2008, Brandon Casey wrote:
Show 25 quoted lines
> Johannes Sixt wrote:
> > diff --git a/git-filter-branch.sh b/git-filter-branch.sh
> > index 2688254..81392ad 100755
> > --- a/git-filter-branch.sh
> > +++ b/git-filter-branch.sh
> > @@ -412,15 +412,17 @@ if [ "$filter_tag_name" ]; then
> >  		echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
> >
> >  		if [ "$type" = "tag" ]; then
> > -			new_sha1=$(git cat-file tag "$ref" |
> > +			new_sha1=$( ( printf 'object %s\ntype commit\ntag %s\n' \
> > +						"$new_sha1" "$new_ref"
> > +				git cat-file tag "$ref" |
> >  				sed -n \
> >  				    -e "1,/^$/{
> > -					  s/^object .*/object $new_sha1/
> > -					  s/^type .*/type commit/
> > -					  s/^tag .*/tag $new_ref/
> > +					  /^object /d
> > +					  /^type /d
> > +					  /^tag /d
>
> Junio complained that my initial version of this was fragile which has
> similarities with the above. Initially, I was blindly changing the first
> line to contain "object...", second line to "type...", etc.

I don't see what's wrong with that. "object" must be the first line anyway, otherwise git mktag chokes.

Show 23 quoted lines
> Would something like the following be equivalent _and_ clearer? Emphasis on
> "and" because both are necessary, not because I strongly feel it to be so.
>
> diff --git a/git-filter-branch.sh b/git-filter-branch.sh
> index a324cf0..11c5c04 100755
> --- a/git-filter-branch.sh
> +++ b/git-filter-branch.sh
> @@ -419,9 +419,12 @@ if [ "$filter_tag_name" ]; then
>  			new_sha1=$(git cat-file tag "$ref" |
>  				sed -n \
>  				    -e "1,/^$/{
> -					  s/^object .*/object $new_sha1/
> -					  s/^type .*/type commit/
> -					  s/^tag .*/tag $new_ref/
> +					  /^object .*/c\\
> +object $new_sha1
> +					  /^type .*/c\\
> +type commit
> +					  /^tag .*/c\\
> +tag $new_ref
>  					}" \
>  				    -e '/^-----BEGIN PGP SIGNATURE-----/q' \
>  				    -e 'p' |
This looks fine, too. (The '.*' in /^foo .*/c\\ is unnecessary.)
-- Hannes
Junio C Hamano· Aug 21, 2008, 20:26 UTC · re: Brandon Casey · lore

Re: [PATCH] filter-branch: Grok special characters in tag names

Brandon Casey <casey@nrlssc.navy.mil> writes:
> Junio complained that my initial version of this was fragile which has
> similarities with the above. Initially, I was blindly changing the first line
> to contain "object...", second line to "type...", etc.

Was it more about not limiting the munging to only the header part? In any case, I think what Hannes has in the patch is fine (although I did not look the lines that follow outside the context).

> Would something like the following be equivalent _and_ clearer? Emphasis
> on "and" because both are necessary, not because I strongly feel it to
> be so.

I was bitten by a/i/c followed by literal text that behave differently with various implementations of sed, and learned to stay away from the construct long time ago. Things might have gotten better these days, but old habit and gut-reaction is hard to shake off.

Brandon Casey· Aug 21, 2008, 21:34 UTC · re: Junio C Hamano · lore

Re: [PATCH] filter-branch: Grok special characters in tag names

Junio C Hamano wrote:
Show 7 quoted lines
> Brandon Casey <casey@nrlssc.navy.mil> writes:
> 
>> Junio complained that my initial version of this was fragile which has
>> similarities with the above. Initially, I was blindly changing the first line
>> to contain "object...", second line to "type...", etc.
> 
> Was it more about not limiting the munging to only the header part?
No. I originally had something like
   1c\object $new_sha1
   2c\tag commit
   ...

blindly changing line one to "object ...", line two to "tag ..." etc. That aspect is what you commented about. So it would have modified the proper parts of a well-formed tag.

I took your comments to be concerned with future proofing or dealing with a corrupt/flawed tag (allowing the flaws to propagate so mktag would error out), but you didn't state that explicitly.

You also educated me about addresses like 1,/regex/ which was used to limit the munging to only the header part.

> In
> any case, I think what Hannes has in the patch is fine (although I did not
> look the lines that follow outside the context).
That's fine.
-brandon

← back to recent threads