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 <sandals@crustytoothpaste.net> Acked-by: Eric Wong <e@80x24.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
ff508e227c
commit
94b2ee1aee
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user