updated from pesco's darcs repo, current to Oct 11 version
authorJoey Hess <joey@kodama.kitenet.net>
Wed, 15 Oct 2008 23:38:21 +0000 (19:38 -0400)
committerJoey Hess <joey@kodama.kitenet.net>
Wed, 15 Oct 2008 23:38:21 +0000 (19:38 -0400)
IkiWiki/Plugin/darcs.pm
doc/ikiwiki-makerepo.mdwn
ikiwiki-makerepo

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