summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/autoindex.pm
blob: ba2dcb907ce9657f1792432e3efd4dec2f977f5f (plain)
  1. #!/usr/bin/perl
  2. package IkiWiki::Plugin::autoindex;
  3. use warnings;
  4. use strict;
  5. use IkiWiki 3.00;
  6. use Encode;
  7. sub import {
  8. hook(type => "getsetup", id => "autoindex", call => \&getsetup);
  9. hook(type => "refresh", id => "autoindex", call => \&refresh);
  10. }
  11. sub getsetup () {
  12. return
  13. plugin => {
  14. safe => 1,
  15. rebuild => 0,
  16. },
  17. }
  18. sub genindex ($) {
  19. my $page=shift;
  20. my $file=newpagefile($page, $config{default_pageext});
  21. add_autofile($file, "autoindex", sub {
  22. my $message = sprintf(gettext("creating index page %s"),
  23. $page);
  24. debug($message);
  25. my $template = template("autoindex.tmpl");
  26. $template->param(page => $page);
  27. writefile($file, $config{srcdir}, $template->output);
  28. if ($config{rcs}) {
  29. IkiWiki::disable_commit_hook();
  30. IkiWiki::rcs_add($file);
  31. IkiWiki::rcs_commit_staged(message => $message);
  32. IkiWiki::enable_commit_hook();
  33. }
  34. });
  35. }
  36. sub refresh () {
  37. eval q{use File::Find};
  38. error($@) if $@;
  39. eval q{use Cwd};
  40. error($@) if $@;
  41. my $origdir=getcwd();
  42. my (%pages, %dirs);
  43. foreach my $dir ($config{srcdir}, @{$config{underlaydirs}}, $config{underlaydir}) {
  44. chdir($dir) || next;
  45. find({
  46. no_chdir => 1,
  47. wanted => sub {
  48. my $file=decode_utf8($_);
  49. $file=~s/^\.\/?//;
  50. return unless length $file;
  51. if (IkiWiki::file_pruned($file)) {
  52. $File::Find::prune=1;
  53. }
  54. elsif (! -l $_) {
  55. my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint
  56. return unless defined $f;
  57. return if $f =~ /\._([^.]+)$/; # skip internal page
  58. if (! -d _) {
  59. $pages{pagename($f)}=1;
  60. }
  61. elsif ($dir eq $config{srcdir}) {
  62. $dirs{$f}=1;
  63. }
  64. }
  65. }
  66. }, '.');
  67. chdir($origdir) || die "chdir $origdir: $!";
  68. }
  69. # FIXME: some of this is probably redundant with add_autofile now, and
  70. # the rest should perhaps be added to the autofile machinery
  71. my %deleted;
  72. if (ref $wikistate{autoindex}{deleted}) {
  73. %deleted=%{$wikistate{autoindex}{deleted}};
  74. }
  75. elsif (ref $pagestate{index}{autoindex}{deleted}) {
  76. # compatability code
  77. %deleted=%{$pagestate{index}{autoindex}{deleted}};
  78. delete $pagestate{index}{autoindex};
  79. }
  80. if (keys %deleted) {
  81. foreach my $dir (keys %deleted) {
  82. # remove deleted page state if the deleted page is re-added,
  83. # or if all its subpages are deleted
  84. if ($deleted{$dir} && (exists $pages{$dir} ||
  85. ! grep /^$dir\/.*/, keys %pages)) {
  86. delete $deleted{$dir};
  87. }
  88. }
  89. $wikistate{autoindex}{deleted}=\%deleted;
  90. }
  91. my @needed;
  92. foreach my $dir (keys %dirs) {
  93. if (! exists $pages{$dir} && ! $deleted{$dir} &&
  94. grep /^$dir\/.*/, keys %pages) {
  95. if (exists $IkiWiki::pagemtime{$dir}) {
  96. # This page must have just been deleted, so
  97. # don't re-add it. And remember it was
  98. # deleted.
  99. if (! ref $wikistate{autoindex}{deleted}) {
  100. $wikistate{autoindex}{deleted}={};
  101. }
  102. ${$wikistate{autoindex}{deleted}}{$dir}=1;
  103. }
  104. else {
  105. push @needed, $dir;
  106. }
  107. }
  108. }
  109. if (@needed) {
  110. foreach my $page (@needed) {
  111. genindex($page);
  112. }
  113. }
  114. }
  115. 1