updated from pesco's darcs repo, current to Oct 11 version

master
Joey Hess 2008-10-15 19:38:21 -04:00
parent 1f7f5d5e0e
commit 7eb512205f
3 changed files with 356 additions and 353 deletions

View File

@ -45,465 +45,427 @@ use IkiWiki;
sub import { sub import {
hook(type => "checkconfig", id => "darcs", call => \&checkconfig); hook(type => "checkconfig", id => "darcs", call => \&checkconfig);
hook(type => "getsetup", id => "darcs", call => \&getsetup); hook(type => "getsetup", id => "darcs", call => \&getsetup);
hook(type => "rcs", id => "rcs_update", call => \&rcs_update); hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit); hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit); hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit);
hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged); hook(type => "rcs", id => "rcs_commit_staged", call => \&rcs_commit_staged);
hook(type => "rcs", id => "rcs_add", call => \&rcs_add); hook(type => "rcs", id => "rcs_add", call => \&rcs_add);
hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove); hook(type => "rcs", id => "rcs_remove", call => \&rcs_remove);
hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename); hook(type => "rcs", id => "rcs_rename", call => \&rcs_rename);
hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges); hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff); hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime); hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
} }
# Which darcs executable to use.
my $darcs = ($ENV{DARCS} or 'darcs');
# Internal functions # Internal functions
our %cache;
sub loadcache () {
my $repodir=$config{srcdir};
if (!defined %cache) {
my $f = "$repodir/.ikiwiki.ctimes";
if (-s "$f") {
my $VAR1;
my $x = `cat "$f"`;
$x =~ /^(.*)$/sm; # untaint
eval "$1";
%cache = %$VAR1;
}
}
}
END {
my $repodir=$config{srcdir};
if (defined %cache) {
debug("dumping ctime cache to $repodir/.ikiwiki.ctimes");
open CACHE, ">$repodir/.ikiwiki.ctimes";
print CACHE Dumper(\%cache);
close CACHE;
}
}
sub silentsystem (@) { sub silentsystem (@) {
open(SAVED_STDOUT, ">&STDOUT"); open(SAVED_STDOUT, ">&STDOUT");
open(STDOUT, ">/dev/null"); open(STDOUT, ">/dev/null");
my $ret = system @_; my $ret = system @_;
open(STDOUT, ">&SAVED_STDOUT"); open(STDOUT, ">&SAVED_STDOUT");
return $ret; return $ret;
} }
sub darcs_info ($$$) { sub darcs_info ($$$) {
my $field = shift; my $field = shift;
my $repodir = shift; my $repodir = shift;
my $file = shift; # Relative to the repodir. my $file = shift; # Relative to the repodir.
my $child = open(DARCS_CHANGES, "-|"); my $child = open(DARCS_CHANGES, "-|");
if (! $child) { if (! $child) {
exec($darcs, 'changes', '--repodir', $repodir, '--xml-output', $file) or exec('darcs', 'changes', '--repodir', $repodir, '--xml-output', $file) or
error("failed to run 'darcs changes'"); error("failed to run 'darcs changes'");
} }
# Brute force for now. :-/ # Brute force for now. :-/
while (<DARCS_CHANGES>) { while (<DARCS_CHANGES>) {
last if /^<\/created_as>$/; last if /^<\/created_as>$/;
} }
($_) = <DARCS_CHANGES> =~ /$field=\'([^\']+)/; ($_) = <DARCS_CHANGES> =~ /$field=\'([^\']+)/;
$field eq 'hash' and s/\.gz//; # Strip away the '.gz' from 'hash'es. $field eq 'hash' and s/\.gz//; # Strip away the '.gz' from 'hash'es.
close(DARCS_CHANGES) or error("'darcs changes' exited " . $?); close(DARCS_CHANGES) or error("'darcs changes' exited " . $?);
return $_; return $_;
} }
sub darcs_rev($) { sub darcs_rev($) {
my $file = shift; # Relative to the repodir. my $file = shift; # Relative to the repodir.
my $repodir = $config{srcdir}; my $repodir = $config{srcdir};
my $child = open(DARCS_MANIFEST, "-|"); my $child = open(DARCS_MANIFEST, "-|");
if (! $child) { if (! $child) {
exec($darcs, 'query', 'manifest', '--repodir', $repodir) or exec('darcs', 'query', 'manifest', '--repodir', $repodir) or
error("failed to run 'darcs query manifest'"); error("failed to run 'darcs query manifest'");
} }
my $found=0; my $found=0;
while (<DARCS_MANIFEST>) { while (<DARCS_MANIFEST>) {
$found = 1, last if /^$file$/; $found = 1, last if /^$file$/;
} }
return "" if (! $found); return "" if (! $found);
close(DARCS_MANIFEST) or error("'darcs query manifest' exited " . $?); close(DARCS_MANIFEST) or error("'darcs query manifest' exited " . $?);
my $hash = darcs_info('hash', $repodir, $file); my $hash = darcs_info('hash', $repodir, $file);
return defined $hash ? $hash : ""; return defined $hash ? $hash : "";
} }
# Exported functions. # Exported functions.
sub checkconfig() { sub checkconfig() {
if (defined $config{darcs_wrapper} && length $config{darcs_wrapper}) { if (defined $config{darcs_wrapper} && length $config{darcs_wrapper}) {
push @{$config{wrappers}}, { push @{$config{wrappers}}, {
wrapper => $config{darcs_wrapper}, wrapper => $config{darcs_wrapper},
wrappermode => (defined $config{darcs_wrappermode} ? $config{darcs_wrappermode} : "06755"), wrappermode => (defined $config{darcs_wrappermode} ? $config{darcs_wrappermode} : "06755"),
}; };
} }
} }
sub getsetup() { sub getsetup() {
return return
plugin => { plugin => {
safe => 0, # rcs plugin safe => 0, # rcs plugin
rebuild => undef, rebuild => undef,
}, },
darcs_wrapper => { darcs_wrapper => {
type => "string", type => "string",
example => "/darcs/repo/_darcs/ikiwiki-wrapper", example => "/darcs/repo/_darcs/ikiwiki-wrapper",
description => "wrapper to generate (set as master repo apply hook)", description => "wrapper to generate (set as master repo apply hook)",
safe => 0, # file safe => 0, # file
rebuild => 0, rebuild => 0,
}, },
darcs_wrappermode => { darcs_wrappermode => {
type => "string", type => "string",
example => '06755', example => '06755',
description => "mode for darcs_wrapper (can safely be made suid)", description => "mode for darcs_wrapper (can safely be made suid)",
safe => 0, safe => 0,
rebuild => 0, rebuild => 0,
}, },
historyurl => { historyurl => {
type => "string", type => "string",
example => "http://darcs.example.com/darcsweb.cgi?r=wiki;a=filehistory;f=[[file]]", example => "http://darcs.example.com/darcsweb.cgi?r=wiki;a=filehistory;f=[[file]]",
description => "darcsweb url to show file history ([[file]] substituted)", description => "darcsweb url to show file history ([[file]] substituted)",
safe => 1, safe => 1,
rebuild => 1, rebuild => 1,
}, },
diffurl => { diffurl => {
type => "string", type => "string",
example => "http://darcs.example.com/darcsweb.cgi?r=wiki;a=filediff;h=[[hash]];f=[[file]]", example => "http://darcs.example.com/darcsweb.cgi?r=wiki;a=filediff;h=[[hash]];f=[[file]]",
description => "darcsweb url to show a diff ([[hash]] and [[file]] substituted)", description => "darcsweb url to show a diff ([[hash]] and [[file]] substituted)",
safe => 1, safe => 1,
rebuild => 1, rebuild => 1,
}, },
} }
sub rcs_update () { sub rcs_update () {
silentsystem($darcs, "pull", "--repodir", $config{srcdir}, "-qa") silentsystem('darcs', "pull", "--repodir", $config{srcdir}, "-qa")
} }
sub rcs_prepedit ($) { sub rcs_prepedit ($) {
# Prepares to edit a file under revision control. Returns a token that # Prepares to edit a file under revision control. Returns a token that
# must be passed to rcs_commit() when the file is to be commited. For us, # must be passed to rcs_commit() when the file is to be commited. For us,
# this token the hash value of the latest patch that modifies the file, # this token the hash value of the latest patch that modifies the file,
# i.e. something like its current revision. If the file is not yet added # i.e. something like its current revision. If the file is not yet added
# to the repository, we return TODO: the empty string. # to the repository, we return TODO: the empty string.
my $file = shift; # Relative to the repodir. my $file = shift; # Relative to the repodir.
my $rev = darcs_rev($file); my $rev = darcs_rev($file);
return $rev; return $rev;
} }
sub rcs_commit ($$$;$$) { sub rcs_commit ($$$;$$) {
# Commit the page. Returns 'undef' on success and a version of the page # Commit the page. Returns 'undef' on success and a version of the page
# with conflict markers on failure. # with conflict markers on failure.
my ($file, $message, $rcstoken, $user, $ipaddr) = @_; my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
# Compute if the "revision" of $file changed. # Compute if the "revision" of $file changed.
my $changed = darcs_rev($file) ne $rcstoken; my $changed = darcs_rev($file) ne $rcstoken;
# Yes, the following is a bit convoluted. # Yes, the following is a bit convoluted.
if ($changed) { if ($changed) {
# TODO. Invent a better, non-conflicting name. # TODO. Invent a better, non-conflicting name.
rename("$config{srcdir}/$file", "$config{srcdir}/$file.save") or rename("$config{srcdir}/$file", "$config{srcdir}/$file.save") or
error("failed to rename $file to $file.save: $!"); error("failed to rename $file to $file.save: $!");
# Roll the repository back to $rcstoken. # Roll the repository back to $rcstoken.
# TODO. Can we be sure that no changes are lost? I think that # TODO. Can we be sure that no changes are lost? I think that
# we can, if we make sure that the 'darcs push' below will always # we can, if we make sure that the 'darcs push' below will always
# succeed. # succeed.
# We need to revert everything as 'darcs obliterate' might choke # We need to revert everything as 'darcs obliterate' might choke
# otherwise. # otherwise.
# TODO: 'yes | ...' needed? Doesn't seem so. # TODO: 'yes | ...' needed? Doesn't seem so.
silentsystem($darcs, "revert", "--repodir", $config{srcdir}, "--all") and silentsystem('darcs', "revert", "--repodir", $config{srcdir}, "--all") and
error("'darcs revert' failed"); error("'darcs revert' failed");
# Remove all patches starting at $rcstoken. # Remove all patches starting at $rcstoken.
my $child = open(DARCS_OBLITERATE, "|-"); my $child = open(DARCS_OBLITERATE, "|-");
if (! $child) { if (! $child) {
open(STDOUT, ">/dev/null"); open(STDOUT, ">/dev/null");
exec($darcs, "obliterate", "--repodir", $config{srcdir}, exec('darcs', "obliterate", "--repodir", $config{srcdir},
"--match", "hash " . $rcstoken) and "--match", "hash " . $rcstoken) and
error("'darcs obliterate' failed"); error("'darcs obliterate' failed");
} }
while (print DARCS_OBLITERATE "y") { while (print DARCS_OBLITERATE "y") {
; ;
} }
close(DARCS_OBLITERATE); close(DARCS_OBLITERATE);
# Restore the $rcstoken one. # Restore the $rcstoken one.
silentsystem($darcs, "pull", "--quiet", "--repodir", $config{srcdir}, silentsystem('darcs', "pull", "--quiet", "--repodir", $config{srcdir},
"--match", "hash " . $rcstoken, "--all") and "--match", "hash " . $rcstoken, "--all") and
error("'darcs pull' failed"); error("'darcs pull' failed");
# We're back at $rcstoken. Re-install the modified file. # We're back at $rcstoken. Re-install the modified file.
rename("$config{srcdir}/$file.save", "$config{srcdir}/$file") or rename("$config{srcdir}/$file.save", "$config{srcdir}/$file") or
error("failed to rename $file.save to $file: $!"); error("failed to rename $file.save to $file: $!");
} }
# Record the changes. # Record the changes.
my $author; my $author;
if (defined $user) { if (defined $user) {
$author = "$user\@web"; $author = "$user\@web";
} elsif (defined $ipaddr) { } elsif (defined $ipaddr) {
$author = "$ipaddr\@web"; $author = "$ipaddr\@web";
} else { } else {
$author = "anon\@web"; $author = "anon\@web";
} }
if (!defined $message || !length($message)) { if (!defined $message || !length($message)) {
$message = "empty message"; $message = "empty message";
} }
silentsystem($darcs, 'record', '--repodir', $config{srcdir}, '--all', silentsystem('darcs', 'record', '--repodir', $config{srcdir}, '--all',
'-m', $message, '--author', $author, $file) and '-m', $message, '--author', $author, $file) and
error("'darcs record' failed"); error("'darcs record' failed");
# Update the repository by pulling from the default repository, which is # Update the repository by pulling from the default repository, which is
# master repository. # master repository.
silentsystem($darcs, "pull", "--quiet", "--repodir", $config{srcdir}, silentsystem('darcs', "pull", "--quiet", "--repodir", $config{srcdir},
"--all") and error("'darcs pull' failed"); "--all") and error("'darcs pull' failed");
# If this updating yields any conflicts, we'll record them now to resolve # If this updating yields any conflicts, we'll record them now to resolve
# them. If nothing is recorded, there are no conflicts. # them. If nothing is recorded, there are no conflicts.
$rcstoken = darcs_rev($file); $rcstoken = darcs_rev($file);
# TODO: Use only the first line here, i.e. only the patch name? # TODO: Use only the first line here, i.e. only the patch name?
writefile("$file.log", $config{srcdir}, 'resolve conflicts: ' . $message); writefile("$file.log", $config{srcdir}, 'resolve conflicts: ' . $message);
silentsystem($darcs, 'record', '--repodir', $config{srcdir}, '--all', silentsystem('darcs', 'record', '--repodir', $config{srcdir}, '--all',
'-m', 'resolve conflicts: ' . $message, '--author', $author, $file) and '-m', 'resolve conflicts: ' . $message, '--author', $author, $file) and
error("'darcs record' failed"); error("'darcs record' failed");
my $conflicts = darcs_rev($file) ne $rcstoken; my $conflicts = darcs_rev($file) ne $rcstoken;
unlink("$config{srcdir}/$file.log") or unlink("$config{srcdir}/$file.log") or
error("failed to remove '$file.log'"); error("failed to remove '$file.log'");
# Push the changes to the main repository. # Push the changes to the main repository.
silentsystem($darcs, 'push', '--quiet', '--repodir', $config{srcdir}, '--all') silentsystem('darcs', 'push', '--quiet', '--repodir', $config{srcdir}, '--all')
and error("'darcs push' failed"); and error("'darcs push' failed");
# TODO: darcs send? # TODO: darcs send?
if ($conflicts) { if ($conflicts) {
my $document = readfile("$config{srcdir}/$file"); my $document = readfile("$config{srcdir}/$file");
# Try to leave everything in a consistent state. # Try to leave everything in a consistent state.
# TODO: 'yes | ...' needed? Doesn't seem so. # TODO: 'yes | ...' needed? Doesn't seem so.
silentsystem($darcs, "revert", "--repodir", $config{srcdir}, "--all") and silentsystem('darcs', "revert", "--repodir", $config{srcdir}, "--all") and
warn("'darcs revert' failed"); warn("'darcs revert' failed");
return $document; return $document;
} else { } else {
return undef; return undef;
} }
} }
sub rcs_commit_staged($$$) { sub rcs_commit_staged($$$) {
my ($message, $user, $ipaddr) = @_; my ($message, $user, $ipaddr) = @_;
my $author; my $author;
if (defined $user) { if (defined $user) {
$author = "$user\@web"; $author = "$user\@web";
} elsif (defined $ipaddr) { } elsif (defined $ipaddr) {
$author = "$ipaddr\@web"; $author = "$ipaddr\@web";
} else { } else {
$author = "anon\@web"; $author = "anon\@web";
} }
if (!defined $message || !length($message)) { if (!defined $message || !length($message)) {
$message = "empty message"; $message = "empty message";
} }
silentsystem($darcs, "record", "--repodir", $config{srcdir}, "-a", "-A", $author, silentsystem('darcs', "record", "--repodir", $config{srcdir}, "-a", "-A", $author,
"-m", $message) and error("'darcs record' failed"); "-m", $message) and error("'darcs record' failed");
# Push the changes to the main repository. # Push the changes to the main repository.
silentsystem($darcs, 'push', '--quiet', '--repodir', $config{srcdir}, '--all') silentsystem('darcs', 'push', '--quiet', '--repodir', $config{srcdir}, '--all')
and error("'darcs push' failed"); and error("'darcs push' failed");
# TODO: darcs send? # TODO: darcs send?
return undef; return undef;
} }
sub rcs_add ($) { sub rcs_add ($) {
my $file = shift; # Relative to the repodir. my $file = shift; # Relative to the repodir.
# Intermediate directories will be added automagically. # Intermediate directories will be added automagically.
system($darcs, 'add', '--quiet', '--repodir', $config{srcdir}, system('darcs', 'add', '--quiet', '--repodir', $config{srcdir},
'--boring', $file) and error("'darcs add' failed"); '--boring', $file) and error("'darcs add' failed");
} }
sub rcs_remove ($) { sub rcs_remove ($) {
my $file = shift; # Relative to the repodir. my $file = shift; # Relative to the repodir.
system('rm', $config{srcdir}.'/'.$file) unlink($config{srcdir}.'/'.$file);
and error("'rm' failed");
} }
sub rcs_rename ($$) { sub rcs_rename ($$) {
my $a = shift; # Relative to the repodir. my $a = shift; # Relative to the repodir.
my $b = shift; # Relative to the repodir. my $b = shift; # Relative to the repodir.
system($darcs, 'mv', '--repodir', $config{srcdir}, $a, $b) system('darcs', 'mv', '--repodir', $config{srcdir}, $a, $b)
and error("'darcs mv' failed"); and error("'darcs mv' failed");
} }
sub rcs_recentchanges ($) { sub rcs_recentchanges ($) {
my $num=shift; my $num=shift;
my @ret; my @ret;
eval q{use Date::Parse}; eval q{use Date::Parse};
eval q{use XML::Simple}; eval q{use XML::Simple};
my $repodir=$config{srcdir}; my $repodir=$config{srcdir};
debug("darcs recent changes: $num"); debug("darcs recent changes: $num");
my $child = open(LOG, "-|"); my $child = open(LOG, "-|");
if (! $child) { if (! $child) {
$ENV{"DARCS_DONT_ESCAPE_ANYTHING"}=1; $ENV{"DARCS_DONT_ESCAPE_ANYTHING"}=1;
exec("darcs", "changes", "--xml", exec("darcs", "changes", "--xml",
"--summary", "--summary",
"--repodir", "$repodir", "--repodir", "$repodir",
"--last", "$num") "--last", "$num")
|| error("'darcs changes' failed to run"); || error("'darcs changes' failed to run");
} }
my $data; my $data;
$data .= $_ while(<LOG>); $data .= $_ while(<LOG>);
close LOG; close LOG;
my $log = XMLin($data, ForceArray => 1); my $log = XMLin($data, ForceArray => 1);
debug("parsing recent changes..."); debug("parsing recent changes...");
foreach my $patch (@{$log->{patch}}) { foreach my $patch (@{$log->{patch}}) {
my $date=$patch->{local_date}; my $date=$patch->{local_date};
my $hash=$patch->{hash}; my $hash=$patch->{hash};
my $when=str2time($date); my $when=str2time($date);
my (@pages, @files, @pg); my (@pages, @files, @pg);
push @pages, $_ for (@{$patch->{summary}->[0]->{modify_file}}); push @pages, $_ for (@{$patch->{summary}->[0]->{modify_file}});
push @pages, $_ for (@{$patch->{summary}->[0]->{add_file}}); push @pages, $_ for (@{$patch->{summary}->[0]->{add_file}});
push @pages, $_ for (@{$patch->{summary}->[0]->{remove_file}}); push @pages, $_ for (@{$patch->{summary}->[0]->{remove_file}});
for (@pages) { for (@pages) {
my $f = $_; my $f = $_;
$f = $_->{content} if (ref $_); $f = $_->{content} if (ref $_);
$f =~ s,^\s+,,; $f =~ s,\s+$,,; # cut whitespace $f =~ s,^\s+,,; $f =~ s,\s+$,,; # cut whitespace
push @files, $f; push @files, $f;
} }
for (@{$patch->{summary}->[0]->{move}}) { for (@{$patch->{summary}->[0]->{move}}) {
my $p = $_; my $p = $_;
push @files, $p->{from}; push @files, $p->{from};
} }
for (@files) { for (@files) {
my $f = $_; my $f = $_;
my $d = defined $config{'diffurl'} ? $config{'diffurl'} : ""; my $d = defined $config{'diffurl'} ? $config{'diffurl'} : "";
$d =~ s/\[\[file\]\]/$f/go; $d =~ s/\[\[file\]\]/$f/go;
$d =~ s/\[\[hash\]\]/$hash/go; $d =~ s/\[\[hash\]\]/$hash/go;
debug("file: $f"); debug("file: $f");
debug("diffurl: $d"); debug("diffurl: $d");
push @pg, { push @pg, {
page => pagename($f), page => pagename($f),
diffurl => $d, diffurl => $d,
}; };
} }
next unless (scalar @pg > 0); next unless (scalar @pg > 0);
debug("recent change: " . $patch->{name}[0] . " (" debug("recent change: " . $patch->{name}[0] . " ("
. scalar @pg . " changes)"); . scalar @pg . " changes)");
my @message; my @message;
push @message, { line => $_ } for (@{$patch->{name}}); push @message, { line => $_ } for (@{$patch->{name}});
my $committype; my $committype;
if ($patch->{author} =~ /\@web$/) { if ($patch->{author} =~ /\@web$/) {
$committype = "web"; $committype = "web";
} else { } else {
$committype = "darcs"; $committype = "darcs";
} }
push @ret, { push @ret, {
rev => $patch->{hash}, rev => $patch->{hash},
user => $patch->{author}, user => $patch->{author},
committype => $committype, committype => $committype,
when => $when, when => $when,
message => [@message], message => [@message],
pages => [@pg], pages => [@pg],
}; };
} }
return @ret; return @ret;
} }
sub rcs_diff ($) { sub rcs_diff ($) {
my $rev=shift; my $rev=shift;
my @lines; my @lines;
foreach my $line (silentsystem("darcs", "diff", "--match", "hash ".$rev)) { foreach my $line (silentsystem("darcs", "diff", "--match", "hash ".$rev)) {
if (@lines || $line=~/^diff/) { if (@lines || $line=~/^diff/) {
push @lines, $line."\n"; push @lines, $line."\n";
} }
} }
if (wantarray) { if (wantarray) {
return @lines; return @lines;
} }
else { else {
return join("", @lines); return join("", @lines);
} }
} }
sub rcs_getctime ($) { sub rcs_getctime ($) {
my $file=shift; my $file=shift;
eval q{use Date::Parse}; eval q{use Date::Parse};
eval q{use XML::Simple}; eval q{use XML::Simple};
local $/=undef; local $/=undef;
# Sigh... doing things the hard way again # Sigh... doing things the hard way again
my $repodir=$config{srcdir}; my $repodir=$config{srcdir};
&loadcache; my $filer=substr($file, length($repodir));
$filer =~ s:^[/]+::;
my $filer=substr($file, length($repodir)); my $child = open(LOG, "-|");
$filer =~ s:^[/]+::; if (! $child) {
exec("darcs", "changes", "--xml", "--reverse",
"--repodir", "$repodir", "$filer")
|| error("'darcs changes $filer' failed to run");
}
if (defined $cache{$filer}) { my $data;
#debug("taking cached ctime ".localtime($cache{$filer})." for $filer"); $data .= $_ while(<LOG>);
return $cache{$filer}; close LOG;
}
my $child = open(LOG, "-|"); my $log = XMLin($data, ForceArray => 1);
if (! $child) {
exec("darcs", "changes", "--xml", "--reverse",
"--repodir", "$repodir", "$filer")
|| error("'darcs changes $filer' failed to run");
}
my $data; my $datestr=$log->{patch}[0]->{local_date};
$data .= $_ while(<LOG>);
close LOG;
my $log = XMLin($data, ForceArray => 1); if (! defined $datestr) {
warn "failed to get ctime for $filer";
return 0;
}
my $datestr=$log->{patch}[0]->{local_date}; my $date=str2time($datestr);
if (! defined $datestr) { #debug("found ctime ".localtime($date)." for $filer");
warn "failed to get ctime for $filer";
$cache{$filer} = 0;
return 0;
}
my $date=str2time($datestr); return $date;
#debug("found ctime ".localtime($date)." for $filer");
$cache{$filer} = $date;
return $date;
} }
1 1
# vim: ts=4 sw=4 noet

View File

@ -4,9 +4,9 @@ ikiwiki-makerepo - check an ikiwiki srcdir into revision control
# SYNOPSIS # SYNOPSIS
ikiwiki-makerepo svn|git|monotone srcdir repository ikiwiki-makerepo svn|git|monotone|darcs srcdir repository
ikiwiki-makerepo mercurial srcdir ikiwiki-makerepo mercurial|darcs srcdir
# DESCRIPTION # DESCRIPTION
@ -17,6 +17,13 @@ mercurial repository.
Note that for mercurial, the srcdir is converted into a mercurial Note that for mercurial, the srcdir is converted into a mercurial
repository. There is no need to have a separate repository with mercurial. repository. There is no need to have a separate repository with mercurial.
For darcs, the second (one-argument) form turns the given srcdir into a
darcs master repository with the (new) srcdir inside. Adjust your ikiwiki.setup
according to the command output! Also, the master repo's apply hook will be
preconfigured to call a (hypothetical) ikiwiki wrapper. The command
reports the relevant file. Adjust it as needed or remove it if you don't use
the cgi script.
Note that for monotone, you are assumed to already have run "mtn genkey" to generate Note that for monotone, you are assumed to already have run "mtn genkey" to generate
key. key.

View File

@ -6,8 +6,8 @@ srcdir="$2"
repository="$3" repository="$3"
usage () { usage () {
echo "usage: ikiwiki-makerepo svn|git|monotone srcdir repository" >&2 echo "usage: ikiwiki-makerepo svn|git|monotone|darcs srcdir repository" >&2
echo " ikiwiki-makerepo bzr|mercurial srcdir" >&2 echo " ikiwiki-makerepo bzr|mercurial|darcs srcdir" >&2
exit 1 exit 1
} }
@ -20,7 +20,7 @@ if [ ! -d "$srcdir" ]; then
exit 1 exit 1
fi fi
if [ "$rcs" != mercurial ] && [ "$rcs" != bzr ]; then if [ "$rcs" != mercurial ] && [ "$rcs" != bzr ] && [ "$rcs" != darcs ]; then
if [ -z "$repository" ]; then if [ -z "$repository" ]; then
echo "you need to specify both a srcdir and a repository for $rcs" >&2 echo "you need to specify both a srcdir and a repository for $rcs" >&2
usage usage
@ -121,6 +121,40 @@ monotone)
echo ' return "passphrasehere"' echo ' return "passphrasehere"'
echo "end" echo "end"
;; ;;
darcs)
if [ -e "$srcdir/_darcs" ]; then
echo "$srcdir already seems to be a darcs repository" >&2
exit 1
fi
# if only one arg is given, we turn the given srcdir into the darcs
# master repo with a hidden srcdir inside its _darcs directory.
if [ -z "$repository" ]; then
echo "Turning $srcdir into master repo."
repository="$srcdir"
srcdir="$srcdir/_darcs/srcdir"
echo "The new srcdir is $srcdir - adjust ikiwiki.setup accordingly!"
fi
mkdir -p "$repository"
cd "$repository"
darcs initialize
mkdir -p "$srcdir"
cd "$srcdir"
darcs initialize
echo .ikiwiki >> _darcs/prefs/boring
darcs record -a -l -q -m "initial import"
darcs pull -a -q "$repository"
darcs push -a -q "$repository"
echo "Directory $srcdir is now a branch of darcs repo $repository"
# set up master repo's apply hook and tell user to adjust it if desired
darcsdefaults="$repository/_darcs/prefs/defaults"
echo "Preconfiguring apply hook in $darcsdefaults - adjust as desired!"
echo "apply posthook $repository/_darcs/ikiwrapper" >> "$darcsdefaults"
echo "apply run-posthook" >> "$darcsdefaults"
;;
*) *)
echo "Unsupported revision control system $rcs" >&2 echo "Unsupported revision control system $rcs" >&2
usage usage