X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/d2359d50cab3647bfec8fc2c3147a9af2c4ecd67..cc3d2bc904dd66b3a3e5af005f4cdc87fc2229ac:/IkiWiki/Plugin/git.pm?ds=inline

diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm
index 892b711d8..cf7fbe9b7 100644
--- a/IkiWiki/Plugin/git.pm
+++ b/IkiWiki/Plugin/git.pm
@@ -152,10 +152,11 @@ sub genwrapper {
 }
 
 sub safe_git (&@) {
-	# Start a child process safely without resorting /bin/sh.
-	# Return command output or success state (in scalar context).
+	# Start a child process safely without resorting to /bin/sh.
+	# Returns command output (in list content) or success state
+	# (in scalar context), or runs the specified data handler.
 
-	my ($error_handler, @cmdline) = @_;
+	my ($error_handler, $data_handler, @cmdline) = @_;
 
 	my $pid = open my $OUT, "-|";
 
@@ -187,7 +188,12 @@ sub safe_git (&@) {
 
 		chomp;
 
-		push @lines, $_;
+		if (! defined $data_handler) {
+			push @lines, $_;
+		}
+		else {
+			last unless $data_handler->($_);
+		}
 	}
 
 	close $OUT;
@@ -197,9 +203,9 @@ sub safe_git (&@) {
 	return wantarray ? @lines : ($? == 0);
 }
 # Convenient wrappers.
-sub run_or_die ($@) { safe_git(\&error, @_) }
-sub run_or_cry ($@) { safe_git(sub { warn @_ },  @_) }
-sub run_or_non ($@) { safe_git(undef,            @_) }
+sub run_or_die ($@) { safe_git(\&error, undef, @_) }
+sub run_or_cry ($@) { safe_git(sub { warn @_ }, undef, @_) }
+sub run_or_non ($@) { safe_git(undef, undef, @_) }
 
 
 sub merge_past ($$$) {
@@ -496,16 +502,16 @@ sub rcs_commit (@) {
 		return $conflict if defined $conflict;
 	}
 
-	rcs_add($params{file});
-	return rcs_commit_staged(
-		message => $params{message},
-		session => $params{session},
-	);
+	return rcs_commit_helper(@_);
 }
 
 sub rcs_commit_staged (@) {
 	# Commits all staged changes. Changes can be staged using rcs_add,
 	# rcs_remove, and rcs_rename.
+	return rcs_commit_helper(@_);
+}
+
+sub rcs_commit_helper (@) {
 	my %params=@_;
 	
 	my %env=%ENV;
@@ -546,10 +552,12 @@ sub rcs_commit_staged (@) {
 			$params{message}.=".";
 		}
 	}
-	push @opts, '-q';
-	# git commit returns non-zero if file has not been really changed.
-	# so we should ignore its exit status (hence run_or_non).
-	if (run_or_non('git', 'commit', @opts, '-m', $params{message})) {
+	if (exists $params{file}) {
+		push @opts, '--', $params{file};
+	}
+	# git commit returns non-zero if nothing really changed.
+	# So we should ignore its exit status (hence run_or_non).
+	if (run_or_non('git', 'commit', '-m', $params{message}, '-q', @opts)) {
 		if (length $config{gitorigin_branch}) {
 			run_or_cry('git', 'push', $config{gitorigin_branch});
 		}
@@ -661,15 +669,19 @@ sub rcs_recentchanges ($) {
 	return @rets;
 }
 
-sub rcs_diff ($) {
+sub rcs_diff ($;$) {
 	my $rev=shift;
+	my $maxlines=shift;
 	my ($sha1) = $rev =~ /^($sha1_pattern)$/; # untaint
 	my @lines;
-	foreach my $line (run_or_non("git", "show", $sha1)) {
-		if (@lines || $line=~/^diff --git/) {
-			push @lines, $line."\n";
-		}
-	}
+	my $addlines=sub {
+		my $line=shift;
+		return if defined $maxlines && @lines == $maxlines;
+		push @lines, $line."\n"
+			if (@lines || $line=~/^diff --git/);
+		return 1;
+	};
+	safe_git(undef, $addlines, "git", "show", $sha1);
 	if (wantarray) {
 		return @lines;
 	}
@@ -688,7 +700,7 @@ sub findtimes ($$) {
 	if (! keys %time_cache) {
 		my $date;
 		foreach my $line (run_or_die('git', 'log',
-				'--pretty=format:%ct',
+				'--pretty=format:%at',
 				'--name-only', '--relative')) {
 			if (! defined $date && $line =~ /^(\d+)$/) {
 				$date=$line;
@@ -797,7 +809,7 @@ sub git_parse_changes {
 				eval q{use File::Temp};
 				die $@ if $@;
 				my $fh;
-				($fh, $path)=File::Temp::tempfile("XXXXXXXXXX", UNLINK => 1);
+				($fh, $path)=File::Temp::tempfile(undef, UNLINK => 1);
 				my $cmd = "cd $git_dir && ".
 				          "git show $detail->{sha1_to} > '$path'";
 				if (system($cmd) != 0) {
@@ -848,8 +860,22 @@ sub rcs_preprevert ($) {
 	# in order to see all changes.
 	my ($subdir, $rootdir) = git_find_root();
 	$git_dir=$rootdir;
-	return git_parse_changes(git_commit_info($sha1, 1));
+
+	my @commits=git_commit_info($sha1, 1);
+	if (! @commits) {
+		error "unknown commit"; # just in case
+	}
+
+	# git revert will fail on merge commits. Add a nice message.
+	if (exists $commits[0]->{parents} &&
+	    @{$commits[0]->{parents}} > 1) {
+		error gettext("you are not allowed to revert a merge");
+	}
+
+	my @ret=git_parse_changes(@commits);
+
 	$git_dir=undef;
+	return @ret;
 }
 
 sub rcs_revert ($) {