X-Git-Url: http://git.vanrenterghem.biz/git.ikiwiki.info.git/blobdiff_plain/04a9dbfe7daa9c352ae4e9af17df8134248f3806..b62270dfdddac257a295d80c1a0b2d9786f9a94e:/IkiWiki/Rcs/git.pm

diff --git a/IkiWiki/Rcs/git.pm b/IkiWiki/Rcs/git.pm
index 05eaa8d78..9f64b8630 100644
--- a/IkiWiki/Rcs/git.pm
+++ b/IkiWiki/Rcs/git.pm
@@ -8,8 +8,6 @@ use open qw{:utf8 :std};
 
 package IkiWiki;
 
-my $origin_branch    = 'origin';            # Git ref for main repository
-my $master_branch    = 'master';            # working branch
 my $sha1_pattern     = qr/[0-9a-fA-F]{40}/; # pattern to validate Git sha1sums
 my $dummy_commit_msg = 'dummy commit';      # message to skip in recent changes
 
@@ -112,8 +110,8 @@ sub _merge_past ($$$) { #{{{
 
 		# Switch to throw-away branch for the merge operation.
 		push @undo, sub {
-			if (!run_or_cry('git-checkout', $master_branch)) {
-				run_or_cry('git-checkout','-f',$master_branch);
+			if (!run_or_cry('git-checkout', $config{gitmaster_branch})) {
+				run_or_cry('git-checkout','-f',$config{gitmaster_branch});
 			}
 		};
 		run_or_die('git-checkout', $branch);
@@ -125,7 +123,7 @@ sub _merge_past ($$$) { #{{{
 		# _Silently_ commit all modifications in the current branch.
 		run_or_non('git-commit', '-m', $message, '-a');
 		# ... and re-switch to master.
-		run_or_die('git-checkout', $master_branch);
+		run_or_die('git-checkout', $config{gitmaster_branch});
 
 		# Attempt to merge without complaining.
 		if (!run_or_non('git-pull', '--no-commit', '.', $branch)) {
@@ -146,34 +144,37 @@ sub _merge_past ($$$) { #{{{
 	return $conflict;
 } #}}}
 
-sub _parse_diff_tree (@) { #{{{
+sub _parse_diff_tree ($@) { #{{{
 	# Parse the raw diff tree chunk and return the info hash.
 	# See git-diff-tree(1) for the syntax.
 
-	my ($dt_ref) = @_;
+	my ($prefix, $dt_ref) = @_;
 
 	# End of stream?
-	return if !defined @{ $dt_ref } || !length @{ $dt_ref }[0];
+	return if !defined @{ $dt_ref } ||
+		  !defined @{ $dt_ref }[0] || !length @{ $dt_ref }[0];
 
 	my %ci;
 	# Header line.
-	HEADER: while (my $line = shift @{ $dt_ref }) {
+	while (my $line = shift @{ $dt_ref }) {
 		return if $line !~ m/^(.+) ($sha1_pattern)/;
 
-		my $sha1 = $1;
+		my $sha1 = $2;
 		$ci{'sha1'} = $sha1;
-		last HEADER;
+		last;
 	}
 
 	# Identification lines for the commit.
-	IDENT: while (my $line = shift @{ $dt_ref }) {
+	while (my $line = shift @{ $dt_ref }) {
 		# Regexps are semi-stolen from gitweb.cgi.
 		if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) {
 			$ci{'tree'} = $1;
-		} elsif ($line =~ m/^parent ([0-9a-fA-F]{40})$/) {
+		}
+		elsif ($line =~ m/^parent ([0-9a-fA-F]{40})$/) {
 			# XXX: collecting in reverse order
 			push @{ $ci{'parents'} }, $1;
-		} elsif ($line =~ m/^(author|committer) (.*) ([0-9]+) (.*)$/) {
+		}
+		elsif ($line =~ m/^(author|committer) (.*) ([0-9]+) (.*)$/) {
 			my ($who, $name, $epoch, $tz) =
 			   ($1,   $2,    $3,     $4 );
 
@@ -185,33 +186,35 @@ sub _parse_diff_tree (@) { #{{{
 				my ($fullname, $username) = ($1, $2);
 				$ci{"${who}_fullname"}    = $fullname;
 				$ci{"${who}_username"}    = $username;
-			} else {
+			}
+			else {
 				$ci{"${who}_fullname"} =
 					$ci{"${who}_username"} = $name;
 			}
-		} elsif ($line =~ m/^$/) {
+		}
+		elsif ($line =~ m/^$/) {
 			# Trailing empty line signals next section.
-			last IDENT;
+			last;
 		}
 	}
 
-	error("No 'tree' or 'parents' seen in diff-tree output")
+	debug("No 'tree' or 'parents' seen in diff-tree output")
 	    if !defined $ci{'tree'} || !defined $ci{'parents'};
 
-	$ci{'parent'} = @{ $ci{'parents'} }[0];
+	$ci{'parent'} = @{ $ci{'parents'} }[0] if defined $ci{'parents'};
 
 	# Commit message.
-	COMMENT: while (my $line = shift @{ $dt_ref }) {
+	while (my $line = shift @{ $dt_ref }) {
 		if ($line =~ m/^$/) {
 			# Trailing empty line signals next section.
-			last COMMENT;
+			last;
 		};
 		$line =~ s/^    //;
 		push @{ $ci{'comment'} }, $line;
 	}
 
 	# Modified files.
-	FILE: while (my $line = shift @{ $dt_ref }) {
+	while (my $line = shift @{ $dt_ref }) {
 		if ($line =~ m{^:
 			([0-7]{6})[ ]      # from mode
 			([0-7]{6})[ ]      # to mode
@@ -227,6 +230,7 @@ sub _parse_diff_tree (@) { #{{{
 			if ($file =~ m/^"(.*)"$/) {
 				($file=$1) =~ s/\\([0-7]{1,3})/chr(oct($1))/eg;
 			}
+			$file =~ s/^\Q$prefix\E//;
 			if (length $file) {
 				push @{ $ci{'details'} }, {
 					'file'      => decode_utf8($file),
@@ -234,30 +238,30 @@ sub _parse_diff_tree (@) { #{{{
 					'sha1_to'   => $sha1_to,
 				};
 			}
-			next FILE;
+			next;
 		};
-		last FILE;
+		last;
 	}
 
-	warn "No detail in diff-tree output" if !defined $ci{'details'};
+	debug("No detail in diff-tree output") if !defined $ci{'details'};
 
 	return \%ci;
 } #}}}
 
-sub git_commit_info (;$$) { #{{{
+sub git_commit_info ($;$) { #{{{
 	# Return an array of commit info hashes of num commits (default: 1)
-	# starting from the given sha1sum (default: HEAD).
+	# starting from the given sha1sum.
 
 	my ($sha1, $num) = @_;
 
 	$num ||= 1;
 
 	my @raw_lines =
-	    run_or_die(qq{git-rev-list --max-count=$num $sha1 |
-		          git-diff-tree --stdin --pretty=raw -M -r});
+	    run_or_die('git-log', "--max-count=$num", '--pretty=raw', '--raw', '--abbrev=40', '--always', '-m', '-r', $sha1, '--', '.');
+	my ($prefix) = run_or_die('git-rev-parse', '--show-prefix');
 
 	my @ci;
-	while (my $parsed = _parse_diff_tree(\@raw_lines)) {
+	while (my $parsed = _parse_diff_tree(($prefix or ""), \@raw_lines)) {
 		push @ci, $parsed;
 	}
 
@@ -282,7 +286,7 @@ sub git_sha1 (;$) { #{{{
 sub rcs_update () { #{{{
 	# Update working directory.
 
-	run_or_cry('git-pull', $origin_branch);
+	run_or_cry('git-pull', $config{gitorigin_branch});
 } #}}}
 
 sub rcs_prepedit ($) { #{{{
@@ -302,10 +306,12 @@ sub rcs_commit ($$$;$$) { #{{{
 	my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
 
 	if (defined $user) {
-		$message="web commit by $user".(length $message ? ": $message" : "");
+		$message = "web commit by $user" .
+		    (length $message ? ": $message" : "");
 	}
 	elsif (defined $ipaddr) {
-		$message="web commit from $ipaddr".(length $message ? ": $message" : "");
+		$message = "web commit from $ipaddr" .
+		    (length $message ? ": $message" : "");
 	}
 
 	# XXX: Wiki directory is in the unlocked state when starting this
@@ -330,7 +336,7 @@ sub rcs_commit ($$$;$$) { #{{{
 	$message = possibly_foolish_untaint($message);
 	if (run_or_non('git-commit', '-m', $message, '-i', $file)) {
 		unlockwiki();
-		run_or_cry('git-push', $origin_branch);
+		run_or_cry('git-push', $config{gitorigin_branch});
 	}
 
 	return undef; # success
@@ -352,18 +358,20 @@ sub rcs_recentchanges ($) { #{{{
 	eval q{use Date::Parse};
 	error($@) if $@;
 
-	my ($sha1, $type, $when, $diffurl, $user, @pages, @message, @rets);
-	INFO: foreach my $ci (git_commit_info('HEAD', $num)) {
+	my @rets;
+	foreach my $ci (git_commit_info('HEAD', $num)) {
 		my $title = @{ $ci->{'comment'} }[0];
 
 		# Skip redundant commits.
-		next INFO if ($title eq $dummy_commit_msg);
+		next if ($title eq $dummy_commit_msg);
 
-		$sha1 = $ci->{'sha1'};
-		$type = "web";
-		$when = time - $ci->{'author_epoch'};
+		my ($sha1, $when) = (
+			$ci->{'sha1'},
+			time - $ci->{'author_epoch'}
+		);
 
-		DETAIL: foreach my $detail (@{ $ci->{'details'} }) {
+		my (@pages, @messages);
+		foreach my $detail (@{ $ci->{'details'} }) {
 			my $diffurl = $config{'diffurl'};
 			my $file    = $detail->{'file'};
 
@@ -377,14 +385,16 @@ sub rcs_recentchanges ($) { #{{{
 				diffurl => $diffurl,
 			};
 		}
+		push @messages, { line => $title };
 
-		push @message, { line => $title };
+		my ($user, $type) = (q{}, "web");
 
-		if (defined $message[0] &&
-		    $message[0]->{line} =~ m/$config{web_commit_regexp}/) {
-			$user=defined $2 ? "$2" : "$3";
-			$message[0]->{line}=$4;
-		} else {
+		if (defined $messages[0] &&
+		    $messages[0]->{line} =~ m/$config{web_commit_regexp}/) {
+			$user = defined $2 ? "$2" : "$3";
+			$messages[0]->{line} = $4;
+		}
+		else {
 			$type ="git";
 			$user = $ci->{'author_username'};
 		}
@@ -394,12 +404,11 @@ sub rcs_recentchanges ($) { #{{{
 			user       => $user,
 			committype => $type,
 			when       => $when,
-			message    => [@message],
+			message    => [@messages],
 			pages      => [@pages],
-		} if @pages;
+		};
 
-		$sha1 = $type = $when = $diffurl = $user = undef;
-		@pages = @message = ();
+		last if @rets >= $num;
 	}
 
 	return @rets;
@@ -433,7 +442,8 @@ sub rcs_notify () { #{{{
 	if (@{ $ci->{'comment'} }[0] =~ m/$config{web_commit_regexp}/) {
 		$user    = defined $2 ? "$2" : "$3";
 		$message = $4;
-	} else {
+	}
+	else {
 		$user    = $ci->{'author_username'};
 		$message = join "\n", @{ $ci->{'comment'} };
 	}
@@ -445,7 +455,8 @@ sub rcs_notify () { #{{{
 		},
 		sub {
 			join "\n", run_or_die('git-diff', "${sha1}^", $sha1);
-		}, $user, @changed_pages);
+		}, $user, @changed_pages
+	);
 } #}}}
 
 sub rcs_getctime ($) { #{{{