2 # For subversion support.
9 my $svn_log_infoline=qr/^r(\d+)\s+\|\s+([^\s]+)\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/;
11 sub svn_info ($$) { #{{{
15 my $info=`LANG=C svn info $file`;
16 my ($ret)=$info=~/^$field: (.*)$/m;
20 sub rcs_update () { #{{{
21 if (-d "$config{srcdir}/.svn") {
22 if (system("svn", "update", "--quiet", $config{srcdir}) != 0) {
23 warn("svn update failed\n");
28 sub rcs_prepedit ($) { #{{{
29 # Prepares to edit a file under revision control. Returns a token
30 # that must be passed into rcs_commit when the file is ready
32 # The file is relative to the srcdir.
35 if (-d "$config{srcdir}/.svn") {
36 # For subversion, return the revision of the file when
38 my $rev=svn_info("Revision", "$config{srcdir}/$file");
39 return defined $rev ? $rev : "";
43 sub rcs_commit ($$$) { #{{{
44 # Tries to commit the page; returns undef on _success_ and
45 # a version of the page with the rcs's conflict markers on failure.
46 # The file is relative to the srcdir.
51 if (-d "$config{srcdir}/.svn") {
52 # Check to see if the page has been changed by someone
53 # else since rcs_prepedit was called.
54 my ($oldrev)=$rcstoken=~/^([0-9]+)$/; # untaint
55 my $rev=svn_info("Revision", "$config{srcdir}/$file");
56 if (defined $rev && defined $oldrev && $rev != $oldrev) {
57 # Merge their changes into the file that we've
59 chdir($config{srcdir}); # svn merge wants to be here
60 if (system("svn", "merge", "--quiet", "-r$oldrev:$rev",
61 "$config{srcdir}/$file") != 0) {
62 warn("svn merge -r$oldrev:$rev failed\n");
66 if (system("svn", "commit", "--quiet", "-m",
67 possibly_foolish_untaint($message),
68 "$config{srcdir}") != 0) {
69 my $conflict=readfile("$config{srcdir}/$file");
70 if (system("svn", "revert", "--quiet", "$config{srcdir}/$file") != 0) {
71 warn("svn revert failed\n");
76 return undef # success
79 sub rcs_add ($) { #{{{
80 # filename is relative to the root of the srcdir
83 if (-d "$config{srcdir}/.svn") {
84 my $parent=dirname($file);
85 while (! -d "$config{srcdir}/$parent/.svn") {
87 $parent=dirname($file);
90 if (system("svn", "add", "--quiet", "$config{srcdir}/$file") != 0) {
91 warn("svn add failed\n");
96 sub rcs_recentchanges ($) { #{{{
100 eval q{use CGI 'escapeHTML'};
101 eval q{use Date::Parse};
102 eval q{use Time::Duration};
104 if (-d "$config{srcdir}/.svn") {
105 my $svn_url=svn_info("URL", $config{srcdir});
107 # FIXME: currently assumes that the wiki is somewhere
108 # under trunk in svn, doesn't support other layouts.
109 my ($svn_base)=$svn_url=~m!(/trunk(?:/.*)?)$!;
111 my $div=qr/^--------------------+$/;
113 my ($rev, $user, $when, @pages, @message);
114 foreach (`LANG=C svn log --limit $num -v '$svn_url'`) {
116 if ($state eq 'start' && /$div/) {
119 elsif ($state eq 'header' && /$svn_log_infoline/) {
122 $when=concise(ago(time - str2time($3)));
124 elsif ($state eq 'header' && /^\s+[A-Z]\s+\Q$svn_base\E\/([^ ]+)(?:$|\s)/) {
126 my $diffurl=$config{diffurl};
127 $diffurl=~s/\[\[file\]\]/$file/g;
128 $diffurl=~s/\[\[r1\]\]/$rev - 1/eg;
129 $diffurl=~s/\[\[r2\]\]/$rev/g;
131 link => htmllink("", pagename($file), 1),
135 elsif ($state eq 'header' && /^$/) {
138 elsif ($state eq 'body' && /$div/) {
139 my $committype="web";
140 if (defined $message[0] &&
141 $message[0]->{line}=~/^web commit by (\w+):?(.*)/) {
143 $message[0]->{line}=$2;
149 push @ret, { rev => $rev,
150 user => htmllink("", $user, 1),
151 committype => $committype,
152 when => $when, message => [@message],
155 return @ret if @ret >= $num;
158 $rev=$user=$when=undef;
161 elsif ($state eq 'body') {
162 push @message, {line => escapeHTML($_)},
170 sub rcs_getctime () { #{{{
171 eval q{use Date::Parse};
172 foreach my $page (keys %pagectime) {
173 my $file="$config{srcdir}/$pagesources{$page}";
174 next unless -e $file;
175 my $child = open(SVNLOG, "-|");
177 exec("svn", "log", $file) || error("svn log $file failed to run");
182 if (/$svn_log_infoline/) {
186 close SVNLOG || warn "svn log $file exited $?";
188 if (! defined $date) {
189 warn "failed to parse svn log for $file\n";
193 $pagectime{$page}=$date=str2time($date);
194 debug("found ctime ".localtime($date)." for $page");