git-svn: extra safety for noMetadata and useSvmProps users

Make sure we flush our userspace buffers and and fsync(2)
.rev_db information to disk if we use these options because
we really don't want to lose this information.

Also, disallow --use-svm-props and --no-metadata from the
command-line because history will be inconsistent if they're
only used occasionally.  If a user wants to use these options,
they must be set in the config so they're always on.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
Eric Wong
2007-02-11 15:21:24 -08:00
parent 93f2689ccd
commit 97ae091169
2 changed files with 42 additions and 11 deletions

View File

@ -316,17 +316,33 @@ for more information on using GIT_SVN_ID.
config key: svn.followparent config key: svn.followparent
--no-metadata:: svn.noMetadata:
svn-remote.<name>.noMetadata:
This gets rid of the git-svn-id: lines at the end of every commit. This gets rid of the git-svn-id: lines at the end of every commit.
If you lose your .git/svn/git-svn/.rev_db file, git-svn will not If you lose your .git/svn/git-svn/.rev_db file, git-svn will not
be able to rebuild it and you won't be able to fetch again, be able to rebuild it and you won't be able to fetch again,
either. This is fine for one-shot imports. either. This is fine for one-shot imports.
The 'git-svn log' command will not work on repositories using this, The 'git-svn log' command will not work on repositories using
either. this, either. Using this conflicts with the 'useSvmProps'
option for (hopefully) obvious reasons.
config key: svn.nometadata svn.useSvmProps:
svn-remote.<name>.useSvmProps:
This allows git-svn to re-map repository URLs and UUIDs from
mirrors created using SVN::Mirror (or svk) for metadata.
If an SVN revision has a property, "svm:headrev", it is likely
that the revision was created by SVN::Mirror (also used by SVK).
The property contains a repository UUID and a revision. We want
to make it look like we are mirroring the original URL, so
introduce a helper function that returns the original identity
URL and UUID, and use it when generating metadata in commit
messages.
Using this conflicts with the 'noMetadata' option for
(hopefully) obvious reasons.
-- --

View File

@ -63,8 +63,8 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent, my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
'authors-file|A=s' => \$_authors, 'authors-file|A=s' => \$_authors,
'repack:i' => \$Git::SVN::_repack, 'repack:i' => \$Git::SVN::_repack,
'no-metadata' => \$Git::SVN::_no_metadata, 'noMetadata' => \$Git::SVN::_no_metadata,
'use-svm-props|svm-props' => \$Git::SVN::_use_svm_props, 'useSvmProps' => \$Git::SVN::_use_svm_props,
'quiet|q' => \$_q, 'quiet|q' => \$_q,
'repack-flags|repack-args|repack-opts=s' => 'repack-flags|repack-args|repack-opts=s' =>
\$Git::SVN::_repack_flags, \$Git::SVN::_repack_flags,
@ -606,9 +606,14 @@ sub load_authors {
sub read_repo_config { sub read_repo_config {
return unless -d $ENV{GIT_DIR}; return unless -d $ENV{GIT_DIR};
my $opts = shift; my $opts = shift;
my @config_only;
foreach my $o (keys %$opts) { foreach my $o (keys %$opts) {
# if we have mixedCase and a long option-only, then
# it's a config-only variable that we don't need for
# the command-line.
push @config_only, $o if ($o =~ /[A-Z]/ && $o =~ /^[a-z]+$/i);
my $v = $opts->{$o}; my $v = $opts->{$o};
my ($key) = ($o =~ /^([a-z\-]+)/); my ($key) = ($o =~ /^([a-zA-Z\-]+)/);
$key =~ s/-//g; $key =~ s/-//g;
my $arg = 'git-config'; my $arg = 'git-config';
$arg .= ' --int' if ($o =~ /[:=]i$/); $arg .= ' --int' if ($o =~ /[:=]i$/);
@ -623,6 +628,7 @@ sub read_repo_config {
} }
} }
} }
delete @$opts{@config_only} if @config_only;
} }
sub extract_metadata { sub extract_metadata {
@ -983,8 +989,8 @@ sub ra {
my $ra = Git::SVN::Ra->new($self->{url}); my $ra = Git::SVN::Ra->new($self->{url});
if ($self->use_svm_props && !$self->{svm}) { if ($self->use_svm_props && !$self->{svm}) {
if ($self->no_metadata) { if ($self->no_metadata) {
die "Can't have both --no-metadata and ", die "Can't have both 'noMetadata' and ",
"--use-svm-props options set!\n"; "'useSvmProps' options set!\n";
} }
$ra = $self->set_svm_vars($ra); $ra = $self->set_svm_vars($ra);
$self->{-want_revprops} = 1; $self->{-want_revprops} = 1;
@ -1566,7 +1572,7 @@ sub rebuild {
# to a revision: (41 * rev) is the byte offset. # to a revision: (41 * rev) is the byte offset.
# A record of 40 0s denotes an empty revision. # A record of 40 0s denotes an empty revision.
# And yes, it's still pretty fast (faster than Tie::File). # And yes, it's still pretty fast (faster than Tie::File).
# These files are disposable unless --no-metadata is set # These files are disposable unless noMetadata or useSvmProps is set
sub rev_db_set { sub rev_db_set {
my ($self, $rev, $commit, $update_ref) = @_; my ($self, $rev, $commit, $update_ref) = @_;
@ -1578,7 +1584,12 @@ sub rev_db_set {
$SIG{USR1} = $SIG{USR2} = sub { $sig = $_[0] }; $SIG{USR1} = $SIG{USR2} = sub { $sig = $_[0] };
} }
$LOCKFILES{$db_lock} = 1; $LOCKFILES{$db_lock} = 1;
if ($self->no_metadata) { my $sync;
# both of these options make our .rev_db file very, very important
# and we can't afford to lose it because rebuild() won't work
if ($self->use_svm_props || $self->no_metadata) {
$sync = 1;
copy($db, $db_lock) or die "rev_db_set(@_): ", copy($db, $db_lock) or die "rev_db_set(@_): ",
"Failed to copy: ", "Failed to copy: ",
"$db => $db_lock ($!)\n"; "$db => $db_lock ($!)\n";
@ -1599,6 +1610,10 @@ sub rev_db_set {
} }
seek $fh, $offset, 0 or croak $!; seek $fh, $offset, 0 or croak $!;
print $fh $commit,"\n" or croak $!; print $fh $commit,"\n" or croak $!;
if ($sync) {
$fh->flush or die "Couldn't flush $db_lock: $!\n";
$fh->sync or die "Couldn't sync $db_lock: $!\n";
}
close $fh or croak $!; close $fh or croak $!;
if ($update_ref) { if ($update_ref) {
command_noisy('update-ref', '-m', "r$rev", command_noisy('update-ref', '-m', "r$rev",