git-svn: extra safety for noMetadata and useSvmProps users
authorEric Wong <normalperson@yhbt.net>
Sun, 11 Feb 2007 23:21:24 +0000 (15:21 -0800)
committerEric Wong <normalperson@yhbt.net>
Fri, 23 Feb 2007 08:57:12 +0000 (00:57 -0800)
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>
Documentation/git-svn.txt
git-svn.perl

index 50dc6ac..d45283a 100644 (file)
@@ -316,17 +316,33 @@ for more information on using GIT_SVN_ID.
 
 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.
 
        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,
        either.  This is fine for one-shot imports.
 
-       The 'git-svn log' command will not work on repositories using this,
-       either.
-
-config key: svn.nometadata
+       The 'git-svn log' command will not work on repositories using
+       this, either.  Using this conflicts with the 'useSvmProps'
+       option for (hopefully) obvious reasons.
+
+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.
 
 --
 
index b62cc06..fdecffb 100755 (executable)
@@ -63,8 +63,8 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
 my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
                'authors-file|A=s' => \$_authors,
                'repack:i' => \$Git::SVN::_repack,
-               'no-metadata' => \$Git::SVN::_no_metadata,
-               'use-svm-props|svm-props' => \$Git::SVN::_use_svm_props,
+               'noMetadata' => \$Git::SVN::_no_metadata,
+               'useSvmProps' => \$Git::SVN::_use_svm_props,
                'quiet|q' => \$_q,
                'repack-flags|repack-args|repack-opts=s' =>
                   \$Git::SVN::_repack_flags,
@@ -606,9 +606,14 @@ sub load_authors {
 sub read_repo_config {
        return unless -d $ENV{GIT_DIR};
        my $opts = shift;
+       my @config_only;
        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 ($key) = ($o =~ /^([a-z\-]+)/);
+               my ($key) = ($o =~ /^([a-zA-Z\-]+)/);
                $key =~ s/-//g;
                my $arg = 'git-config';
                $arg .= ' --int' if ($o =~ /[:=]i$/);
@@ -623,6 +628,7 @@ sub read_repo_config {
                        }
                }
        }
+       delete @$opts{@config_only} if @config_only;
 }
 
 sub extract_metadata {
@@ -983,8 +989,8 @@ sub ra {
        my $ra = Git::SVN::Ra->new($self->{url});
        if ($self->use_svm_props && !$self->{svm}) {
                if ($self->no_metadata) {
-                       die "Can't have both --no-metadata and ",
-                           "--use-svm-props options set!\n";
+                       die "Can't have both 'noMetadata' and ",
+                           "'useSvmProps' options set!\n";
                }
                $ra = $self->set_svm_vars($ra);
                $self->{-want_revprops} = 1;
@@ -1566,7 +1572,7 @@ sub rebuild {
 # to a revision: (41 * rev) is the byte offset.
 # A record of 40 0s denotes an empty revision.
 # 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 {
        my ($self, $rev, $commit, $update_ref) = @_;
@@ -1578,7 +1584,12 @@ sub rev_db_set {
                            $SIG{USR1} = $SIG{USR2} = sub { $sig = $_[0] };
        }
        $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(@_): ",
                                           "Failed to copy: ",
                                           "$db => $db_lock ($!)\n";
@@ -1599,6 +1610,10 @@ sub rev_db_set {
        }
        seek $fh, $offset, 0 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 $!;
        if ($update_ref) {
                command_noisy('update-ref', '-m', "r$rev",