}
sub cmd_fetch {
+ if (@_) {
+ die "Additional fetch arguments are no longer supported.\n",
+ "Use --follow-parent if you have moved/copied directories
+ instead.\n";
+ }
my $gs = Git::SVN->new;
- $gs->fetch(@_);
+ $gs->fetch;
if ($gs->{last_commit} && !verify_ref('refs/heads/master^0')) {
command_noisy(qw(update-ref refs/heads/master),
$gs->{last_commit});
}
sub verify_remotes_sanity {
+ return unless -d $ENV{GIT_DIR};
my %seen;
foreach (command(qw/config -l/)) {
if (m!^svn-remote\.(?:.+)\.fetch=.*:refs/remotes/(\S+)\s*$!) {
$name;
}
-sub init {
- my ($class, $url, $path, $repo_id, $ref_id) = @_;
- my $self = _new($class, $repo_id, $ref_id, $path);
- if (defined $url) {
- $url =~ s!/+$!!; # strip trailing slash
+sub find_existing_remote {
+ my ($url, $remotes) = @_;
+ my $existing;
+ foreach my $repo_id (keys %$remotes) {
+ my $u = $remotes->{$repo_id}->{url} or next;
+ next if $u ne $url;
+ $existing = $repo_id;
+ last;
+ }
+ $existing;
+}
+sub init_remote_config {
+ my ($self, $url) = @_;
+ $url =~ s!/+$!!; # strip trailing slash
+ my $r = read_all_remotes();
+ my $existing = find_existing_remote($url, $r);
+ if ($existing) {
+ print STDERR "Using existing ",
+ "[svn-remote \"$existing\"]\n";
+ $self->{repo_id} = $existing;
+ } else {
+ my $min_url = Git::SVN::Ra->new($url)->minimize_url;
+ $existing = find_existing_remote($min_url, $r);
+ if ($existing) {
+ print STDERR "Using existing ",
+ "[svn-remote \"$existing\"]\n";
+ $self->{repo_id} = $existing;
+ }
+ if ($min_url ne $url) {
+ print STDERR "Using higher level of URL: ",
+ "$url => $min_url\n";
+ my $old_path = $self->{path};
+ $self->{path} = $url;
+ $self->{path} =~ s!^\Q$min_url\E/*!!;
+ if (length $old_path) {
+ $self->{path} .= "/$old_path";
+ }
+ $url = $min_url;
+ }
+ }
+ my $orig_url;
+ if (!$existing) {
# verify that we aren't overwriting anything:
- my $orig_url = eval {
+ $orig_url = eval {
command_oneline('config', '--get',
- "svn-remote.$repo_id.url")
+ "svn-remote.$self->{repo_id}.url")
};
if ($orig_url && ($orig_url ne $url)) {
- die "svn-remote.$repo_id.url already set: ",
+ die "svn-remote.$self->{repo_id}.url already set: ",
"$orig_url\nwanted to set to: $url\n";
}
- my ($xrepo_id, $xpath) = find_ref($self->refname);
- if (defined $xpath) {
- die "svn-remote.$xrepo_id.fetch already set to track ",
- "$xpath:refs/remotes/", $self->refname, "\n";
- }
- if (!$orig_url) {
- command_noisy('config',
- "svn-remote.$repo_id.url", $url);
- }
- command_noisy('config', '--add',
- "svn-remote.$repo_id.fetch",
- "$path:".$self->refname);
}
+ my ($xrepo_id, $xpath) = find_ref($self->refname);
+ if (defined $xpath) {
+ die "svn-remote.$xrepo_id.fetch already set to track ",
+ "$xpath:refs/remotes/", $self->refname, "\n";
+ }
+ command_noisy('config',
+ "svn-remote.$self->{repo_id}.url", $url);
+ command_noisy('config', '--add',
+ "svn-remote.$self->{repo_id}.fetch",
+ "$self->{path}:".$self->refname);
$self->{url} = $url;
+}
+
+sub init {
+ my ($class, $url, $path, $repo_id, $ref_id) = @_;
+ my $self = _new($class, $repo_id, $ref_id, $path);
+ if (defined $url) {
+ $self->init_remote_config($url);
+ }
$self;
}
sub find_parent_branch {
my ($self, $paths, $rev) = @_;
+ return undef unless $::_follow_parent;
# look for a parent from another branch:
- my $i = $paths->{'/'.$self->rel_path} or return;
- my $branch_from = $i->copyfrom_path or return;
+ my @b_path_components = split m#/#, $self->rel_path;
+ my @a_path_components;
+ my $i;
+ while (@b_path_components) {
+ $i = $paths->{'/'.join('/', @b_path_components)};
+ last if $i;
+ unshift(@a_path_components, pop(@b_path_components));
+ }
+ goto not_found unless defined $i;
+ my $branch_from = $i->copyfrom_path or goto not_found;
+ if (@a_path_components) {
+ print STDERR "branch_from: $branch_from => ";
+ $branch_from .= '/'.join('/', @a_path_components);
+ print STDERR $branch_from, "\n";
+ }
my $r = $i->copyfrom_rev;
my $repos_root = $self->ra->{repos_root};
my $url = $self->ra->{url};
}
my ($r0, $parent) = $gs->find_rev_before($r, 1);
if ($::_follow_parent && (!defined $r0 || !defined $parent)) {
- foreach (0 .. $r) {
- my $log_entry = eval { $gs->do_fetch(undef, $_) };
+ $gs->ra->get_log([$gs->{path}], 0, $r, 0, 1, 1, sub {
+ my ($paths, $rev) = @_;
+ my $log_entry = eval { $gs->do_fetch($paths, $rev) };
$gs->do_git_commit($log_entry) if $log_entry;
- }
+ });
($r0, $parent) = $gs->last_rev_commit;
}
if (defined $r0 && defined $parent && $gs->revisions_eq($r0, $r)) {
}
return $self->make_log_entry($rev, [$parent], $ed);
}
- print STDERR "Branch parent not found...\n";
+not_found:
+ print STDERR "Branch parent for path: '/",
+ $self->rel_path, "' not found\n";
+ return undef unless $paths;
+ foreach my $x (sort keys %$paths) {
+ my $p = $paths->{$x};
+ print STDERR ' ', $p->action, ' ', $x;
+ if (my $cp_from = $p->copyfrom_path) {
+ print STDERR "(from $cp_from:", $p->copyfrom_rev, ')';
+ }
+ print STDERR "\n";
+ }
return undef;
}
$editor->{git_commit_ok};
}
+sub minimize_url {
+ my ($self) = @_;
+ return $self->{url} if ($self->{url} eq $self->{repos_root});
+ my $url = $self->{repos_root};
+ my @components = split(m!/!, $self->{svn_path});
+ my $c = '';
+ do {
+ $url .= "/$c" if length $c;
+ eval { (ref $self)->new($url)->get_latest_revnum };
+ } while ($@ && ($c = shift @components));
+ $url;
+}
+
sub can_do_switch {
my $self = shift;
unless (defined $can_do_switch) {