From 62814dfd171f71bf901155d40834d846d83c184f Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 19 Jun 2020 22:39:34 +0000 Subject: [PATCH 01/14] t9109: make test hash independent Instead of stripping off the first 41 characters of git log output, let's just strip off the first space-separated component, which will work for any size hash. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9109-git-svn-multi-glob.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/t/t9109-git-svn-multi-glob.sh b/t/t9109-git-svn-multi-glob.sh index c1e7542a37..648dcee1ea 100755 --- a/t/t9109-git-svn-multi-glob.sh +++ b/t/t9109-git-svn-multi-glob.sh @@ -48,7 +48,7 @@ test_expect_success 'test refspec globbing' ' "tags/*/src/a:refs/remotes/tags/*" && git svn multi-fetch && git log --pretty=oneline refs/remotes/tags/end >actual && - sed -e "s/^.\{41\}//" actual >output.end && + cut -d" " -f2- actual >output.end && test_cmp expect.end output.end && test "$(git rev-parse refs/remotes/tags/end~1)" = \ "$(git rev-parse refs/remotes/branches/v1/start)" && @@ -84,7 +84,7 @@ test_expect_success 'test left-hand-side only globbing' ' test $(git rev-parse refs/remotes/two/tags/end~3) = \ $(git rev-parse refs/remotes/two/branches/v1/start) && git log --pretty=oneline refs/remotes/two/tags/end >actual && - sed -e "s/^.\{41\}//" actual >output.two && + cut -d" " -f2- actual >output.two && test_cmp expect.two output.two ' cat > expect.four <actual && - sed -e "s/^.\{41\}//" actual >output.four && + cut -d" " -f2- actual >output.four && test_cmp expect.four output.four ' From 5aa68775408646753534dee69004745802487877 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 19 Jun 2020 22:39:35 +0000 Subject: [PATCH 02/14] t9168: make test hash independent Instead of stripping off the first 41 characters of git log output, let's just strip off the first space-separated component, which will work for any size hash. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9168-git-svn-partially-globbed-names.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t/t9168-git-svn-partially-globbed-names.sh b/t/t9168-git-svn-partially-globbed-names.sh index bdf6e84999..854b3419b2 100755 --- a/t/t9168-git-svn-partially-globbed-names.sh +++ b/t/t9168-git-svn-partially-globbed-names.sh @@ -49,7 +49,7 @@ test_expect_success 'test refspec prefixed globbing' ' "tags/t_*/src/a:refs/remotes/tags/t_*" && git svn multi-fetch && git log --pretty=oneline refs/remotes/tags/t_end >actual && - sed -e "s/^.\{41\}//" actual >output.end && + cut -d" " -f2- actual >output.end && test_cmp expect.end output.end && test "$(git rev-parse refs/remotes/tags/t_end~1)" = \ "$(git rev-parse refs/remotes/branches/b_start)" && @@ -87,7 +87,7 @@ test_expect_success 'test left-hand-side only prefixed globbing' ' test $(git rev-parse refs/remotes/two/tags/t_end~3) = \ $(git rev-parse refs/remotes/two/branches/b_start) && git log --pretty=oneline refs/remotes/two/tags/t_end >actual && - sed -e "s/^.\{41\}//" actual >output.two && + cut -d" " -f2- actual >output.two && test_cmp expect.two output.two ' @@ -129,7 +129,7 @@ test_expect_success 'test prefixed globs match just prefix' ' test $(git rev-parse refs/remotes/three/tags/t_~1) = \ $(git rev-parse refs/remotes/three/branches/b_) && git log --pretty=oneline refs/remotes/three/tags/t_ >actual && - sed -e "s/^.\{41\}//" actual >output.three && + cut -d" " -f2- actual >output.three && test_cmp expect.three output.three ' @@ -199,7 +199,7 @@ test_expect_success 'test globbing in the middle of the word' ' test $(git rev-parse refs/remotes/five/tags/fghij~1) = \ $(git rev-parse refs/remotes/five/branches/abcde) && git log --pretty=oneline refs/remotes/five/tags/fghij >actual && - sed -e "s/^.\{41\}//" actual >output.five && + cut -d" " -f2- actual >output.five && test_cmp expect.five output.five ' From 606b9749c6ac864863705b643dbc8193fef09040 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 19 Jun 2020 22:39:36 +0000 Subject: [PATCH 03/14] t9108: make test hash independent Instead of stripping off the first 41 characters of git log output, let's just strip off the first space-separated component, which will work for any size hash. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9108-git-svn-glob.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh index 6990f64364..d5939d4753 100755 --- a/t/t9108-git-svn-glob.sh +++ b/t/t9108-git-svn-glob.sh @@ -48,7 +48,7 @@ test_expect_success 'test refspec globbing' ' "tags/*/src/a:refs/remotes/tags/*" && git svn multi-fetch && git log --pretty=oneline refs/remotes/tags/end >actual && - sed -e "s/^.\{41\}//" actual >output.end && + cut -d" " -f2- actual >output.end && test_cmp expect.end output.end && test "$(git rev-parse refs/remotes/tags/end~1)" = \ "$(git rev-parse refs/remotes/branches/start)" && @@ -84,7 +84,7 @@ test_expect_success 'test left-hand-side only globbing' ' test $(git rev-parse refs/remotes/two/tags/end~3) = \ $(git rev-parse refs/remotes/two/branches/start) && git log --pretty=oneline refs/remotes/two/tags/end >actual && - sed -e "s/^.\{41\}//" actual >output.two && + cut -d" " -f2- actual >output.two && test_cmp expect.two output.two ' From 407527ba448f2916dbd8a56f63735b386e6eb30b Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 19 Jun 2020 22:39:37 +0000 Subject: [PATCH 04/14] t9100: make test work with SHA-256 Compute the relevant tree objects for SHA-256 and use those when appropriate instead of using the SHA-1 ones. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9100-git-svn-basic.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 2c309a57d9..9f2d19ecc4 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -208,9 +208,10 @@ name='check imported tree checksums expected tree checksums' rm -f expected if test_have_prereq UTF8 then - echo tree dc68b14b733e4ec85b04ab6f712340edc5dc936e > expected + echo tree dc68b14b733e4ec85b04ab6f712340edc5dc936e > expected.sha1 + echo tree b95b55b29d771f5eb73aa9b9d52d02fe11a2538c2feb0829f754ce20a91d98eb > expected.sha256 fi -cat >> expected <<\EOF +cat >> expected.sha1 <<\EOF tree c3322890dcf74901f32d216f05c5044f670ce632 tree d3ccd5035feafd17b030c5732e7808cc49122853 tree d03e1630363d4881e68929d532746b20b0986b83 @@ -220,8 +221,20 @@ tree 149d63cd5878155c846e8c55d7d8487de283f89e tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4 EOF +cat >> expected.sha256 <<\EOF +tree 8d12756699d0b5b110514240a0ff141f6cbf8891fd69ab05e5594196fb437c9f +tree 8187168d33f7d4ccb8c1cc6e99532810aaccb47658f35d19b3803072d1128d7a +tree 74e535d85da8ee25eb23d7b506790c5ab3ccdb1ba0826bd57625ed44ef361650 +tree 6fd7dd963e3cdca0cbd6368ed3cfcc8037cc154d2e7719d9d369a0952364fd95 +tree 1fd6cec6aa95102d69266e20419bb62ec2a06372d614b9850ef23ff204103bb4 +tree 6fd7dd963e3cdca0cbd6368ed3cfcc8037cc154d2e7719d9d369a0952364fd95 +tree deb2b7ac79cd8ce6f52af6a5a0a08691e94ba74a2ed55966bb27dbec551730eb +tree 59e2e936761188476a7752034e8aa0a822b34050c8504b0dfd946407f4bc9215 +EOF -test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp expected a" +test_expect_success POSIXPERM,SYMLINKS "$name" ' + test_cmp expected.$(test_oid algo) a +' test_expect_success 'exit if remote refs are ambigious' ' git config --add svn-remote.svn.fetch \ From bbe0616cd85f30804d62d3fb6e183e9c5ff81b9d Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 19 Jun 2020 22:39:38 +0000 Subject: [PATCH 05/14] t9104: make hash size independent The size of a record in the database used by git svn is four bytes plus the length of the binary hash. Instead of hard-coding 24, compute this value based on the size of the hash in use. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9104-git-svn-follow-parent.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index 5e0ad19177..67eed2fefc 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -161,6 +161,7 @@ test_expect_success "track initial change if it was only made to parent" ' ' test_expect_success "follow-parent is atomic" ' + record_size=$(($(test_oid rawsz) + 4)) && ( cd wc && svn_cmd up && @@ -186,7 +187,7 @@ test_expect_success "follow-parent is atomic" ' mkdir -p "$GIT_DIR"/svn/refs/remotes/flunk@18 && rev_map=$(cd "$GIT_DIR"/svn/refs/remotes/stunk && ls .rev_map*) && dd if="$GIT_DIR"/svn/refs/remotes/stunk/$rev_map \ - of="$GIT_DIR"/svn/refs/remotes/flunk@18/$rev_map bs=24 count=1 && + of="$GIT_DIR"/svn/refs/remotes/flunk@18/$rev_map bs=$record_size count=1 && rm -rf "$GIT_DIR"/svn/refs/remotes/stunk && git svn init --minimize-url -i flunk "$svnrepo"/flunk && git svn fetch -i flunk && From 3e04b6e1b672a2b38b1e2a7094bcc600e76959b1 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Fri, 19 Jun 2020 22:39:39 +0000 Subject: [PATCH 06/14] t9101: make hash independent Instead of hard-coding the object ID for our test .gitignore file, let's compute it. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/t9101-git-svn-props.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index c26c4b0927..8b5681dd68 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -160,11 +160,13 @@ cat >create-ignore.expect <<\EOF /no-such-file* EOF -cat >create-ignore-index.expect <<\EOF -100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 .gitignore -100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/.gitignore -100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/nested/.gitignore -100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0 deeply/nested/directory/.gitignore +expectoid=$(git hash-object create-ignore.expect) + +cat >create-ignore-index.expect < Date: Mon, 22 Jun 2020 18:04:11 +0000 Subject: [PATCH 07/14] t/lib-git-svn: make hash size independent The record size used in the git svn storage is four bytes plus the length of the binary hash. Pass the hash length into our Perl invocation and use it to compute the size of the records. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- t/lib-git-svn.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index 7d248e6588..547eb3c31a 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -78,21 +78,24 @@ maybe_start_httpd () { } convert_to_rev_db () { - perl -w -- - "$@" <<\EOF + perl -w -- - "$(test_oid rawsz)" "$@" <<\EOF use strict; +my $oidlen = shift; @ARGV == 2 or die "usage: convert_to_rev_db "; +my $record_size = $oidlen + 4; +my $hexlen = $oidlen * 2; open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]"; open my $rd, '<', $ARGV[0] or die "$!: couldn't open: $ARGV[0]"; my $size = (stat($rd))[7]; -($size % 24) == 0 or die "Inconsistent size: $size"; -while (sysread($rd, my $buf, 24) == 24) { - my ($r, $c) = unpack('NH40', $buf); - my $offset = $r * 41; +($size % $record_size) == 0 or die "Inconsistent size: $size"; +while (sysread($rd, my $buf, $record_size) == $record_size) { + my ($r, $c) = unpack("NH$hexlen", $buf); + my $offset = $r * ($hexlen + 1); seek $wr, 0, 2 or die $!; my $pos = tell $wr; if ($pos < $offset) { - for (1 .. (($offset - $pos) / 41)) { - print $wr (('0' x 40),"\n") or die $!; + for (1 .. (($offset - $pos) / ($hexlen + 1))) { + print $wr (('0' x $hexlen),"\n") or die $!; } } seek $wr, $offset, 0 or die $!; From 9ab33150a0d14089d0496dd8354d4a969e849571 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:12 +0000 Subject: [PATCH 08/14] perl: create and switch variables for hash constants git-svn has several variables for SHA-1 constants, including short hash values and full length hash values. Since these are no longer SHA-1 specific, let's start them with "oid" instead of "sha1". Add a constant, oid_length, which is the length of the hash algorithm in use in hex. We use the hex version because overwhelmingly that's what's used by git-svn. We don't currently set oid_length based on the repository algorithm, but we will in a future commit. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 14 ++++++++------ perl/Git/SVN.pm | 10 +++++----- perl/Git/SVN/Editor.pm | 2 +- perl/Git/SVN/Log.pm | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 4aa208ff5f..7c735cebd3 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -5,7 +5,8 @@ use 5.008; use warnings; use strict; use vars qw/ $AUTHOR $VERSION - $sha1 $sha1_short $_revision $_repository + $oid $oid_short $oid_length + $_revision $_repository $_q $_authors $_authors_prog %users/; $AUTHOR = 'Eric Wong '; $VERSION = '@@GIT_VERSION@@'; @@ -103,8 +104,9 @@ sub _req_svn { } } -$sha1 = qr/[a-f\d]{40}/; -$sha1_short = qr/[a-f\d]{4,40}/; +$oid = qr/(?:[a-f\d]{40}(?:[a-f\d]{24})?)/; +$oid_short = qr/[a-f\d]{4,64}/; +$oid_length = 40; my ($_stdin, $_help, $_edit, $_message, $_file, $_branch_dest, $_template, $_shared, @@ -582,7 +584,7 @@ sub cmd_set_tree { print "Reading from stdin...\n"; @commits = (); while () { - if (/\b($sha1_short)\b/o) { + if (/\b($oid_short)\b/o) { unshift @commits, $1; } } @@ -1831,7 +1833,7 @@ sub get_tree_from_treeish { if ($type eq 'commit') { $expected = (grep /^tree /, command(qw/cat-file commit/, $treeish))[0]; - ($expected) = ($expected =~ /^tree ($sha1)$/o); + ($expected) = ($expected =~ /^tree ($oid)$/o); die "Unable to get tree from $treeish\n" unless $expected; } elsif ($type eq 'tree') { $expected = $treeish; @@ -2036,7 +2038,7 @@ sub working_head_info { my $hash; my %max; while (<$fh>) { - if ( m{^commit ($::sha1)$} ) { + if ( m{^commit ($::oid)$} ) { unshift @$refs, $hash if $hash and $refs; $hash = $1; next; diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index 4b28b87784..fcf1e3bb5e 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -874,7 +874,7 @@ sub assert_index_clean { command_noisy('read-tree', $treeish) unless -e $self->{index}; my $x = command_oneline('write-tree'); my ($y) = (command(qw/cat-file commit/, $treeish) =~ - /^tree ($::sha1)/mo); + /^tree ($::oid)/mo); return if $y eq $x; warn "Index mismatch: $y != $x\nrereading $treeish\n"; @@ -1020,7 +1020,7 @@ sub do_git_commit { $tree = $self->tmp_index_do(sub { command_oneline('write-tree') }); } - die "Tree is not a valid sha1: $tree\n" if $tree !~ /^$::sha1$/o; + die "Tree is not a valid oid $tree\n" if $tree !~ /^$::oid$/o; my @exec = ('git', 'commit-tree', $tree); foreach ($self->get_commit_parents($log_entry)) { @@ -1048,8 +1048,8 @@ sub do_git_commit { close $out_fh or croak $!; waitpid $pid, 0; croak $? if $?; - if ($commit !~ /^$::sha1$/o) { - die "Failed to commit, invalid sha1: $commit\n"; + if ($commit !~ /^$::oid$/o) { + die "Failed to commit, invalid oid: $commit\n"; } $self->rev_map_set($log_entry->{revision}, $commit, 1); @@ -2150,7 +2150,7 @@ sub rebuild { my $svn_uuid = $self->rewrite_uuid || $self->ra_uuid; my $c; while (<$log>) { - if ( m{^commit ($::sha1)$} ) { + if ( m{^commit ($::oid)$} ) { $c = $1; next; } diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm index 0df16ed726..70b6d78cd9 100644 --- a/perl/Git/SVN/Editor.pm +++ b/perl/Git/SVN/Editor.pm @@ -63,7 +63,7 @@ sub generate_diff { my @mods; while (defined($_ = get_record($diff_fh, "\0"))) { if ($state eq 'meta' && /^:(\d{6})\s(\d{6})\s - ($::sha1)\s($::sha1)\s + ($::oid)\s($::oid)\s ([MTCRAD])\d*$/xo) { push @mods, { mode_a => $1, mode_b => $2, sha1_a => $3, sha1_b => $4, diff --git a/perl/Git/SVN/Log.pm b/perl/Git/SVN/Log.pm index 664105357c..3858fcf27d 100644 --- a/perl/Git/SVN/Log.pm +++ b/perl/Git/SVN/Log.pm @@ -285,7 +285,7 @@ sub cmd_show_log { my (@k, $c, $d, $stat); my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/; while (<$log>) { - if (/^${esc_color}commit (?:- )?($::sha1_short)/o) { + if (/^${esc_color}commit (?:- )?($::oid_short)/o) { my $cmt = $1; if ($c && cmt_showable($c) && $c->{r} != $r_last) { $r_last = $c->{r}; From ff508e227c881acf6016c88ddde8158664ee18e3 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:13 +0000 Subject: [PATCH 09/14] perl: make Git::IndexInfo work with SHA-256 Most of the Git modules, git-svn excepted, don't know anything about the hash algorithm and mostly work. However, when we're printing an all-zero object ID in Git::IndexInfo, we need to know the hash length. Since we don't want to change the API to have that information passed in, let's query the config to find the hash algorithm and compute the right value. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- perl/Git/IndexInfo.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/perl/Git/IndexInfo.pm b/perl/Git/IndexInfo.pm index a43108c985..2a7b4908f3 100644 --- a/perl/Git/IndexInfo.pm +++ b/perl/Git/IndexInfo.pm @@ -5,13 +5,15 @@ use Git qw/command_input_pipe command_close_pipe/; sub new { my ($class) = @_; + my $hash_algo = Git::config('extensions.objectformat') || 'sha1'; my ($gui, $ctx) = command_input_pipe(qw/update-index -z --index-info/); - bless { gui => $gui, ctx => $ctx, nr => 0}, $class; + bless { gui => $gui, ctx => $ctx, nr => 0, hash_algo => $hash_algo}, $class; } sub remove { my ($self, $path) = @_; - if (print { $self->{gui} } '0 ', 0 x 40, "\t", $path, "\0") { + my $length = $self->{hash_algo} eq 'sha256' ? 64 : 40; + if (print { $self->{gui} } '0 ', 0 x $length, "\t", $path, "\0") { return ++$self->{nr}; } undef; From 94b2ee1aeeb2dbec8383118db74d5c5c0a95476f Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:14 +0000 Subject: [PATCH 10/14] perl: make SVN code hash independent There are several places throughout git-svn that use various hard-coded constants. For matching object IDs, use the $oid variable. Compute the record size we use for our revision storage based on the object ID. When parsing the revision map format, use a wildcard in the pack format since we know that the data we're parsing is always exactly the record size. This lets us continue to use a constant for the pack format. Finally, update several comments to reflect the fact that an object ID may be of one of multiple sizes. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 4 +-- perl/Git/SVN.pm | 73 +++++++++++++++++++++-------------------- perl/Git/SVN/Editor.pm | 6 ++-- perl/Git/SVN/Fetcher.pm | 6 ++-- perl/Git/SVN/Ra.pm | 4 +-- 5 files changed, 48 insertions(+), 45 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 7c735cebd3..00276c051b 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -2008,10 +2008,10 @@ sub cmt_sha2rev_batch { print $out $sha, "\n"; while (my $line = <$in>) { - if ($first && $line =~ /^[[:xdigit:]]{40}\smissing$/) { + if ($first && $line =~ /^$::oid\smissing$/) { last; } elsif ($first && - $line =~ /^[[:xdigit:]]{40}\scommit\s(\d+)$/) { + $line =~ /^$::oid\scommit\s(\d+)$/) { $first = 0; $size = $1; next; diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index fcf1e3bb5e..d1c352f92b 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -2,7 +2,7 @@ package Git::SVN; use strict; use warnings; use Fcntl qw/:DEFAULT :seek/; -use constant rev_map_fmt => 'NH40'; +use constant rev_map_fmt => 'NH*'; use vars qw/$_no_metadata $_repack $_repack_flags $_use_svm_props $_head $_use_svnsync_props $no_reuse_existing @@ -2087,10 +2087,10 @@ sub rebuild_from_rev_db { open my $fh, '<', $path or croak "open: $!"; binmode $fh or croak "binmode: $!"; while (<$fh>) { - length($_) == 41 or croak "inconsistent size in ($_) != 41"; + length($_) == $::oid_length + 1 or croak "inconsistent size in ($_)"; chomp($_); ++$r; - next if $_ eq ('0' x 40); + next if $_ eq ('0' x $::oid_length); $self->rev_map_set($r, $_); print "r$r = $_\n"; } @@ -2196,9 +2196,9 @@ sub rebuild { # (mainly tags) # # The format is this: -# - 24 bytes for every record, +# - 24 or 36 bytes for every record, # * 4 bytes for the integer representing an SVN revision number -# * 20 bytes representing the sha1 of a git commit +# * 20 or 32 bytes representing the oid of a git commit # - No empty padding records like the old format # (except the last record, which can be overwritten) # - new records are written append-only since SVN revision numbers @@ -2207,7 +2207,7 @@ sub rebuild { # - Piping the file to xxd -c24 is a good way of dumping it for # viewing or editing (piped back through xxd -r), should the need # ever arise. -# - The last record can be padding revision with an all-zero sha1 +# - The last record can be padding revision with an all-zero oid # This is used to optimize fetch performance when using multiple # "fetch" directives in .git/config # @@ -2215,38 +2215,39 @@ sub rebuild { sub _rev_map_set { my ($fh, $rev, $commit) = @_; + my $record_size = ($::oid_length / 2) + 4; binmode $fh or croak "binmode: $!"; my $size = (stat($fh))[7]; - ($size % 24) == 0 or croak "inconsistent size: $size"; + ($size % $record_size) == 0 or croak "inconsistent size: $size"; my $wr_offset = 0; if ($size > 0) { - sysseek($fh, -24, SEEK_END) or croak "seek: $!"; - my $read = sysread($fh, my $buf, 24) or croak "read: $!"; - $read == 24 or croak "read only $read bytes (!= 24)"; + sysseek($fh, -$record_size, SEEK_END) or croak "seek: $!"; + my $read = sysread($fh, my $buf, $record_size) or croak "read: $!"; + $read == $record_size or croak "read only $read bytes (!= $record_size)"; my ($last_rev, $last_commit) = unpack(rev_map_fmt, $buf); - if ($last_commit eq ('0' x40)) { - if ($size >= 48) { - sysseek($fh, -48, SEEK_END) or croak "seek: $!"; - $read = sysread($fh, $buf, 24) or + if ($last_commit eq ('0' x $::oid_length)) { + if ($size >= ($record_size * 2)) { + sysseek($fh, -($record_size * 2), SEEK_END) or croak "seek: $!"; + $read = sysread($fh, $buf, $record_size) or croak "read: $!"; - $read == 24 or - croak "read only $read bytes (!= 24)"; + $read == $record_size or + croak "read only $read bytes (!= $record_size)"; ($last_rev, $last_commit) = unpack(rev_map_fmt, $buf); - if ($last_commit eq ('0' x40)) { + if ($last_commit eq ('0' x $::oid_length)) { croak "inconsistent .rev_map\n"; } } if ($last_rev >= $rev) { croak "last_rev is higher!: $last_rev >= $rev"; } - $wr_offset = -24; + $wr_offset = -$record_size; } } sysseek($fh, $wr_offset, SEEK_END) or croak "seek: $!"; - syswrite($fh, pack(rev_map_fmt, $rev, $commit), 24) == 24 or + syswrite($fh, pack(rev_map_fmt, $rev, $commit), $record_size) == $record_size or croak "write: $!"; } @@ -2271,7 +2272,7 @@ sub mkfile { sub rev_map_set { my ($self, $rev, $commit, $update_ref, $uuid) = @_; defined $commit or die "missing arg3\n"; - length $commit == 40 or die "arg3 must be a full SHA1 hexsum\n"; + $commit =~ /^$::oid$/ or die "arg3 must be a full hex object ID\n"; my $db = $self->map_path($uuid); my $db_lock = "$db.lock"; my $sigmask; @@ -2344,29 +2345,30 @@ sub rev_map_max { sub rev_map_max_norebuild { my ($self, $want_commit) = @_; + my $record_size = ($::oid_length / 2) + 4; my $map_path = $self->map_path; stat $map_path or return $want_commit ? (0, undef) : 0; sysopen(my $fh, $map_path, O_RDONLY) or croak "open: $!"; binmode $fh or croak "binmode: $!"; my $size = (stat($fh))[7]; - ($size % 24) == 0 or croak "inconsistent size: $size"; + ($size % $record_size) == 0 or croak "inconsistent size: $size"; if ($size == 0) { close $fh or croak "close: $!"; return $want_commit ? (0, undef) : 0; } - sysseek($fh, -24, SEEK_END) or croak "seek: $!"; - sysread($fh, my $buf, 24) == 24 or croak "read: $!"; + sysseek($fh, -$record_size, SEEK_END) or croak "seek: $!"; + sysread($fh, my $buf, $record_size) == $record_size or croak "read: $!"; my ($r, $c) = unpack(rev_map_fmt, $buf); - if ($want_commit && $c eq ('0' x40)) { - if ($size < 48) { + if ($want_commit && $c eq ('0' x $::oid_length)) { + if ($size < $record_size * 2) { return $want_commit ? (0, undef) : 0; } - sysseek($fh, -48, SEEK_END) or croak "seek: $!"; - sysread($fh, $buf, 24) == 24 or croak "read: $!"; + sysseek($fh, -($record_size * 2), SEEK_END) or croak "seek: $!"; + sysread($fh, $buf, $record_size) == $record_size or croak "read: $!"; ($r, $c) = unpack(rev_map_fmt, $buf); - if ($c eq ('0'x40)) { + if ($c eq ('0' x $::oid_length)) { croak "Penultimate record is all-zeroes in $map_path"; } } @@ -2387,30 +2389,31 @@ sub rev_map_get { sub _rev_map_get { my ($fh, $rev) = @_; + my $record_size = ($::oid_length / 2) + 4; binmode $fh or croak "binmode: $!"; my $size = (stat($fh))[7]; - ($size % 24) == 0 or croak "inconsistent size: $size"; + ($size % $record_size) == 0 or croak "inconsistent size: $size"; if ($size == 0) { return undef; } - my ($l, $u) = (0, $size - 24); + my ($l, $u) = (0, $size - $record_size); my ($r, $c, $buf); while ($l <= $u) { - my $i = int(($l/24 + $u/24) / 2) * 24; + my $i = int(($l/$record_size + $u/$record_size) / 2) * $record_size; sysseek($fh, $i, SEEK_SET) or croak "seek: $!"; - sysread($fh, my $buf, 24) == 24 or croak "read: $!"; + sysread($fh, my $buf, $record_size) == $record_size or croak "read: $!"; my ($r, $c) = unpack(rev_map_fmt, $buf); if ($r < $rev) { - $l = $i + 24; + $l = $i + $record_size; } elsif ($r > $rev) { - $u = $i - 24; + $u = $i - $record_size; } else { # $r == $rev - return $c eq ('0' x 40) ? undef : $c; + return $c eq ('0' x $::oid_length) ? undef : $c; } } undef; diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm index 70b6d78cd9..c961444d4c 100644 --- a/perl/Git/SVN/Editor.pm +++ b/perl/Git/SVN/Editor.pm @@ -400,12 +400,12 @@ sub T { ($m->{mode_b} !~ /^120/ && $m->{mode_a} =~ /^120/)) { $self->D({ mode_a => $m->{mode_a}, mode_b => '000000', - sha1_a => $m->{sha1_a}, sha1_b => '0' x 40, + sha1_a => $m->{sha1_a}, sha1_b => '0' x $::oid_length, chg => 'D', file_b => $m->{file_b} }, $deletions); $self->A({ mode_a => '000000', mode_b => $m->{mode_b}, - sha1_a => '0' x 40, sha1_b => $m->{sha1_b}, + sha1_a => '0' x $::oid_length, sha1_b => $m->{sha1_b}, chg => 'A', file_b => $m->{file_b} }, $deletions); return; @@ -434,7 +434,7 @@ sub _chg_file_get_blob ($$$$) { $self->change_file_prop($fbat,'svn:special',undef); } my $blob = $m->{"sha1_$which"}; - return ($fh,) if ($blob =~ /^0{40}$/); + return ($fh,) if ($blob =~ /^0+$/); my $size = $::_repository->cat_blob($blob, $fh); croak "Failed to read object $blob" if ($size < 0); $fh->flush == 0 or croak $!; diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm index 64e900a0e9..729e5337df 100644 --- a/perl/Git/SVN/Fetcher.pm +++ b/perl/Git/SVN/Fetcher.pm @@ -173,7 +173,7 @@ sub delete_entry { # remove entire directories. my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath") - =~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/); + =~ /\A040000 tree ($::oid)\t\Q$gpath\E\0/); if ($tree) { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, @@ -203,7 +203,7 @@ sub open_file { my $gpath = $self->git_path($path); ($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath") - =~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/); + =~ /\A(\d{6}) blob ($::oid)\t\Q$gpath\E\0/); unless (defined $mode && defined $blob) { die "$path was not found in commit $self->{c} (r$rev)\n"; } @@ -413,7 +413,7 @@ sub close_file { $hash = $::_repository->hash_and_insert_object( Git::temp_path($fh)); - $hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n"; + $hash =~ /^$::oid$/ or die "not an object ID: $hash\n"; Git::temp_release($fb->{base}, 1); Git::temp_release($fh, 1); diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm index 56ad9870bc..2cfe055a9a 100644 --- a/perl/Git/SVN/Ra.pm +++ b/perl/Git/SVN/Ra.pm @@ -486,11 +486,11 @@ sub gs_fetch_loop_common { $reload_ra->() if $ra_invalid; } # pre-fill the .rev_db since it'll eventually get filled in - # with '0' x40 if something new gets committed + # with '0' x $oid_length if something new gets committed foreach my $gs (@$gsv) { next if $gs->rev_map_max >= $max; next if defined $gs->rev_map_get($max); - $gs->rev_map_set($max, 0 x40); + $gs->rev_map_set($max, 0 x $::oid_length); } foreach my $g (@$globs) { my $k = "svn-remote.$g->{remote}.$g->{t}-maxRev"; From 66eadd119a02aa9a001d44006563b3bd99b41d54 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:15 +0000 Subject: [PATCH 11/14] git-svn: set the OID length based on hash algorithm When reading the configuration or when creating a new repository, load the extensions.objectFormat value and set the object ID length to 64 if it's "sha256". Note that we use the hex length in git-svn because most of our processing is done on hex values, not binary ones. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/git-svn.perl b/git-svn.perl index 00276c051b..58f5a7ac8f 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -500,6 +500,7 @@ sub do_git_init_db { command_noisy('config', "$pfx.preserve-empty-dirs", 'true'); command_noisy('config', "$pfx.placeholder-filename", $$fname); } + load_object_format(); } sub init_subdir { @@ -1977,9 +1978,15 @@ sub read_git_config { } } } + load_object_format(); delete @$opts{@config_only} if @config_only; } +sub load_object_format { + chomp(my $hash = `git config --get extensions.objectformat`); + $::oid_length = 64 if $hash eq 'sha256'; +} + sub extract_metadata { my $id = shift or return (undef, undef, undef); my ($url, $rev, $uuid) = ($id =~ /^\s*git-svn-id:\s+(.*)\@(\d+) From 05ea93d6b2bfb9a45a9019a5cfaba82dc81dc2f3 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:16 +0000 Subject: [PATCH 12/14] git-cvsserver: port to SHA-256 The code of git-cvsserver currently has several hard-coded 20 and 40 constants that are the length of SHA-1. When parsing the configuration file, read the extensions.objectformat configuration setting as well as CVS-related ones and adjust the hash sizes accordingly. Use these computed values in all the places we match object IDs. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-cvsserver.perl | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/git-cvsserver.perl b/git-cvsserver.perl index ae1044273d..f6f3fc192c 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -365,7 +365,7 @@ sub req_Root } foreach my $line ( @gitvars ) { - next unless ( $line =~ /^(gitcvs)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ ); + next unless ( $line =~ /^(gitcvs|extensions)\.(?:(ext|pserver)\.)?([\w-]+)=(.*)$/ ); unless ($2) { $cfg->{$1}{$3} = $4; } else { @@ -392,6 +392,9 @@ sub req_Root $log->nofile(); } + $state->{rawsz} = ($cfg->{'extensions'}{'objectformat'} || 'sha1') eq 'sha256' ? 32 : 20; + $state->{hexsz} = $state->{rawsz} * 2; + return 1; } @@ -1581,7 +1584,7 @@ sub req_ci $parenthash = safe_pipe_capture('git', 'show-ref', '-s', $branchRef); chomp $parenthash; - if ($parenthash !~ /^[0-9a-f]{40}$/) + if ($parenthash !~ /^[0-9a-f]{$state->{hexsz}}$/) { if ( defined($stickyInfo) && defined($stickyInfo->{tag}) ) { @@ -1708,7 +1711,7 @@ sub req_ci chomp($commithash); $log->info("Commit hash : $commithash"); - unless ( $commithash =~ /[a-zA-Z0-9]{40}/ ) + unless ( $commithash =~ /[a-zA-Z0-9]{$state->{hexsz}}/ ) { $log->warn("Commit failed (Invalid commit hash)"); print "error 1 Commit failed (unknown reason)\n"; @@ -2375,7 +2378,7 @@ sub req_annotate print "E ***************\n"; while ( ) { - if (m/^([a-zA-Z0-9]{40})\t\([^\)]*\)(.*)$/i) + if (m/^([a-zA-Z0-9]{$state->{hexsz}})\t\([^\)]*\)(.*)$/i) { my $commithash = $1; my $data = $2; @@ -2852,7 +2855,7 @@ sub transmitfile return; } - die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{40}$/ ); + die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{$state->{hexsz}}$/ ); my $type = safe_pipe_capture('git', 'cat-file', '-t', $filehash); chomp $type; @@ -3042,7 +3045,7 @@ sub ensureWorkTree my $ver = safe_pipe_capture('git', 'show-ref', '-s', "refs/heads/$state->{module}"); chomp $ver; - if ($ver !~ /^[0-9a-f]{40}$/) + if ($ver !~ /^[0-9a-f]{$state->{hexsz}}$/) { $log->warn("Error from git show-ref -s refs/head$state->{module}"); print "error 1 cannot find the current HEAD of module"; @@ -3281,7 +3284,7 @@ sub open_blob_or_die } elsif( $srcType eq "sha1" ) { - unless ( defined ( $name ) and $name =~ /^[a-zA-Z0-9]{40}$/ ) + unless ( defined ( $name ) and $name =~ /^[a-zA-Z0-9]{$state->{hexsz}}$/ ) { $log->warn("Need filehash"); die "Need filehash\n"; @@ -3817,7 +3820,7 @@ sub update chomp $commitsha1; my $commitinfo = ::safe_pipe_capture('git', 'cat-file', 'commit', $self->{module}); - unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ ) + unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{$state->{hexsz}}/ ) { die("Invalid module '$self->{module}'"); } @@ -3957,7 +3960,7 @@ sub update while ( ) { chomp; - unless ( /^:\d{6}\s+([0-7]{6})\s+[a-f0-9]{40}\s+([a-f0-9]{40})\s+(\w)$/o ) + unless ( /^:\d{6}\s+([0-7]{6})\s+[a-f0-9]{$state->{hexsz}}\s+([a-f0-9]{$state->{hexsz}})\s+(\w)$/o ) { die("Couldn't process git-diff-tree line : $_"); } @@ -4625,11 +4628,11 @@ sub getmeta $db_query->execute($filename, $intRev); $meta = $db_query->fetchrow_hashref; } - elsif ( $revision =~ /^2\.1\.1\.2000(\.[1-3][0-9][0-9]){20}$/ ) + elsif ( $revision =~ /^2\.1\.1\.2000(\.[1-3][0-9][0-9]){$state->{rawsz}}$/ ) { my ($commitHash)=($revision=~/^2\.1\.1\.2000(.*)$/); $commitHash=~s/\.([0-9]+)/sprintf("%02x",$1-100)/eg; - if($commitHash=~/^[0-9a-f]{40}$/) + if($commitHash=~/^[0-9a-f]{$state->{hexsz}}$/) { return $self->getMetaFromCommithash($filename,$commitHash); } @@ -4639,7 +4642,7 @@ sub getmeta $log->warning("failed get $revision with commithash=$commitHash"); undef $revision; } - elsif ( $revision =~ /^[0-9a-f]{40}$/ ) + elsif ( $revision =~ /^[0-9a-f]{$state->{hexsz}}$/ ) { # Try DB first. This is mostly only useful for req_annotate(), # which only calls this for stuff that should already be in @@ -4658,7 +4661,7 @@ sub getmeta if(! $meta) { my($revCommit)=$self->lookupCommitRef($revision); - if($revCommit=~/^[0-9a-f]{40}$/) + if($revCommit=~/^[0-9a-f]{$state->{hexsz}}$/) { return $self->getMetaFromCommithash($filename,$revCommit); } @@ -4672,7 +4675,7 @@ sub getmeta else { my($revCommit)=$self->lookupCommitRef($revision); - if($revCommit=~/^[0-9a-f]{40}$/) + if($revCommit=~/^[0-9a-f]{$state->{hexsz}}$/) { return $self->getMetaFromCommithash($filename,$revCommit); } @@ -4767,7 +4770,7 @@ sub getMetaFromCommithash my($fileHash) = ::safe_pipe_capture("git","rev-parse","$revCommit:$filename"); chomp $fileHash; - if(!($fileHash=~/^[0-9a-f]{40}$/)) + if(!($fileHash=~/^[0-9a-f]{$state->{hexsz}}$/)) { die "Invalid fileHash '$fileHash' looking up" ." '$revCommit:$filename'\n"; @@ -4863,7 +4866,7 @@ sub lookupCommitRef $commitHash = ::safe_pipe_capture("git","rev-parse","--verify","--quiet", $self->unescapeRefName($ref)); $commitHash=~s/\s*$//; - if(!($commitHash=~/^[0-9a-f]{40}$/)) + if(!($commitHash=~/^[0-9a-f]{$state->{hexsz}}$/)) { $commitHash=undef; } @@ -4909,7 +4912,7 @@ sub commitmessage my $commithash = shift; my $tablename = $self->tablename("commitmsgs"); - die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{40}$/ ); + die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{$state->{hexsz}}$/ ); my $db_query; $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1); From f3eaa09261c25813c84a0e47ce8a4dd1b9f5b717 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:17 +0000 Subject: [PATCH 13/14] git-cvsimport: port to SHA-256 Instead of calling the function is_sha1, call it is_oid and update it to match either a SHA-1 or a SHA-256 hex object ID. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-cvsimport.perl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 1057f389d3..7bf3c12d67 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -637,9 +637,9 @@ sub getwd() { return $pwd; } -sub is_sha1 { +sub is_oid { my $s = shift; - return $s =~ /^[a-f0-9]{40}$/; + return $s =~ /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/; } sub get_headref ($) { @@ -810,7 +810,7 @@ sub write_tree () { open(my $fh, '-|', qw(git write-tree)) or die "unable to open git write-tree: $!"; chomp(my $tree = <$fh>); - is_sha1($tree) + is_oid($tree) or die "Cannot get tree id ($tree): $!"; close($fh) or die "Error running git write-tree: $?\n"; @@ -896,7 +896,7 @@ sub commit { print "Committed patch $patchset ($branch $commit_date)\n" if $opt_v; chomp(my $cid = <$commit_read>); - is_sha1($cid) or die "Cannot get commit id ($cid): $!\n"; + is_oid($cid) or die "Cannot get commit id ($cid): $!\n"; print "Commit ID $cid\n" if $opt_v; close($commit_read); From 6e9c4d408dfa842b22d612b7a6f1242bba2a5479 Mon Sep 17 00:00:00 2001 From: "brian m. carlson" Date: Mon, 22 Jun 2020 18:04:18 +0000 Subject: [PATCH 14/14] git-cvsexportcommit: port to SHA-256 When we apply a binary patch, we must have the full object ID in the header in order to apply it; without that, any attempt to apply it will fail. If we set GIT_DIR to empty, git apply does not know about the hash algorithm we're using, and consequently any attempt to apply a patch using SHA-256 will fail, since the object ID is the wrong length. The reason we set the GIT_DIR environment variable is because we don't want to modify the index; we just want to know whether the patch applies. Instead, let's just use a temporary file for the index, which will be cleaned up automatically when the object goes out of scope. Additionally, read the configuration for the repository and compute the length of an object ID based on it. Use that when matching object IDs with a regex or computing the all-zeros object ID. Signed-off-by: brian m. carlson Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- git-cvsexportcommit.perl | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl index fc00d5946a..6483d792d3 100755 --- a/git-cvsexportcommit.perl +++ b/git-cvsexportcommit.perl @@ -22,6 +22,10 @@ die "Need at least one commit identifier!" unless @ARGV; my $repo = Git->repository(); $opt_w = $repo->config('cvsexportcommit.cvsdir') unless defined $opt_w; +my $tmpdir = File::Temp->newdir; +my $hash_algo = $repo->config('extensions.objectformat') || 'sha1'; +my $hexsz = $hash_algo eq 'sha256' ? 64 : 40; + if ($opt_w || $opt_W) { # Remember where GIT_DIR is before changing to CVS checkout unless ($ENV{GIT_DIR}) { @@ -96,7 +100,7 @@ foreach my $line (@commit) { } if ($stage eq 'headers') { - if ($line =~ m/^parent (\w{40})$/) { # found a parent + if ($line =~ m/^parent ([0-9a-f]{$hexsz})$/) { # found a parent push @parents, $1; } elsif ($line =~ m/^author (.+) \d+ [-+]\d+$/) { $author = $1; @@ -111,7 +115,7 @@ foreach my $line (@commit) { } } -my $noparent = "0000000000000000000000000000000000000000"; +my $noparent = "0" x $hexsz; if ($parent) { my $found; # double check that it's a valid parent @@ -174,7 +178,7 @@ my $context = $opt_p ? '' : '-C1'; print "Checking if patch will apply\n"; my @stat; -open APPLY, "GIT_DIR= git-apply $context --summary --numstat<.cvsexportcommit.diff|" || die "cannot patch"; +open APPLY, "GIT_INDEX_FILE=$tmpdir/index git-apply $context --summary --numstat<.cvsexportcommit.diff|" || die "cannot patch"; @stat=; close APPLY || die "Cannot patch"; my (@bfiles,@files,@afiles,@dfiles); @@ -329,7 +333,7 @@ print "Applying\n"; if ($opt_W) { system("git checkout -q $commit^0") && die "cannot patch"; } else { - `GIT_DIR= git-apply $context --summary --numstat --apply <.cvsexportcommit.diff` || die "cannot patch"; + `GIT_INDEX_FILE=$tmpdir/index git-apply $context --summary --numstat --apply <.cvsexportcommit.diff` || die "cannot patch"; } print "Patch applied successfully. Adding new files and directories to CVS\n"; @@ -407,7 +411,7 @@ unlink(".cvsexportcommit.diff"); if ($opt_W) { system("git checkout $go_back_to") && die "cannot move back to $go_back_to"; - if (!($go_back_to =~ /^[0-9a-fA-F]{40}$/)) { + if (!($go_back_to =~ /^[0-9a-fA-F]{$hexsz}$/)) { system("git symbolic-ref HEAD $go_back_to") && die "cannot move back to $go_back_to"; }