Skip to content

Commit 94b2ee1

Browse files
bk2204gitster
authored andcommitted
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 <[email protected]> Acked-by: Eric Wong <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ff508e2 commit 94b2ee1

File tree

5 files changed

+48
-45
lines changed

5 files changed

+48
-45
lines changed

git-svn.perl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,10 +2008,10 @@ sub cmt_sha2rev_batch {
20082008
print $out $sha, "\n";
20092009

20102010
while (my $line = <$in>) {
2011-
if ($first && $line =~ /^[[:xdigit:]]{40}\smissing$/) {
2011+
if ($first && $line =~ /^$::oid\smissing$/) {
20122012
last;
20132013
} elsif ($first &&
2014-
$line =~ /^[[:xdigit:]]{40}\scommit\s(\d+)$/) {
2014+
$line =~ /^$::oid\scommit\s(\d+)$/) {
20152015
$first = 0;
20162016
$size = $1;
20172017
next;

perl/Git/SVN.pm

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package Git::SVN;
22
use strict;
33
use warnings;
44
use Fcntl qw/:DEFAULT :seek/;
5-
use constant rev_map_fmt => 'NH40';
5+
use constant rev_map_fmt => 'NH*';
66
use vars qw/$_no_metadata
77
$_repack $_repack_flags $_use_svm_props $_head
88
$_use_svnsync_props $no_reuse_existing
@@ -2087,10 +2087,10 @@ sub rebuild_from_rev_db {
20872087
open my $fh, '<', $path or croak "open: $!";
20882088
binmode $fh or croak "binmode: $!";
20892089
while (<$fh>) {
2090-
length($_) == 41 or croak "inconsistent size in ($_) != 41";
2090+
length($_) == $::oid_length + 1 or croak "inconsistent size in ($_)";
20912091
chomp($_);
20922092
++$r;
2093-
next if $_ eq ('0' x 40);
2093+
next if $_ eq ('0' x $::oid_length);
20942094
$self->rev_map_set($r, $_);
20952095
print "r$r = $_\n";
20962096
}
@@ -2196,9 +2196,9 @@ sub rebuild {
21962196
# (mainly tags)
21972197
#
21982198
# The format is this:
2199-
# - 24 bytes for every record,
2199+
# - 24 or 36 bytes for every record,
22002200
# * 4 bytes for the integer representing an SVN revision number
2201-
# * 20 bytes representing the sha1 of a git commit
2201+
# * 20 or 32 bytes representing the oid of a git commit
22022202
# - No empty padding records like the old format
22032203
# (except the last record, which can be overwritten)
22042204
# - new records are written append-only since SVN revision numbers
@@ -2207,46 +2207,47 @@ sub rebuild {
22072207
# - Piping the file to xxd -c24 is a good way of dumping it for
22082208
# viewing or editing (piped back through xxd -r), should the need
22092209
# ever arise.
2210-
# - The last record can be padding revision with an all-zero sha1
2210+
# - The last record can be padding revision with an all-zero oid
22112211
# This is used to optimize fetch performance when using multiple
22122212
# "fetch" directives in .git/config
22132213
#
22142214
# These files are disposable unless noMetadata or useSvmProps is set
22152215

22162216
sub _rev_map_set {
22172217
my ($fh, $rev, $commit) = @_;
2218+
my $record_size = ($::oid_length / 2) + 4;
22182219

22192220
binmode $fh or croak "binmode: $!";
22202221
my $size = (stat($fh))[7];
2221-
($size % 24) == 0 or croak "inconsistent size: $size";
2222+
($size % $record_size) == 0 or croak "inconsistent size: $size";
22222223

22232224
my $wr_offset = 0;
22242225
if ($size > 0) {
2225-
sysseek($fh, -24, SEEK_END) or croak "seek: $!";
2226-
my $read = sysread($fh, my $buf, 24) or croak "read: $!";
2227-
$read == 24 or croak "read only $read bytes (!= 24)";
2226+
sysseek($fh, -$record_size, SEEK_END) or croak "seek: $!";
2227+
my $read = sysread($fh, my $buf, $record_size) or croak "read: $!";
2228+
$read == $record_size or croak "read only $read bytes (!= $record_size)";
22282229
my ($last_rev, $last_commit) = unpack(rev_map_fmt, $buf);
2229-
if ($last_commit eq ('0' x40)) {
2230-
if ($size >= 48) {
2231-
sysseek($fh, -48, SEEK_END) or croak "seek: $!";
2232-
$read = sysread($fh, $buf, 24) or
2230+
if ($last_commit eq ('0' x $::oid_length)) {
2231+
if ($size >= ($record_size * 2)) {
2232+
sysseek($fh, -($record_size * 2), SEEK_END) or croak "seek: $!";
2233+
$read = sysread($fh, $buf, $record_size) or
22332234
croak "read: $!";
2234-
$read == 24 or
2235-
croak "read only $read bytes (!= 24)";
2235+
$read == $record_size or
2236+
croak "read only $read bytes (!= $record_size)";
22362237
($last_rev, $last_commit) =
22372238
unpack(rev_map_fmt, $buf);
2238-
if ($last_commit eq ('0' x40)) {
2239+
if ($last_commit eq ('0' x $::oid_length)) {
22392240
croak "inconsistent .rev_map\n";
22402241
}
22412242
}
22422243
if ($last_rev >= $rev) {
22432244
croak "last_rev is higher!: $last_rev >= $rev";
22442245
}
2245-
$wr_offset = -24;
2246+
$wr_offset = -$record_size;
22462247
}
22472248
}
22482249
sysseek($fh, $wr_offset, SEEK_END) or croak "seek: $!";
2249-
syswrite($fh, pack(rev_map_fmt, $rev, $commit), 24) == 24 or
2250+
syswrite($fh, pack(rev_map_fmt, $rev, $commit), $record_size) == $record_size or
22502251
croak "write: $!";
22512252
}
22522253

@@ -2271,7 +2272,7 @@ sub mkfile {
22712272
sub rev_map_set {
22722273
my ($self, $rev, $commit, $update_ref, $uuid) = @_;
22732274
defined $commit or die "missing arg3\n";
2274-
length $commit == 40 or die "arg3 must be a full SHA1 hexsum\n";
2275+
$commit =~ /^$::oid$/ or die "arg3 must be a full hex object ID\n";
22752276
my $db = $self->map_path($uuid);
22762277
my $db_lock = "$db.lock";
22772278
my $sigmask;
@@ -2344,29 +2345,30 @@ sub rev_map_max {
23442345

23452346
sub rev_map_max_norebuild {
23462347
my ($self, $want_commit) = @_;
2348+
my $record_size = ($::oid_length / 2) + 4;
23472349
my $map_path = $self->map_path;
23482350
stat $map_path or return $want_commit ? (0, undef) : 0;
23492351
sysopen(my $fh, $map_path, O_RDONLY) or croak "open: $!";
23502352
binmode $fh or croak "binmode: $!";
23512353
my $size = (stat($fh))[7];
2352-
($size % 24) == 0 or croak "inconsistent size: $size";
2354+
($size % $record_size) == 0 or croak "inconsistent size: $size";
23532355

23542356
if ($size == 0) {
23552357
close $fh or croak "close: $!";
23562358
return $want_commit ? (0, undef) : 0;
23572359
}
23582360

2359-
sysseek($fh, -24, SEEK_END) or croak "seek: $!";
2360-
sysread($fh, my $buf, 24) == 24 or croak "read: $!";
2361+
sysseek($fh, -$record_size, SEEK_END) or croak "seek: $!";
2362+
sysread($fh, my $buf, $record_size) == $record_size or croak "read: $!";
23612363
my ($r, $c) = unpack(rev_map_fmt, $buf);
2362-
if ($want_commit && $c eq ('0' x40)) {
2363-
if ($size < 48) {
2364+
if ($want_commit && $c eq ('0' x $::oid_length)) {
2365+
if ($size < $record_size * 2) {
23642366
return $want_commit ? (0, undef) : 0;
23652367
}
2366-
sysseek($fh, -48, SEEK_END) or croak "seek: $!";
2367-
sysread($fh, $buf, 24) == 24 or croak "read: $!";
2368+
sysseek($fh, -($record_size * 2), SEEK_END) or croak "seek: $!";
2369+
sysread($fh, $buf, $record_size) == $record_size or croak "read: $!";
23682370
($r, $c) = unpack(rev_map_fmt, $buf);
2369-
if ($c eq ('0'x40)) {
2371+
if ($c eq ('0' x $::oid_length)) {
23702372
croak "Penultimate record is all-zeroes in $map_path";
23712373
}
23722374
}
@@ -2387,30 +2389,31 @@ sub rev_map_get {
23872389

23882390
sub _rev_map_get {
23892391
my ($fh, $rev) = @_;
2392+
my $record_size = ($::oid_length / 2) + 4;
23902393

23912394
binmode $fh or croak "binmode: $!";
23922395
my $size = (stat($fh))[7];
2393-
($size % 24) == 0 or croak "inconsistent size: $size";
2396+
($size % $record_size) == 0 or croak "inconsistent size: $size";
23942397

23952398
if ($size == 0) {
23962399
return undef;
23972400
}
23982401

2399-
my ($l, $u) = (0, $size - 24);
2402+
my ($l, $u) = (0, $size - $record_size);
24002403
my ($r, $c, $buf);
24012404

24022405
while ($l <= $u) {
2403-
my $i = int(($l/24 + $u/24) / 2) * 24;
2406+
my $i = int(($l/$record_size + $u/$record_size) / 2) * $record_size;
24042407
sysseek($fh, $i, SEEK_SET) or croak "seek: $!";
2405-
sysread($fh, my $buf, 24) == 24 or croak "read: $!";
2408+
sysread($fh, my $buf, $record_size) == $record_size or croak "read: $!";
24062409
my ($r, $c) = unpack(rev_map_fmt, $buf);
24072410

24082411
if ($r < $rev) {
2409-
$l = $i + 24;
2412+
$l = $i + $record_size;
24102413
} elsif ($r > $rev) {
2411-
$u = $i - 24;
2414+
$u = $i - $record_size;
24122415
} else { # $r == $rev
2413-
return $c eq ('0' x 40) ? undef : $c;
2416+
return $c eq ('0' x $::oid_length) ? undef : $c;
24142417
}
24152418
}
24162419
undef;

perl/Git/SVN/Editor.pm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,12 @@ sub T {
400400
($m->{mode_b} !~ /^120/ && $m->{mode_a} =~ /^120/)) {
401401
$self->D({
402402
mode_a => $m->{mode_a}, mode_b => '000000',
403-
sha1_a => $m->{sha1_a}, sha1_b => '0' x 40,
403+
sha1_a => $m->{sha1_a}, sha1_b => '0' x $::oid_length,
404404
chg => 'D', file_b => $m->{file_b}
405405
}, $deletions);
406406
$self->A({
407407
mode_a => '000000', mode_b => $m->{mode_b},
408-
sha1_a => '0' x 40, sha1_b => $m->{sha1_b},
408+
sha1_a => '0' x $::oid_length, sha1_b => $m->{sha1_b},
409409
chg => 'A', file_b => $m->{file_b}
410410
}, $deletions);
411411
return;
@@ -434,7 +434,7 @@ sub _chg_file_get_blob ($$$$) {
434434
$self->change_file_prop($fbat,'svn:special',undef);
435435
}
436436
my $blob = $m->{"sha1_$which"};
437-
return ($fh,) if ($blob =~ /^0{40}$/);
437+
return ($fh,) if ($blob =~ /^0+$/);
438438
my $size = $::_repository->cat_blob($blob, $fh);
439439
croak "Failed to read object $blob" if ($size < 0);
440440
$fh->flush == 0 or croak $!;

perl/Git/SVN/Fetcher.pm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ sub delete_entry {
173173

174174
# remove entire directories.
175175
my ($tree) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
176-
=~ /\A040000 tree ([a-f\d]{40})\t\Q$gpath\E\0/);
176+
=~ /\A040000 tree ($::oid)\t\Q$gpath\E\0/);
177177
if ($tree) {
178178
my ($ls, $ctx) = command_output_pipe(qw/ls-tree
179179
-r --name-only -z/,
@@ -203,7 +203,7 @@ sub open_file {
203203

204204
my $gpath = $self->git_path($path);
205205
($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath")
206-
=~ /\A(\d{6}) blob ([a-f\d]{40})\t\Q$gpath\E\0/);
206+
=~ /\A(\d{6}) blob ($::oid)\t\Q$gpath\E\0/);
207207
unless (defined $mode && defined $blob) {
208208
die "$path was not found in commit $self->{c} (r$rev)\n";
209209
}
@@ -413,7 +413,7 @@ sub close_file {
413413

414414
$hash = $::_repository->hash_and_insert_object(
415415
Git::temp_path($fh));
416-
$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
416+
$hash =~ /^$::oid$/ or die "not an object ID: $hash\n";
417417

418418
Git::temp_release($fb->{base}, 1);
419419
Git::temp_release($fh, 1);

perl/Git/SVN/Ra.pm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,11 +486,11 @@ sub gs_fetch_loop_common {
486486
$reload_ra->() if $ra_invalid;
487487
}
488488
# pre-fill the .rev_db since it'll eventually get filled in
489-
# with '0' x40 if something new gets committed
489+
# with '0' x $oid_length if something new gets committed
490490
foreach my $gs (@$gsv) {
491491
next if $gs->rev_map_max >= $max;
492492
next if defined $gs->rev_map_get($max);
493-
$gs->rev_map_set($max, 0 x40);
493+
$gs->rev_map_set($max, 0 x $::oid_length);
494494
}
495495
foreach my $g (@$globs) {
496496
my $k = "svn-remote.$g->{remote}.$g->{t}-maxRev";

0 commit comments

Comments
 (0)