Browse Source

Merge branch 'jc/thin' into next

* jc/thin:
  git-push: make --thin pack transfer the default.
  gitk: Fix two bugs reported by users
  gitk: Improve appearance of first child links
  gitk: Make downward-pointing arrows end in vertical line segment
  gitk: Don't change cursor at end of layout if find in progress
  gitk: Make commitdata an array rather than a list
  gitk: Fix display of diff lines beginning with --- or +++
  [PATCH] gitk: Make error_popup react to Return
  gitk: Fix a bug in drawing the selected line as a thick line
  gitk: Further speedups
  gitk: Various speed improvements
  gitk: Fix Update menu item
  gitk: Fix clicks on arrows on line ends
  gitk: New improved gitk
  contrib/git-svn: stabilize memory usage for big fetches
maint
Junio C Hamano 19 years ago
parent
commit
f4e96f97e8
  1. 109
      contrib/git-svn/git-svn.perl
  2. 6
      git-push.sh
  3. 1968
      gitk

109
contrib/git-svn/git-svn.perl

@ -8,7 +8,7 @@ use vars qw/ $AUTHOR $VERSION @@ -8,7 +8,7 @@ use vars qw/ $AUTHOR $VERSION
$GIT_SVN_INDEX $GIT_SVN
$GIT_DIR $REV_DIR/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '0.10.0';
$VERSION = '0.11.0';
$GIT_DIR = $ENV{GIT_DIR} || "$ENV{PWD}/.git";
# make sure the svn binary gives consistent output between locales and TZs:
$ENV{TZ} = 'UTC';
@ -217,9 +217,8 @@ sub fetch { @@ -217,9 +217,8 @@ sub fetch {
push @log_args, '--stop-on-copy' unless $_no_stop_copy;

my $svn_log = svn_log_raw(@log_args);
@$svn_log = sort { $a->{revision} <=> $b->{revision} } @$svn_log;

my $base = shift @$svn_log or croak "No base revision!\n";
my $base = next_log_entry($svn_log) or croak "No base revision!\n";
my $last_commit = undef;
unless (-d $SVN_WC) {
svn_cmd_checkout($SVN_URL,$base->{revision},$SVN_WC);
@ -234,18 +233,22 @@ sub fetch { @@ -234,18 +233,22 @@ sub fetch {
}
my @svn_up = qw(svn up);
push @svn_up, '--ignore-externals' unless $_no_ignore_ext;
my $last_rev = $base->{revision};
foreach my $log_msg (@$svn_log) {
assert_svn_wc_clean($last_rev, $last_commit);
$last_rev = $log_msg->{revision};
sys(@svn_up,"-r$last_rev");
my $last = $base;
while (my $log_msg = next_log_entry($svn_log)) {
assert_svn_wc_clean($last->{revision}, $last_commit);
if ($last->{revision} >= $log_msg->{revision}) {
croak "Out of order: last >= current: ",
"$last->{revision} >= $log_msg->{revision}\n";
}
sys(@svn_up,"-r$log_msg->{revision}");
$last_commit = git_commit($log_msg, $last_commit, @parents);
$last = $log_msg;
}
assert_svn_wc_clean($last_rev, $last_commit);
assert_svn_wc_clean($last->{revision}, $last_commit);
unless (-e "$GIT_DIR/refs/heads/master") {
sys(qw(git-update-ref refs/heads/master),$last_commit);
}
return pop @$svn_log;
return $last;
}

sub commit {
@ -708,49 +711,61 @@ sub svn_commit_tree { @@ -708,49 +711,61 @@ sub svn_commit_tree {
return fetch("$rev_committed=$commit")->{revision};
}

# read the entire log into a temporary file (which is removed ASAP)
# and store the file handle + parser state
sub svn_log_raw {
my (@log_args) = @_;
my $pid = open my $log_fh,'-|';
my $log_fh = IO::File->new_tmpfile or croak $!;
my $pid = fork;
defined $pid or croak $!;

if ($pid == 0) {
if (!$pid) {
open STDOUT, '>&', $log_fh or croak $!;
exec (qw(svn log), @log_args) or croak $!
}
waitpid $pid, 0;
croak if $?;
seek $log_fh, 0, 0 or croak $!;
return { state => 'sep', fh => $log_fh };
}

sub next_log_entry {
my $log = shift; # retval of svn_log_raw()
my $ret = undef;
my $fh = $log->{fh};

my @svn_log;
my $state = 'sep';
while (<$log_fh>) {
while (<$fh>) {
chomp;
if (/^\-{72}$/) {
if ($state eq 'msg') {
if ($svn_log[$#svn_log]->{lines}) {
$svn_log[$#svn_log]->{msg} .= $_."\n";
unless(--$svn_log[$#svn_log]->{lines}) {
$state = 'sep';
if ($log->{state} eq 'msg') {
if ($ret->{lines}) {
$ret->{msg} .= $_."\n";
unless(--$ret->{lines}) {
$log->{state} = 'sep';
}
} else {
croak "Log parse error at: $_\n",
$svn_log[$#svn_log]->{revision},
$ret->{revision},
"\n";
}
next;
}
if ($state ne 'sep') {
if ($log->{state} ne 'sep') {
croak "Log parse error at: $_\n",
"state: $state\n",
$svn_log[$#svn_log]->{revision},
"state: $log->{state}\n",
$ret->{revision},
"\n";
}
$state = 'rev';
$log->{state} = 'rev';

# if we have an empty log message, put something there:
if (@svn_log) {
$svn_log[$#svn_log]->{msg} ||= "\n";
delete $svn_log[$#svn_log]->{lines};
if ($ret) {
$ret->{msg} ||= "\n";
delete $ret->{lines};
return $ret;
}
next;
}
if ($state eq 'rev' && s/^r(\d+)\s*\|\s*//) {
if ($log->{state} eq 'rev' && s/^r(\d+)\s*\|\s*//) {
my $rev = $1;
my ($author, $date, $lines) = split(/\s*\|\s*/, $_, 3);
($lines) = ($lines =~ /(\d+)/);
@ -758,36 +773,34 @@ sub svn_log_raw { @@ -758,36 +773,34 @@ sub svn_log_raw {
/(\d{4})\-(\d\d)\-(\d\d)\s
(\d\d)\:(\d\d)\:(\d\d)\s([\-\+]\d+)/x)
or croak "Failed to parse date: $date\n";
my %log_msg = ( revision => $rev,
$ret = { revision => $rev,
date => "$tz $Y-$m-$d $H:$M:$S",
author => $author,
lines => $lines,
msg => '' );
msg => '' };
if (defined $_authors && ! defined $users{$author}) {
die "Author: $author not defined in ",
"$_authors file\n";
}
push @svn_log, \%log_msg;
$state = 'msg_start';
$log->{state} = 'msg_start';
next;
}
# skip the first blank line of the message:
if ($state eq 'msg_start' && /^$/) {
$state = 'msg';
} elsif ($state eq 'msg') {
if ($svn_log[$#svn_log]->{lines}) {
$svn_log[$#svn_log]->{msg} .= $_."\n";
unless (--$svn_log[$#svn_log]->{lines}) {
$state = 'sep';
if ($log->{state} eq 'msg_start' && /^$/) {
$log->{state} = 'msg';
} elsif ($log->{state} eq 'msg') {
if ($ret->{lines}) {
$ret->{msg} .= $_."\n";
unless (--$ret->{lines}) {
$log->{state} = 'sep';
}
} else {
croak "Log parse error at: $_\n",
$svn_log[$#svn_log]->{revision},"\n";
$ret->{revision},"\n";
}
}
}
close $log_fh or croak $?;
return \@svn_log;
return $ret;
}

sub svn_info {
@ -1114,9 +1127,13 @@ __END__ @@ -1114,9 +1127,13 @@ __END__

Data structures:

@svn_log = array of log_msg hashes
$svn_log hashref (as returned by svn_log_raw)
{
fh => file handle of the log file,
state => state of the log file parser (sep/msg/rev/msg_start...)
}

$log_msg hash
$log_msg hashref as returned by next_log_entry($svn_log)
{
msg => 'whitespace-formatted log entry
', # trailing newline is preserved

6
git-push.sh

@ -8,7 +8,7 @@ USAGE='[--all] [--tags] [--force] <repository> [<refspec>...]' @@ -8,7 +8,7 @@ USAGE='[--all] [--tags] [--force] <repository> [<refspec>...]'
has_all=
has_force=
has_exec=
has_thin=
has_thin=--thin
remote=
do_tags=

@ -24,7 +24,9 @@ do @@ -24,7 +24,9 @@ do
--exec=*)
has_exec="$1" ;;
--thin)
has_thin="$1" ;;
;; # noop
--no-thin)
has_thin= ;;
-*)
usage ;;
*)

1968
gitk

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save