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
+hook(type => "checkconfig", id => "git", call => sub { #{{{
+ if (! defined $config{diffurl}) {
+ $config{diffurl}="";
+ }
+ if (! defined $config{gitorigin_branch}) {
+ $config{gitorigin_branch}="origin";
+ }
+ if (! defined $config{gitmaster_branch}) {
+ $config{gitmaster_branch}="master";
+ }
+ if (exists $config{git_wrapper}) {
+ push @{$config{wrappers}}, {
+ wrapper => $config{git_wrapper},
+ wrappermode => (defined $config{git_wrappermode} ? $config{git_wrappermode} : "06755"),
+ };
+ }
+}); #}}}
+
+hook(type => "getsetup", id => "git", call => sub { #{{{
+ return
+ git_wrapper => {
+ type => "string",
+ example => "/git/wiki.git/hooks/post-update",
+ description => "git post-update executable to generate",
+ safe => 0, # file
+ rebuild => 0,
+ },
+ git_wrappermode => {
+ type => "string",
+ example => '06755',
+ description => "mode for git_wrapper (can safely be made suid)",
+ safe => 0,
+ rebuild => 0,
+ },
+ historyurl => {
+ type => "string",
+ example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=history;f=[[file]]",
+ description => "gitweb url to show file history ([[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ diffurl => {
+ type => "string",
+ example => "http://git.example.com/gitweb.cgi?p=wiki.git;a=blobdiff;h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_parent]];f=[[file]]",
+ description => "gitweb url to show a diff ([[sha1_to]], [[sha1_from]], [[sha1_parent]], and [[file]] substituted)",
+ safe => 1,
+ rebuild => 1,
+ },
+ gitorigin_branch => {
+ type => "string",
+ example => "origin",
+ description => "where to pull and push changes (set to empty string to disable)",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+ gitmaster_branch => {
+ type => "string",
+ example => "master",
+ description => "branch that the wiki is stored in",
+ safe => 0, # paranoia
+ rebuild => 0,
+ },
+}); #}}}
+
sub _safe_git (&@) { #{{{
# Start a child process safely without resorting /bin/sh.
# Return command output or success state (in scalar context).
my $conflict = _merge_past($prev, $file, $dummy_commit_msg);
return $conflict if defined $conflict;
}
-
+
+ rcs_add($file);
+ return rcs_commit_staged($message, $user, $ipaddr);
+} #}}}
+
+sub rcs_commit_staged ($$$) {
+ # Commits all staged changes. Changes can be staged using rcs_add,
+ # rcs_remove, and rcs_rename.
+ my ($message, $user, $ipaddr)=@_;
+
# Set the commit author and email to the web committer.
my %env=%ENV;
if (defined $user || defined $ipaddr) {
# git commit returns non-zero if file has not been really changed.
# so we should ignore its exit status (hence run_or_non).
$message = possibly_foolish_untaint($message);
- if (run_or_non('git', 'commit', '--cleanup=verbatim', '-q', '-m', $message, '-i', $file)) {
+ if (run_or_non('git', 'commit', '--cleanup=verbatim',
+ '-q', '-m', $message)) {
if (length $config{gitorigin_branch}) {
run_or_cry('git', 'push', $config{gitorigin_branch});
}
%ENV=%env;
return undef; # success
-} #}}}
+}
sub rcs_add ($) { # {{{
# Add file to archive.
run_or_cry('git', 'rm', '-f', $file);
} #}}}
+sub rcs_rename ($$) { # {{{
+ my ($src, $dest) = @_;
+
+ run_or_cry('git', 'mv', '-f', $src, $dest);
+} #}}}
+
sub rcs_recentchanges ($) { #{{{
# List of recent changes.