summaryrefslogtreecommitdiff
path: root/IkiWiki/Rcs/tla.pm
blob: 549e9f52d96ea051fa1425cb18f10838d1bba765 (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki;
  3. use warnings;
  4. use strict;
  5. use IkiWiki;
  6. hook(type => "getsetup", id => "tla", call => sub { #{{{
  7. return
  8. historyurl => {
  9. type => "string",
  10. default => "",
  11. #example => "", # TODO example
  12. description => "url to show file history ([[file]] substituted)",
  13. safe => 1,
  14. rebuild => 1,
  15. },
  16. diffurl => {
  17. type => "string",
  18. default => "",
  19. #example => "", # TODO example
  20. description => "url to show a diff ([[file]] and [[rev]] substituted)",
  21. safe => 1,
  22. rebuild => 1,
  23. },
  24. }); #}}}
  25. sub quiet_system (@) {
  26. # See Debian bug #385939.
  27. open (SAVEOUT, ">&STDOUT");
  28. close STDOUT;
  29. open (STDOUT, ">/dev/null");
  30. my $ret=system(@_);
  31. close STDOUT;
  32. open (STDOUT, ">&SAVEOUT");
  33. close SAVEOUT;
  34. return $ret;
  35. }
  36. sub rcs_update () { #{{{
  37. if (-d "$config{srcdir}/{arch}") {
  38. if (quiet_system("tla", "replay", "-d", $config{srcdir}) != 0) {
  39. warn("tla replay failed\n");
  40. }
  41. }
  42. } #}}}
  43. sub rcs_prepedit ($) { #{{{
  44. my $file=shift;
  45. if (-d "$config{srcdir}/{arch}") {
  46. # For Arch, return the tree-id of archive when
  47. # editing begins.
  48. my $rev=`tla tree-id $config{srcdir}`;
  49. return defined $rev ? $rev : "";
  50. }
  51. } #}}}
  52. sub rcs_commit ($$$;$$) { #{{{
  53. my $file=shift;
  54. my $message=shift;
  55. my $rcstoken=shift;
  56. my $user=shift;
  57. my $ipaddr=shift;
  58. if (defined $user) {
  59. $message="web commit by $user".(length $message ? ": $message" : "");
  60. }
  61. elsif (defined $ipaddr) {
  62. $message="web commit from $ipaddr".(length $message ? ": $message" : "");
  63. }
  64. if (-d "$config{srcdir}/{arch}") {
  65. # Check to see if the page has been changed by someone
  66. # else since rcs_prepedit was called.
  67. my ($oldrev)=$rcstoken=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
  68. my $rev=`tla tree-id $config{srcdir}`;
  69. if (defined $rev && defined $oldrev && $rev ne $oldrev) {
  70. # Merge their changes into the file that we've
  71. # changed.
  72. if (quiet_system("tla", "update", "-d",
  73. "$config{srcdir}") != 0) {
  74. warn("tla update failed\n");
  75. }
  76. }
  77. if (quiet_system("tla", "commit",
  78. "-L".possibly_foolish_untaint($message),
  79. '-d', $config{srcdir}) != 0) {
  80. my $conflict=readfile("$config{srcdir}/$file");
  81. if (system("tla", "undo", "-n", "--quiet", "-d", "$config{srcdir}") != 0) {
  82. warn("tla undo failed\n");
  83. }
  84. return $conflict;
  85. }
  86. }
  87. return undef # success
  88. } #}}}
  89. sub rcs_commit_staged ($$$) {
  90. # Commits all staged changes. Changes can be staged using rcs_add,
  91. # rcs_remove, and rcs_rename.
  92. my ($message, $user, $ipaddr)=@_;
  93. error("rcs_commit_staged not implemented for tla"); # TODO
  94. }
  95. sub rcs_add ($) { #{{{
  96. my $file=shift;
  97. if (-d "$config{srcdir}/{arch}") {
  98. if (quiet_system("tla", "add", "$config{srcdir}/$file") != 0) {
  99. warn("tla add failed\n");
  100. }
  101. }
  102. } #}}}
  103. sub rcs_remove ($) { # {{{
  104. my $file = shift;
  105. error("rcs_remove not implemented for tla"); # TODO
  106. } #}}}
  107. sub rcs_rename ($$) { # {{{a
  108. my ($src, $dest) = @_;
  109. error("rcs_rename not implemented for tla"); # TODO
  110. } #}}}
  111. sub rcs_recentchanges ($) {
  112. my $num=shift;
  113. my @ret;
  114. return unless -d "$config{srcdir}/{arch}";
  115. eval q{use Date::Parse};
  116. error($@) if $@;
  117. eval q{use Mail::Header};
  118. error($@) if $@;
  119. my $logs = `tla logs -d $config{srcdir}`;
  120. my @changesets = reverse split(/\n/, $logs);
  121. for (my $i=0; $i<$num && $i<$#changesets; $i++) {
  122. my ($change)=$changesets[$i]=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
  123. open(LOG, "tla cat-log -d $config{srcdir} $change|");
  124. my $head = Mail::Header->new(\*LOG);
  125. close(LOG);
  126. my $rev = $head->get("Revision");
  127. my $summ = $head->get("Summary");
  128. my $newfiles = $head->get("New-files");
  129. my $modfiles = $head->get("Modified-files");
  130. my $remfiles = $head->get("Removed-files");
  131. my $user = $head->get("Creator");
  132. my @paths = grep { !/^(.*\/)?\.arch-ids\/.*\.id$/ }
  133. split(/ /, "$newfiles $modfiles .arch-ids/fake.id");
  134. my $sdate = $head->get("Standard-date");
  135. my $when = str2time($sdate, 'UTC');
  136. my $committype = "web";
  137. if (defined $summ && $summ =~ /$config{web_commit_regexp}/) {
  138. $user = defined $2 ? "$2" : "$3";
  139. $summ = $4;
  140. }
  141. else {
  142. $committype="tla";
  143. }
  144. my @message;
  145. push @message, { line => $summ };
  146. my @pages;
  147. foreach my $file (@paths) {
  148. my $diffurl=$config{diffurl};
  149. $diffurl=~s/\[\[file\]\]/$file/g;
  150. $diffurl=~s/\[\[rev\]\]/$change/g;
  151. push @pages, {
  152. page => pagename($file),
  153. diffurl => $diffurl,
  154. } if length $file;
  155. }
  156. push @ret, {
  157. rev => $change,
  158. user => $user,
  159. committype => $committype,
  160. when => $when,
  161. message => [@message],
  162. pages => [@pages],
  163. } if @pages;
  164. last if $i == $num;
  165. }
  166. return @ret;
  167. }
  168. sub rcs_diff ($) { #{{{
  169. my $rev=shift;
  170. my $logs = `tla logs -d $config{srcdir}`;
  171. my @changesets = reverse split(/\n/, $logs);
  172. my $i;
  173. for($i=0;$i<$#changesets;$i++) {
  174. last if $changesets[$i] eq $rev;
  175. }
  176. my $revminusone = $changesets[$i+1];
  177. return `tla diff -d $config{srcdir} $revminusone`;
  178. } #}}}
  179. sub rcs_getctime ($) { #{{{
  180. my $file=shift;
  181. eval q{use Date::Parse};
  182. error($@) if $@;
  183. eval q{use Mail::Header};
  184. error($@) if $@;
  185. my $logs = `tla logs -d $config{srcdir}`;
  186. my @changesets = reverse split(/\n/, $logs);
  187. my $sdate;
  188. for (my $i=0; $i<$#changesets; $i++) {
  189. my $change = $changesets[$i];
  190. open(LOG, "tla cat-log -d $config{srcdir} $change|");
  191. my $head = Mail::Header->new(\*LOG);
  192. close(LOG);
  193. $sdate = $head->get("Standard-date");
  194. my $newfiles = $head->get("New-files");
  195. my ($lastcreation) = grep {/^$file$/} split(/ /, "$newfiles");
  196. last if defined($lastcreation);
  197. }
  198. my $date=str2time($sdate, 'UTC');
  199. debug("found ctime ".localtime($date)." for $file");
  200. return $date;
  201. } #}}}
  202. 1