From 4af4d26582f0c2b915d7102fb4a604b176385748 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sat, 30 Jan 2010 10:25:10 +0100 Subject: Make srcfile() return undef, if the file isn't there. This has the advantage that it's now possible to check for the existence of a sourcefile with that function. --- IkiWiki.pm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index b8e599928..cb1c46a68 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -743,7 +743,10 @@ sub srcfile_stat { } sub srcfile ($;$) { - return (srcfile_stat(@_))[0]; + if (my @stat=srcfile_stat(@_)) { + return $stat[0]; + } + return undef } sub add_underlay ($) { -- cgit v1.2.3 From f3abeac919c4736429bd3362af6edf51ede8e7fe Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sat, 30 Jan 2010 18:12:01 +0100 Subject: Code deduplication fin find_src_files() This also has the advantage that I can use the resulting new function elsewhere. --- IkiWiki/Render.pm | 59 +++++++++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 3ebb1a324..44b2fb9c2 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -280,6 +280,27 @@ sub srcdir_check () { } +sub verify_src_file ($$) { + my $file=decode_utf8(shift); + my $dir=shift; + + return if -l $file || -d $file; + $file=~s/^\Q$dir\E\/?//; + return if ! length $file; + my $page = pagename($file); + if (! exists $pagesources{$page} && + file_pruned($file)) { + $File::Find::prune=1; + return; + } + + my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint + if (! defined $f) { + warn(sprintf(gettext("skipping bad filename %s"), $file)."\n"); + } + return ($file,$page,$f); +} + sub find_src_files () { my @files; my %pages; @@ -288,22 +309,9 @@ sub find_src_files () { find({ no_chdir => 1, wanted => sub { - my $file=decode_utf8($_); - $file=~s/^\Q$config{srcdir}\E\/?//; - return if -l $_ || -d _ || ! length $file; - my $page = pagename($file); - if (! exists $pagesources{$page} && - file_pruned($file)) { - $File::Find::prune=1; - return; - } - - my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint - if (! defined $f) { - warn(sprintf(gettext("skipping bad filename %s"), $file)."\n"); - } - else { - push @files, $f; + my ($file,$page,$f) = verify_src_file($_,$config{srcdir}); + if ($file) { + push @files, $file; if ($pages{$page}) { debug(sprintf(gettext("%s has multiple possible source pages"), $page)); } @@ -315,24 +323,11 @@ sub find_src_files () { find({ no_chdir => 1, wanted => sub { - my $file=decode_utf8($_); - $file=~s/^\Q$dir\E\/?//; - return if -l $_ || -d _ || ! length $file; - my $page=pagename($file); - if (! exists $pagesources{$page} && - file_pruned($file)) { - $File::Find::prune=1; - return; - } - - my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint - if (! defined $f) { - warn(sprintf(gettext("skipping bad filename %s"), $file)."\n"); - } - else { + my ($file,$page,$f) = verify_src_file($_,$dir); + if ($f) { # avoid underlaydir override # attacks; see security.mdwn - if (! -l "$config{srcdir}/$f" && + if (! -l "$config{srcdir}/$f" && ! -e _) { if (! $pages{$page}) { push @files, $f; -- cgit v1.2.3 From f35d35abe36166893f68061a1fcb2a26bc056fbc Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sat, 30 Jan 2010 18:22:32 +0100 Subject: Automatically create tag pages, if "tag_autocreate=1" is set in the configuration. The pages will be created in tagbase, if and only if they do not exist in the srcdir yet. Tag pages will be create from "autotag.tmpl". At this stage a second refresh is needed for the tag pages to be rendered. Add autotag.tmpl template. --- IkiWiki/Plugin/tag.pm | 26 ++++++++++++++++++++++++++ templates/autotag.tmpl | 3 +++ 2 files changed, 29 insertions(+) create mode 100644 templates/autotag.tmpl diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index cdcfaf536..6c43a053d 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -36,6 +36,13 @@ sub getsetup () { safe => 1, rebuild => 1, }, + tag_autocreate => { + type => "boolean", + example => 0, + description => "Autocreate new tag pages", + safe => 1, + rebuild => 1, + }, } sub tagpage ($) { @@ -59,6 +66,21 @@ sub taglink ($$$;@) { return htmllink($page, $destpage, tagpage($tag), %opts); } +sub gentag ($) { + my $tag=shift; + if (defined $config{tag_autocreate} && $config{tag_autocreate}) { + my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); + $tagfile=~s/^\///; + return if (srcfile($tagfile,1)); + + debug(sprintf(gettext("creating tag page %s"), $tag)); + + my $template=template("autotag.tmpl"); + $template->param(tag => $tag); + writefile($tagfile, $config{srcdir}, $template->output); + } +} + sub preprocess_tag (@) { if (! @_) { return ""; @@ -72,6 +94,10 @@ sub preprocess_tag (@) { foreach my $tag (keys %params) { $tag=linkpage($tag); $tags{$page}{$tag}=1; + + # add tagpage if necessary + gentag($tag); + # hidden WikiLink add_link($page, tagpage($tag)); } diff --git a/templates/autotag.tmpl b/templates/autotag.tmpl new file mode 100644 index 000000000..754e0b35b --- /dev/null +++ b/templates/autotag.tmpl @@ -0,0 +1,3 @@ +## Pagest tagged ## + +[[!inline pages="tagged()" actions="no" archive="yes"]] -- cgit v1.2.3 From b18fde2bde0c7d445fd4aab3cd35add8c211aab4 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sun, 31 Jan 2010 02:31:12 +0100 Subject: Add a function add_autofiles(). The objective is to provide a sensible way to let plugins add files during the "scan stage" of the build. Currently does a little verification and adds the file to the global array @add_autofiles. --- IkiWiki.pm | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index cb1c46a68..115c512d3 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -14,7 +14,7 @@ use open qw{:utf8 :std}; use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %pagestate %wikistate %renderedfiles %oldrenderedfiles %pagesources %destsources %depends %depends_simple %hooks - %forcerebuild %loaded_plugins}; + %forcerebuild %loaded_plugins @autofiles}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage deptype @@ -1898,6 +1898,14 @@ sub add_link ($$) { unless grep { $_ eq $link } @{$links{$page}}; } +sub add_autofile ($) { + my $addfile=shift; + my ($file,$page) = verify_src_file($addfile,$config{srcdir}); + if ($page) { + push @autofiles, $file; + } +} + sub pagespec_translate ($) { my $spec=shift; -- cgit v1.2.3 From f3c59ed3e52f6e68e73338f6e7799a4de7b6f9d6 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sun, 31 Jan 2010 02:23:11 +0100 Subject: Process files from @autofiles in refresh(). To make automatically added files render they have to be added to the $files, $pages, $new, and $changed variables. After that scan() is called on them. --- IkiWiki/Render.pm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 44b2fb9c2..dd4d9ca0c 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -642,6 +642,20 @@ sub refresh () { scan($file); } + while (my $autofile = shift (@autofiles)) { + my $page=pagename($autofile); + if ($pages->{$page}) { + debug(sprintf(gettext("%s has multiple possible source pages"), $page)); + } + $pages->{$page}=1; + + push @{$files}, $autofile; + push @{$new}, $autofile if find_new_files([$autofile]); + push @{$changed}, $autofile if find_changed([$autofile]); + + scan($autofile); + } + calculate_links(); remove_del(@$del, @$internal_del); -- cgit v1.2.3 From a8d313aba1094fc6d976c9ba3d09f58b768435c5 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sun, 31 Jan 2010 01:12:20 +0100 Subject: Use add_autofile() in tag.pm to make the automatically created tagpages render. --- IkiWiki/Plugin/tag.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 6c43a053d..90833fd9c 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -78,6 +78,8 @@ sub gentag ($) { my $template=template("autotag.tmpl"); $template->param(tag => $tag); writefile($tagfile, $config{srcdir}, $template->output); + + IkiWiki::add_autofile("$config{srcdir}/$tagfile"); } } -- cgit v1.2.3 From f58f3e1bec41ccf9316f37b014ce0b373c8e49e1 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Tue, 2 Feb 2010 11:01:24 +0100 Subject: Revert the effects of find_del_files() for (re)autoadded files. This also means that if autoadded files are deleted they will just be recreated. --- IkiWiki.pm | 3 ++- IkiWiki/Render.pm | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 115c512d3..ad9fb7c79 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -14,7 +14,8 @@ use open qw{:utf8 :std}; use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %pagestate %wikistate %renderedfiles %oldrenderedfiles %pagesources %destsources %depends %depends_simple %hooks - %forcerebuild %loaded_plugins @autofiles}; + %forcerebuild %loaded_plugins @autofiles %dellinks + %delrenderedfiles}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage deptype diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index dd4d9ca0c..d2fa80fbb 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -392,7 +392,9 @@ sub find_del_files ($) { else { push @del, $pagesources{$page}; } + $dellinks{$page}= $links{$page}; $links{$page}=[]; + $delrenderedfiles{$page}= $renderedfiles{$page}; $renderedfiles{$page}=[]; $pagemtime{$page}=0; } @@ -642,8 +644,14 @@ sub refresh () { scan($file); } + my %del_hash = map {$_, 1} @$del; while (my $autofile = shift (@autofiles)) { my $page=pagename($autofile); + if (exists $del_hash{$page}) { + $links{$page}= $dellinks{$page}; + $renderedfiles{$page}= $delrenderedfiles{$page}; + delete $del_hash{$page}; + } if ($pages->{$page}) { debug(sprintf(gettext("%s has multiple possible source pages"), $page)); } @@ -655,6 +663,7 @@ sub refresh () { scan($autofile); } + $del = [keys %del_hash]; calculate_links(); -- cgit v1.2.3 From 25741100b0a0d81ae5113dfabe5a1ed84cdf8746 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Tue, 2 Feb 2010 12:12:23 +0100 Subject: Export add_autofile() for use in Plugins. --- IkiWiki.pm | 2 +- IkiWiki/Plugin/tag.pm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index ad9fb7c79..7d7f430b3 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -23,7 +23,7 @@ our @EXPORT = qw(hook debug error template htmlpage deptype htmllink readfile writefile pagetype srcfile pagename displaytime will_render gettext urlto targetpage add_underlay pagetitle titlepage linkpage newpagefile - inject add_link + inject add_link add_autofile %config %links %pagestate %wikistate %renderedfiles %pagesources %destsources); our $VERSION = 3.00; # plugin interface version, next is ikiwiki version diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 90833fd9c..c0b7feb23 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -79,7 +79,7 @@ sub gentag ($) { $template->param(tag => $tag); writefile($tagfile, $config{srcdir}, $template->output); - IkiWiki::add_autofile("$config{srcdir}/$tagfile"); + add_autofile("$config{srcdir}/$tagfile"); } } -- cgit v1.2.3 From 9330b91703ba245ceb9c36e0682b8cfc0d225eaa Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Tue, 2 Feb 2010 16:29:27 +0100 Subject: fix typo in autotag.tmpl --- templates/autotag.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/autotag.tmpl b/templates/autotag.tmpl index 754e0b35b..a8824171b 100644 --- a/templates/autotag.tmpl +++ b/templates/autotag.tmpl @@ -1,3 +1,3 @@ -## Pagest tagged ## +## Pages tagged ## [[!inline pages="tagged()" actions="no" archive="yes"]] -- cgit v1.2.3 From bd1e29b8c4d2c2e0329789d1baf0a879617aeee4 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Wed, 3 Feb 2010 02:35:19 +0100 Subject: Revert "Make srcfile() return undef, if the file isn't there." This reverts commit 1bde208ec9b915db0187030c33450b5accb4892c. --- IkiWiki.pm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 7d7f430b3..90e623330 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -744,10 +744,7 @@ sub srcfile_stat { } sub srcfile ($;$) { - if (my @stat=srcfile_stat(@_)) { - return $stat[0]; - } - return undef + return (srcfile_stat(@_))[0]; } sub add_underlay ($) { -- cgit v1.2.3 From da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Wed, 3 Feb 2010 06:57:20 +0100 Subject: fix bugs in `find_src_files()`. Use `_` to avoid superfluous stat. Check for `defined $file`, instead of just `$file`. Add spaces after commas. Change return values of `verify_src_file()` to not return the tainted filename. Rename `$f` to `$file_untainted in `verify_src_file()`. $f changes to `$file` in `find_src_files()`. This attempts to fix commit f3abeac919c4736429bd3362af6edf51ede8e7fe. For discussion see --- IkiWiki/Render.pm | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index d2fa80fbb..5b72b6de1 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -284,7 +284,7 @@ sub verify_src_file ($$) { my $file=decode_utf8(shift); my $dir=shift; - return if -l $file || -d $file; + return if -l $file || -d _; $file=~s/^\Q$dir\E\/?//; return if ! length $file; my $page = pagename($file); @@ -294,11 +294,11 @@ sub verify_src_file ($$) { return; } - my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint - if (! defined $f) { + my ($file_untainted) = $file =~ /$config{wiki_file_regexp}/; # untaint + if (! defined $file_untainted) { warn(sprintf(gettext("skipping bad filename %s"), $file)."\n"); } - return ($file,$page,$f); + return ($file_untainted, $page); } sub find_src_files () { @@ -309,8 +309,8 @@ sub find_src_files () { find({ no_chdir => 1, wanted => sub { - my ($file,$page,$f) = verify_src_file($_,$config{srcdir}); - if ($file) { + my ($file, $page) = verify_src_file($_, $config{srcdir}); + if (defined $file) { push @files, $file; if ($pages{$page}) { debug(sprintf(gettext("%s has multiple possible source pages"), $page)); @@ -323,14 +323,14 @@ sub find_src_files () { find({ no_chdir => 1, wanted => sub { - my ($file,$page,$f) = verify_src_file($_,$dir); - if ($f) { + my ($file, $page) = verify_src_file($_, $dir); + if (defined $file) { # avoid underlaydir override # attacks; see security.mdwn - if (! -l "$config{srcdir}/$f" && + if (! -l "$config{srcdir}/$file" && ! -e _) { if (! $pages{$page}) { - push @files, $f; + push @files, $file; $pages{$page}=1; } } -- cgit v1.2.3 From a358d74bef51dae31332ff27e897fe04834571e6 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Wed, 3 Feb 2010 04:29:10 +0100 Subject: Check for existence off srcfile in add_autofile add_autofile has to have checks, whether to create the file, anyway, so this will make things more consistent. Correcter check for the result of verify_src_file(). Cosmetic rename of a variable $addfile to $autofile. --- IkiWiki.pm | 11 ++++++++--- IkiWiki/Plugin/tag.pm | 5 ++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 90e623330..56c491339 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1897,9 +1897,14 @@ sub add_link ($$) { } sub add_autofile ($) { - my $addfile=shift; - my ($file,$page) = verify_src_file($addfile,$config{srcdir}); - if ($page) { + my $autofile=shift; + + if (srcfile($autofile, 1)) { + return 0; + } + + my ($file, $page) = verify_src_file("$config{srcdir}/$autofile", $config{srcdir}); + if (defined $file) { push @autofiles, $file; } } diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index c0b7feb23..c6c99ae45 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -71,15 +71,14 @@ sub gentag ($) { if (defined $config{tag_autocreate} && $config{tag_autocreate}) { my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); $tagfile=~s/^\///; - return if (srcfile($tagfile,1)); + + return if (! add_autofile($tagfile)); debug(sprintf(gettext("creating tag page %s"), $tag)); my $template=template("autotag.tmpl"); $template->param(tag => $tag); writefile($tagfile, $config{srcdir}, $template->output); - - add_autofile("$config{srcdir}/$tagfile"); } } -- cgit v1.2.3 From 628a52a6c49f5d2fc5af251f2d718c8dff5e8ed5 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sat, 3 Apr 2010 21:17:20 +0200 Subject: Revert "Revert the effects of find_del_files() for (re)autoadded files." This reverts commit 31680111f0062f07727d14fcf291c98978ad5a2f. --- IkiWiki.pm | 3 +-- IkiWiki/Render.pm | 9 --------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 56c491339..1770703a5 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -14,8 +14,7 @@ use open qw{:utf8 :std}; use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %pagestate %wikistate %renderedfiles %oldrenderedfiles %pagesources %destsources %depends %depends_simple %hooks - %forcerebuild %loaded_plugins @autofiles %dellinks - %delrenderedfiles}; + %forcerebuild %loaded_plugins @autofiles}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage deptype diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 5b72b6de1..fc71c8919 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -392,9 +392,7 @@ sub find_del_files ($) { else { push @del, $pagesources{$page}; } - $dellinks{$page}= $links{$page}; $links{$page}=[]; - $delrenderedfiles{$page}= $renderedfiles{$page}; $renderedfiles{$page}=[]; $pagemtime{$page}=0; } @@ -644,14 +642,8 @@ sub refresh () { scan($file); } - my %del_hash = map {$_, 1} @$del; while (my $autofile = shift (@autofiles)) { my $page=pagename($autofile); - if (exists $del_hash{$page}) { - $links{$page}= $dellinks{$page}; - $renderedfiles{$page}= $delrenderedfiles{$page}; - delete $del_hash{$page}; - } if ($pages->{$page}) { debug(sprintf(gettext("%s has multiple possible source pages"), $page)); } @@ -663,7 +655,6 @@ sub refresh () { scan($autofile); } - $del = [keys %del_hash]; calculate_links(); -- cgit v1.2.3 From 981400177d68a279f485727be3f013e68f0bf691 Mon Sep 17 00:00:00 2001 From: David Riebenbauer Date: Sat, 3 Apr 2010 21:10:16 +0200 Subject: Make sure deleted tag pages don't get recreated. The reason to do this is basically a user interaction design decision. It is achieved by adding an entry, associated to the creating plugin, to %pagestate. To find out if files were deleted a new global hash %del_hash is %introduced. --- IkiWiki.pm | 19 +++++++++++++++---- IkiWiki/Plugin/tag.pm | 2 +- IkiWiki/Render.pm | 5 ++++- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 1770703a5..966a3bbc6 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -14,7 +14,7 @@ use open qw{:utf8 :std}; use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %pagestate %wikistate %renderedfiles %oldrenderedfiles %pagesources %destsources %depends %depends_simple %hooks - %forcerebuild %loaded_plugins @autofiles}; + %forcerebuild %loaded_plugins %autofiles %del_hash}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage deptype @@ -1895,17 +1895,28 @@ sub add_link ($$) { unless grep { $_ eq $link } @{$links{$page}}; } -sub add_autofile ($) { +sub add_autofile ($$) { my $autofile=shift; + my $plugin=shift; if (srcfile($autofile, 1)) { return 0; } my ($file, $page) = verify_src_file("$config{srcdir}/$autofile", $config{srcdir}); - if (defined $file) { - push @autofiles, $file; + + if ((!defined $file) || + (exists $pagestate{$page}{$plugin}{autofile_deleted})) { + return 0; + } + + if (exists $del_hash{$file}) { + $pagestate{$page}{$plugin}{autofile_deleted}=1; + return 0; } + + $autofiles{$file}=$plugin; + return 1; } sub pagespec_translate ($) { diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index c6c99ae45..fdd63d637 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -72,7 +72,7 @@ sub gentag ($) { my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); $tagfile=~s/^\///; - return if (! add_autofile($tagfile)); + return if (! add_autofile($tagfile, "tag")); debug(sprintf(gettext("creating tag page %s"), $tag)); diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index fc71c8919..0c21455fb 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -637,12 +637,14 @@ sub refresh () { my ($changed, $internal_changed)=find_changed($files); run_hooks(needsbuild => sub { shift->($changed) }); my $oldlink_targets=calculate_old_links($changed, $del); + %del_hash = map { $_ => 1 } @{$del}; foreach my $file (@$changed) { scan($file); } - while (my $autofile = shift (@autofiles)) { + while (my $autofile = shift @{[keys %autofiles]}) { + my $plugin=$autofiles{$autofile}; my $page=pagename($autofile); if ($pages->{$page}) { debug(sprintf(gettext("%s has multiple possible source pages"), $page)); @@ -654,6 +656,7 @@ sub refresh () { push @{$changed}, $autofile if find_changed([$autofile]); scan($autofile); + delete $autofiles{$autofile}; } calculate_links(); -- cgit v1.2.3 From 2269a4c74b24378d8e7e2229ca3374a197d08d9c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 12:54:22 -0400 Subject: whitespace --- IkiWiki.pm | 24 ++++++++++++------------ IkiWiki/Render.pm | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 2f26a16ce..3812961dc 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -12,20 +12,20 @@ use Storable; use open qw{:utf8 :std}; use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase - %pagestate %wikistate %renderedfiles %oldrenderedfiles - %pagesources %destsources %depends %depends_simple %hooks - %forcerebuild %loaded_plugins %typedlinks %oldtypedlinks - %autofiles %del_hash}; + %pagestate %wikistate %renderedfiles %oldrenderedfiles + %pagesources %destsources %depends %depends_simple %hooks + %forcerebuild %loaded_plugins %typedlinks %oldtypedlinks + %autofiles %del_hash}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage deptype - add_depends pagespec_match pagespec_match_list bestlink - htmllink readfile writefile pagetype srcfile pagename - displaytime will_render gettext ngettext urlto targetpage - add_underlay pagetitle titlepage linkpage newpagefile - inject add_link add_autofile - %config %links %pagestate %wikistate %renderedfiles - %pagesources %destsources %typedlinks); + add_depends pagespec_match pagespec_match_list bestlink + htmllink readfile writefile pagetype srcfile pagename + displaytime will_render gettext ngettext urlto targetpage + add_underlay pagetitle titlepage linkpage newpagefile + inject add_link add_autofile + %config %links %pagestate %wikistate %renderedfiles + %pagesources %destsources %typedlinks); our $VERSION = 3.00; # plugin interface version, next is ikiwiki version our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE @@ -1891,7 +1891,7 @@ sub define_gettext () { return shift; } }; - *ngettext=sub { + *ngettext=sub { $getobj->() if $getobj; if ($gettext_obj) { $gettext_obj->nget(@_); diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 796af6af2..c80030deb 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -43,7 +43,7 @@ sub backlinks ($) { my @links; foreach my $p (backlink_pages($page)) { my $href=urlto($p, $page); - + # Trim common dir prefixes from both pages. my $p_trimmed=$p; my $page_trimmed=$page; -- cgit v1.2.3 From b7d50abc0f3dbe99d2a3664c12ea95d24bfcf04b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 13:35:15 -0400 Subject: refactor autofiles Made add_autofile take a generator function, and just register the autofile, for later possible creation. The testing is moved into Render, which allows cleaning up some stuff. --- IkiWiki.pm | 35 ++++++++++------------------------ IkiWiki/Plugin/tag.pm | 12 ++++++------ IkiWiki/Render.pm | 52 +++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/IkiWiki.pm b/IkiWiki.pm index 3812961dc..c22c75df8 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -15,7 +15,7 @@ use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase %pagestate %wikistate %renderedfiles %oldrenderedfiles %pagesources %destsources %depends %depends_simple %hooks %forcerebuild %loaded_plugins %typedlinks %oldtypedlinks - %autofiles %del_hash}; + %autofiles}; use Exporter q{import}; our @EXPORT = qw(hook debug error template htmlpage deptype @@ -1956,6 +1956,15 @@ sub add_link ($$;$) { } } +sub add_autofile ($$$) { + my $file=shift; + my $plugin=shift; + my $generator=shift; + + $autofiles{$file}{plugin}=$plugin; + $autofiles{$file}{generator}=$generator; +} + sub sortspec_translate ($$) { my $spec = shift; my $reverse = shift; @@ -2021,30 +2030,6 @@ sub sortspec_translate ($$) { return eval 'sub { '.$code.' }'; } -sub add_autofile ($$) { - my $autofile=shift; - my $plugin=shift; - - if (srcfile($autofile, 1)) { - return 0; - } - - my ($file, $page) = verify_src_file("$config{srcdir}/$autofile", $config{srcdir}); - - if ((!defined $file) || - (exists $pagestate{$page}{$plugin}{autofile_deleted})) { - return 0; - } - - if (exists $del_hash{$file}) { - $pagestate{$page}{$plugin}{autofile_deleted}=1; - return 0; - } - - $autofiles{$file}=$plugin; - return 1; -} - sub pagespec_translate ($) { my $spec=shift; diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 9e6f417bf..7a918a4e8 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -70,13 +70,13 @@ sub gentag ($) { my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); $tagfile=~s/^\///; - return if (! add_autofile($tagfile, "tag")); + add_autofile($tagfile, sub { + debug(sprintf(gettext("creating tag page %s"), $tag)); - debug(sprintf(gettext("creating tag page %s"), $tag)); - - my $template=template("autotag.tmpl"); - $template->param(tag => $tag); - writefile($tagfile, $config{srcdir}, $template->output); + my $template=template("autotag.tmpl"); + $template->param(tag => $tag); + writefile($tagfile, $config{srcdir}, $template->output); + }); } } diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index c80030deb..83242a197 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -680,6 +680,37 @@ sub render_backlinks ($) { } } +sub gen_autofile ($$$) { + my $autofile=shift; + my $pages=shift; + my $del=shift; + + if (srcfile($autofile, 1)) { + return 0; + } + + my ($file, $page) = verify_src_file("$config{srcdir}/$autofile", $config{srcdir}); + + if ((!defined $file) || + (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile_deleted})) { + return 0; + } + + if ($pages->{$page}) { + return 0; + } + + if (grep { $_ eq $file } @$del) { + $wikistate{$autofiles{$autofile}{generator}}{autofile_deleted}=1; + return 0; + } + + $autofiles{$autofile}{generator}->(); + $pages->{$page}=1; + return 1; +} + + sub refresh () { srcdir_check(); run_hooks(refresh => sub { shift->() }); @@ -689,26 +720,19 @@ sub refresh () { my ($changed, $internal_changed)=find_changed($files); run_hooks(needsbuild => sub { shift->($changed) }); my $oldlink_targets=calculate_old_links($changed, $del); - %del_hash = map { $_ => 1 } @{$del}; foreach my $file (@$changed) { scan($file); } - while (my $autofile = shift @{[keys %autofiles]}) { - my $plugin=$autofiles{$autofile}; - my $page=pagename($autofile); - if ($pages->{$page}) { - debug(sprintf(gettext("%s has multiple possible source pages"), $page)); + foreach my $autofile (keys %autofiles) { + if (gen_autofile($autofile, $pages, $del)) { + push @{$files}, $autofile; + push @{$new}, $autofile if find_new_files([$autofile]); + push @{$changed}, $autofile if find_changed([$autofile]); + + scan($autofile); } - $pages->{$page}=1; - - push @{$files}, $autofile; - push @{$new}, $autofile if find_new_files([$autofile]); - push @{$changed}, $autofile if find_changed([$autofile]); - - scan($autofile); - delete $autofiles{$autofile}; } calculate_links(); -- cgit v1.2.3 From ca02c57ee47d4c05946c0c34eee32a0ad4ec6b01 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 14:07:12 -0400 Subject: document add_autofile --- doc/plugins/write.mdwn | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 0bf6fcf48..e33c99421 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -966,6 +966,22 @@ added. Pass it the page that contains the link, and the link text. An optional third parameter sets the link type. If not specified, it is an ordinary [[ikiwiki/WikiLink]]. +### `add_autofile($$$)` + +Sometimes you may want to add a file to the `srcdir`. For example, +[[plugins/tag]] pages can be automatically created as needed. This function +can be used to do that. + +The three parameters are the filename to add, the name of the plugin, +and a callback function. The callback will be called if it is appropriate +to automatically add the file, and should then take care of creating it, +and doing anything else it needs to (such as checking it into revision +control). Note that the callback may not always be called. For example, +if an automatically added file is deleted by the user, ikiwiki will avoid +re-adding it again. + +This function needs to be called during the scan hook, or earlier to work. + ## Miscellaneous ### Internal use pages -- cgit v1.2.3 From adc196a8b53c0b0b4f9ec4cbcea85ba37e421b59 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 15:40:39 -0400 Subject: tag_autocreate fixups Fix style of prompt. Optional to rebuild when it is changed. (Needed to get new all missing tags) --- IkiWiki/Plugin/tag.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 7a918a4e8..1145a9f13 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -37,9 +37,9 @@ sub getsetup () { tag_autocreate => { type => "boolean", example => 0, - description => "Autocreate new tag pages", + description => "autocreate new tag pages?", safe => 1, - rebuild => 1, + rebuild => undef, }, } @@ -66,7 +66,7 @@ sub taglink ($$$;@) { sub gentag ($) { my $tag=shift; - if (defined $config{tag_autocreate} && $config{tag_autocreate}) { + if ($config{tag_autocreate}) { my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); $tagfile=~s/^\///; -- cgit v1.2.3 From 3651e6263c55a0b6184fe46c856a96740621361f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 15:43:58 -0400 Subject: fix autofile call --- IkiWiki/Plugin/tag.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 1145a9f13..957b012ef 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -70,7 +70,7 @@ sub gentag ($) { my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); $tagfile=~s/^\///; - add_autofile($tagfile, sub { + add_autofile($tagfile, "tag", sub { debug(sprintf(gettext("creating tag page %s"), $tag)); my $template=template("autotag.tmpl"); -- cgit v1.2.3 From b00d8771cc212349ca886401bc68facdf08e0d3c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 15:48:00 -0400 Subject: call gentag for taglinks too --- IkiWiki/Plugin/tag.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 957b012ef..9f6df5fc4 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -45,7 +45,7 @@ sub getsetup () { sub tagpage ($) { my $tag=shift; - + if ($tag !~ m{^\.?/} && defined $config{tagbase}) { $tag="/".$config{tagbase}."/".$tag; @@ -96,7 +96,6 @@ sub preprocess_tag (@) { # hidden WikiLink add_link($page, tagpage($tag), 'tag'); - # add tagpage if necessary gentag($tag); } @@ -112,12 +111,14 @@ sub preprocess_taglink (@) { if (/(.*)\|(.*)/) { my $tag=linkpage($2); add_link($params{page}, tagpage($tag), 'tag'); + gentag($tag); return taglink($params{page}, $params{destpage}, $tag, linktext => pagetitle($1)); } else { my $tag=linkpage($_); add_link($params{page}, tagpage($tag), 'tag'); + gentag($tag); return taglink($params{page}, $params{destpage}, $tag); } } -- cgit v1.2.3 From 2fc342b048d23d8355631000b7285fb5d26b258a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 16:01:41 -0400 Subject: fix autotag behavior for relative tags A tag like ./foo is searched for relative to the tagging page. However, if multiple pages use such a tag, the only one sure to be in common is in the root, so autocreate it there to avoid scattering redunadant autocreated tags around the tree. (This is probably not ideal.) Also renamed the tagpage and taglink functions for clarity. --- IkiWiki/Plugin/tag.pm | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 9f6df5fc4..d2a3d4dfd 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -43,7 +43,7 @@ sub getsetup () { }, } -sub tagpage ($) { +sub taglink ($) { my $tag=shift; if ($tag !~ m{^\.?/} && @@ -55,20 +55,28 @@ sub tagpage ($) { return $tag; } -sub taglink ($$$;@) { +sub htmllink_tag ($$$;@) { my $page=shift; my $destpage=shift; my $tag=shift; my %opts=@_; - return htmllink($page, $destpage, tagpage($tag), %opts); + return htmllink($page, $destpage, taglink($tag), %opts); } sub gentag ($) { my $tag=shift; + if ($config{tag_autocreate}) { - my $tagfile = newpagefile(tagpage($tag), $config{default_pageext}); - $tagfile=~s/^\///; + my $tagpage=taglink($tag); + if ($tagpage=~/^\.\/(.*)/) { + $tagpage=$1; + } + else { + $tagpage=~s/^\///; + } + + my $tagfile = newpagefile($tagpage, $config{default_pageext}); add_autofile($tagfile, "tag", sub { debug(sprintf(gettext("creating tag page %s"), $tag)); @@ -94,7 +102,7 @@ sub preprocess_tag (@) { $tag=linkpage($tag); # hidden WikiLink - add_link($page, tagpage($tag), 'tag'); + add_link($page, taglink($tag), 'tag'); gentag($tag); } @@ -110,16 +118,16 @@ sub preprocess_taglink (@) { return join(" ", map { if (/(.*)\|(.*)/) { my $tag=linkpage($2); - add_link($params{page}, tagpage($tag), 'tag'); + add_link($params{page}, taglink($tag), 'tag'); gentag($tag); - return taglink($params{page}, $params{destpage}, $tag, + return htmllink_tag($params{page}, $params{destpage}, $tag, linktext => pagetitle($1)); } else { my $tag=linkpage($_); - add_link($params{page}, tagpage($tag), 'tag'); + add_link($params{page}, taglink($tag), 'tag'); gentag($tag); - return taglink($params{page}, $params{destpage}, $tag); + return htmllink_tag($params{page}, $params{destpage}, $tag); } } grep { @@ -137,7 +145,7 @@ sub pagetemplate (@) { $template->param(tags => [ map { - link => taglink($page, $destpage, $_, rel => "tag") + link => htmllink_tag($page, $destpage, $_, rel => "tag") }, sort keys %$tags ]) if defined $tags && %$tags && $template->query(name => "tags"); @@ -153,7 +161,7 @@ sub pagetemplate (@) { package IkiWiki::PageSpec; sub match_tagged ($$;@) { - return match_link($_[0], IkiWiki::Plugin::tag::tagpage($_[1]), linktype => 'tag'); + return match_link($_[0], IkiWiki::Plugin::tag::taglink($_[1]), linktype => 'tag'); } 1 -- cgit v1.2.3 From f78e6798aa5482e534d7254b87a7b58e9fcc0145 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 16:08:37 -0400 Subject: move decode_utf8 closer to reason for it Filenames need to be decoded, as File::Find does not provide them in decoded form, but other callers of verify_src_file will be using utf8. --- IkiWiki/Render.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 83242a197..fff9dcce6 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -282,7 +282,7 @@ sub srcdir_check () { } sub verify_src_file ($$) { - my $file=decode_utf8(shift); + my $file=shift; my $dir=shift; return if -l $file || -d _; @@ -310,7 +310,7 @@ sub find_src_files () { find({ no_chdir => 1, wanted => sub { - my ($file, $page) = verify_src_file($_, $config{srcdir}); + my ($file, $page) = verify_src_file(decode_utf8($_), $config{srcdir}); if (defined $file) { push @files, $file; if ($pages{$page}) { @@ -324,7 +324,7 @@ sub find_src_files () { find({ no_chdir => 1, wanted => sub { - my ($file, $page) = verify_src_file($_, $dir); + my ($file, $page) = verify_src_file(decode_utf8($_), $dir); if (defined $file) { # avoid underlaydir override # attacks; see security.mdwn -- cgit v1.2.3 From 831b891abdc68d1b111381d6559cebd5a9b6c78f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 16:14:15 -0400 Subject: move File::Find control back into its code blocks Ok, this is longer, but features less scary action at a distance. --- IkiWiki/Render.pm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index fff9dcce6..41f179a50 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -291,7 +291,6 @@ sub verify_src_file ($$) { my $page = pagename($file); if (! exists $pagesources{$page} && file_pruned($file)) { - $File::Find::prune=1; return; } @@ -318,6 +317,9 @@ sub find_src_files () { } $pages{$page}=1; } + else { + $File::Find::prune=1; + } }, }, $config{srcdir}); foreach my $dir (@{$config{underlaydirs}}, $config{underlaydir}) { @@ -336,6 +338,9 @@ sub find_src_files () { } } } + else { + $File::Find::prune=1; + } }, }, $dir); }; -- cgit v1.2.3 From 59ceeb5621ae0ae2bcb7501c6ac0c7a06562a7cc Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 17 Apr 2010 17:15:07 -0400 Subject: improve docs --- doc/plugins/write.mdwn | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index e33c99421..5190a26ed 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -968,9 +968,9 @@ it is an ordinary [[ikiwiki/WikiLink]]. ### `add_autofile($$$)` -Sometimes you may want to add a file to the `srcdir`. For example, -[[plugins/tag]] pages can be automatically created as needed. This function -can be used to do that. +Sometimes you may want to add a file to the `srcdir` as a result of content +of other pages. For example, [[plugins/tag]] pages can be automatically +created as needed. This function can be used to do that. The three parameters are the filename to add, the name of the plugin, and a callback function. The callback will be called if it is appropriate @@ -980,7 +980,8 @@ control). Note that the callback may not always be called. For example, if an automatically added file is deleted by the user, ikiwiki will avoid re-adding it again. -This function needs to be called during the scan hook, or earlier to work. +This function needs to be called during the scan hook, or earlier in the +build process, in order to add the file early enough for it to be built. ## Miscellaneous -- cgit v1.2.3 From 9c8761ba49b06a76a923eb91735f842f419d2916 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 14:27:12 -0400 Subject: add_autofile filename should be relative to srcdir --- doc/plugins/write.mdwn | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 5190a26ed..404c3b44f 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -972,13 +972,13 @@ Sometimes you may want to add a file to the `srcdir` as a result of content of other pages. For example, [[plugins/tag]] pages can be automatically created as needed. This function can be used to do that. -The three parameters are the filename to add, the name of the plugin, -and a callback function. The callback will be called if it is appropriate -to automatically add the file, and should then take care of creating it, -and doing anything else it needs to (such as checking it into revision -control). Note that the callback may not always be called. For example, -if an automatically added file is deleted by the user, ikiwiki will avoid -re-adding it again. +The three parameters are the filename to create (relative to the `srcdir`), +the name of the plugin, and a callback function. The callback will be +called if it is appropriate to automatically add the file, and should then +take care of creating it, and doing anything else it needs to (such as +checking it into revision control). Note that the callback may not always +be called. For example, if an automatically added file is deleted by the +user, ikiwiki will avoid re-adding it again. This function needs to be called during the scan hook, or earlier in the build process, in order to add the file early enough for it to be built. -- cgit v1.2.3 From 034b4e826627dddf47ff27278897804e39741e57 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 15:05:59 -0400 Subject: remove verify_src_file Splitting out this function bothered me. It is conceptially similar to file_pruned, and yet also very specific to exactly the security needs of find_src_files. I liked that it got rid of duplicate code in the latter function. So instead, put a helper sub in that, which I think allows refactoring things more cleanly, and with less boilerplate. As to the needs of gen_autofile, I'm not convinced this needs to handle the same set of problems that verify_src_file did. So I sat down and wrote a custom validator for autofiles, which turned out to seem to just need three things: Make sure the candidate filename is not something that would be pruned; untaint the candidate filename; and make sure that srcdir doesn't already have something with its name. (Plus, of course, all the other checks that were already in gen_autofile.) (In passing, also fixed a bunch of bugs I had introduced in this branch.) --- IkiWiki/Render.pm | 115 ++++++++++++++++++++++++++---------------------------- 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 03b2910fd..14f6f9d5f 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -281,68 +281,59 @@ sub srcdir_check () { } -sub verify_src_file ($$) { - my $file=shift; - my $dir=shift; - - return if -l $file || -d _; - $file=~s/^\Q$dir\E\/?//; - return if ! length $file; - my $page = pagename($file); - if (! exists $pagesources{$page} && - file_pruned($file)) { - return; - } - - my ($file_untainted) = $file =~ /$config{wiki_file_regexp}/; # untaint - if (! defined $file_untainted) { - warn(sprintf(gettext("skipping bad filename %s"), $file)."\n"); - } - return ($file_untainted, $page); -} - sub find_src_files () { my @files; my %pages; eval q{use File::Find}; error($@) if $@; - find({ - no_chdir => 1, - wanted => sub { - my ($file, $page) = verify_src_file(decode_utf8($_), $config{srcdir}); - if (defined $file) { - push @files, $file; - if ($pages{$page}) { - debug(sprintf(gettext("%s has multiple possible source pages"), $page)); + + my ($page, $dir, $underlay); + my $helper=sub { + my $file=decode_utf8($_); + + return if -l $file || -d _; + $file=~s/^\Q$dir\E\/?//; + return if ! length $file; + $page = pagename($file); + if (! exists $pagesources{$page} && + file_pruned($file)) { + $File::Find::prune=1; + return; + } + + my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint + if (! defined $f) { + warn(sprintf(gettext("skipping bad filename %s"), $file)."\n"); + } + + if ($underlay) { + # avoid underlaydir override attacks; see security.mdwn + if (! -l "$config{srcdir}/$f" && ! -e _) { + if (! $pages{$page}) { + push @files, $f; + $pages{$page}=1; } - $pages{$page}=1; } - else { - $File::Find::prune=1; + } + else { + push @files, $f; + if ($pages{$page}) { + debug(sprintf(gettext("%s has multiple possible source pages"), $page)); } - }, - }, $config{srcdir}); - foreach my $dir (@{$config{underlaydirs}}, $config{underlaydir}) { + $pages{$page}=1; + } + }; + + find({ + no_chdir => 1, + wanted => $helper, + }, $dir=$config{srcdir}); + $underlay=1; + foreach (@{$config{underlaydirs}}, $config{underlaydir}) { find({ no_chdir => 1, - wanted => sub { - my ($file, $page) = verify_src_file(decode_utf8($_), $dir); - if (defined $file) { - # avoid underlaydir override - # attacks; see security.mdwn - if (! -l "$config{srcdir}/$file" && - ! -e _) { - if (! $pages{$page}) { - push @files, $file; - $pages{$page}=1; - } - } - } - else { - $File::Find::prune=1; - } - }, - }, $dir); + wanted => $helper, + }, $dir=$_); }; return \@files, \%pages; } @@ -691,24 +682,28 @@ sub gen_autofile ($$$) { my $pages=shift; my $del=shift; - if (srcfile($autofile, 1)) { - return 0; + if (srcfile($autofile, 1) || file_pruned($autofile)) { + return; } - - my ($file, $page) = verify_src_file("$config{srcdir}/$autofile", $config{srcdir}); + my $file="$config{srcdir}/$autofile" =~ /$config{wiki_file_regexp}/; # untaint + if (! defined $file || -l $file || -d _ || -e _) { + return; + } + if ((!defined $file) || (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile_deleted})) { - return 0; + return; } + my $page = pagename($file); if ($pages->{$page}) { - return 0; + return; } if (grep { $_ eq $file } @$del) { - $wikistate{$autofiles{$autofile}{generator}}{autofile_deleted}=1; - return 0; + $wikistate{$autofiles{$autofile}{plugin}}{autofile_deleted}=1; + return; } $autofiles{$autofile}{generator}->(); -- cgit v1.2.3 From 204c0a63f3fd7673dac83da6aa5f9c9e3cc9a6c5 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 15:22:05 -0400 Subject: document tag_autocreate --- debian/changelog | 2 ++ doc/plugins/tag.mdwn | 3 +++ doc/roadmap.mdwn | 1 + 3 files changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index b7ec99463..d66b5e4d4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,8 @@ ikiwiki (3.20100415) UNRELEASED; urgency=low [ Joey Hess ] + * tag: Automatic creation of tag pages can now be enabled using + the tag_autocreate setting. (David Riebenbauer) * bzr: Fix bzr log parsing to work with bzr 2.0. (liw) * comments: Fix missing entity encoding in title. * txt: Add a special case for robots.txt. diff --git a/doc/plugins/tag.mdwn b/doc/plugins/tag.mdwn index 8ff70a069..bdf39d7e8 100644 --- a/doc/plugins/tag.mdwn +++ b/doc/plugins/tag.mdwn @@ -8,6 +8,9 @@ These directives allow tagging pages. It also provides the `tagged()` [[ikiwiki/PageSpec]], which can be used to match pages that are tagged with a specific tag. +If the `tag_autocreate` setting is enabled, tag pages will automatically be +created as needed. + [[!if test="enabled(tag)" then=""" This wiki has the tag plugin enabled, so you'll see a note below that this page is tagged with the "tags" tag. diff --git a/doc/roadmap.mdwn b/doc/roadmap.mdwn index 0c7bf2fa8..8e2a01827 100644 --- a/doc/roadmap.mdwn +++ b/doc/roadmap.mdwn @@ -78,6 +78,7 @@ Probably incomplete list: * Make pagespecs match relative by default? (see [[discussion]]) * Flip wikilinks? (see [[todo/link_plugin_perhaps_too_general?]]) * YADA format setup files per default? +* Enable `tag_autocreate` by default. In general, we try to use [[ikiwiki-transition]] or forced rebuilds on upgrade to deal with changes that break compatability. Some things that -- cgit v1.2.3 From 2a0e3787a056b160843eca263c82d591c7161988 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 15:54:18 -0400 Subject: bugfixes --- IkiWiki/Render.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 14f6f9d5f..09c9121f3 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -681,18 +681,18 @@ sub gen_autofile ($$$) { my $autofile=shift; my $pages=shift; my $del=shift; - + if (srcfile($autofile, 1) || file_pruned($autofile)) { return; } - my $file="$config{srcdir}/$autofile" =~ /$config{wiki_file_regexp}/; # untaint + my ($file)="$config{srcdir}/$autofile" =~ /$config{wiki_file_regexp}/; # untaint if (! defined $file || -l $file || -d _ || -e _) { return; } if ((!defined $file) || - (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile_deleted})) { + (exists $wikistate{$autofiles{$autofile}{plugin}}{deleted_autofile}{$autofile})) { return; } @@ -701,8 +701,8 @@ sub gen_autofile ($$$) { return; } - if (grep { $_ eq $file } @$del) { - $wikistate{$autofiles{$autofile}{plugin}}{autofile_deleted}=1; + if (grep { $_ eq $autofile } @$del) { + $wikistate{$autofiles{$autofile}{plugin}}{deleted_autofile}{$autofile}=1; return; } -- cgit v1.2.3 From a71b92ed5c5572a1384367f8a90e1fc489b3c660 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 15:59:39 -0400 Subject: remember autofiles always This fixes the problem that it did not remember if an autofile is deleted, unless a plugin happened to register the autofile at the same time. With the new code, we just never recreate an autofile more than once. Only downside is that the list of autofiles is never pruned either. And I don't really see a way to prune it. --- IkiWiki/Render.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index 09c9121f3..b3afabf32 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -692,7 +692,7 @@ sub gen_autofile ($$$) { } if ((!defined $file) || - (exists $wikistate{$autofiles{$autofile}{plugin}}{deleted_autofile}{$autofile})) { + (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile})) { return; } @@ -702,11 +702,11 @@ sub gen_autofile ($$$) { } if (grep { $_ eq $autofile } @$del) { - $wikistate{$autofiles{$autofile}{plugin}}{deleted_autofile}{$autofile}=1; return; } $autofiles{$autofile}{generator}->(); + $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}=1; $pages->{$page}=1; return 1; } -- cgit v1.2.3 From fd6fb4c5071d9317b4388a0db6b97037cc010477 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 16:13:37 -0400 Subject: commit autocreated tag pages --- IkiWiki/Plugin/tag.pm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index d2a3d4dfd..c98dd80b2 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -79,11 +79,18 @@ sub gentag ($) { my $tagfile = newpagefile($tagpage, $config{default_pageext}); add_autofile($tagfile, "tag", sub { - debug(sprintf(gettext("creating tag page %s"), $tag)); + my $message=sprintf(gettext("creating tag page %s"), $tag); + debug($message); my $template=template("autotag.tmpl"); $template->param(tag => $tag); writefile($tagfile, $config{srcdir}, $template->output); + if ($config{rcs}) { + IkiWiki::disable_commit_hook(); + IkiWiki::rcs_add($tagfile); + IkiWiki::rcs_commit_staged($message, undef, undef); + IkiWiki::enable_commit_hook(); + } }); } } -- cgit v1.2.3 From 167964b68661de57983993efd7261a75da661665 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 16:41:36 -0400 Subject: remember autofiles that were tried and failed to be added This way, if an autofile is registered for a file that already exists, it is remembered that it was tried, and it doesn't get recreated when removed. --- IkiWiki/Render.pm | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm index b3afabf32..c3e07baf6 100644 --- a/IkiWiki/Render.pm +++ b/IkiWiki/Render.pm @@ -682,20 +682,29 @@ sub gen_autofile ($$$) { my $pages=shift; my $del=shift; - if (srcfile($autofile, 1) || file_pruned($autofile)) { + if (file_pruned($autofile)) { return; } - + my ($file)="$config{srcdir}/$autofile" =~ /$config{wiki_file_regexp}/; # untaint - if (! defined $file || -l $file || -d _ || -e _) { + if (! defined $file) { + return; + } + + # Remember autofiles that were tried, and never try them again later. + if (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}) { return; } + $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}=1; - if ((!defined $file) || - (exists $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile})) { + if (srcfile($autofile, 1) || file_pruned($autofile)) { return; } + if (-l $file || -d _ || -e _) { + return; + } + my $page = pagename($file); if ($pages->{$page}) { return; @@ -706,7 +715,6 @@ sub gen_autofile ($$$) { } $autofiles{$autofile}{generator}->(); - $wikistate{$autofiles{$autofile}{plugin}}{autofile}{$autofile}=1; $pages->{$page}=1; return 1; } -- cgit v1.2.3 From 8cde2365e43f1c96432dcedb378be55d2308dd08 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 19:09:59 -0400 Subject: add separate template variable for tag page and sanitize displayed tag name --- IkiWiki/Plugin/tag.pm | 3 ++- templates/autotag.tmpl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index c98dd80b2..6a6517671 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -83,7 +83,8 @@ sub gentag ($) { debug($message); my $template=template("autotag.tmpl"); - $template->param(tag => $tag); + $template->param(tag => IkiWiki::basename($tag)); + $template->param(tagpage => $tagpage); writefile($tagfile, $config{srcdir}, $template->output); if ($config{rcs}) { IkiWiki::disable_commit_hook(); diff --git a/templates/autotag.tmpl b/templates/autotag.tmpl index a8824171b..7b0d4c90f 100644 --- a/templates/autotag.tmpl +++ b/templates/autotag.tmpl @@ -1,3 +1,3 @@ -## Pages tagged ## +## Pages tagged ## [[!inline pages="tagged()" actions="no" archive="yes"]] -- cgit v1.2.3 From 0e2b5ebe314c617ae4139b5daad314e01208d37b Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 19:49:11 -0400 Subject: clarify --- IkiWiki/Plugin/tag.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 72ae682f3..dd7583ab2 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -170,8 +170,8 @@ package IkiWiki::PageSpec; sub match_tagged ($$;@) { my $page=shift; - my $glob=shift; - return match_link($page, IkiWiki::Plugin::tag::taglink($glob), linktype => 'tag', @_); + my $glob=IkiWiki::Plugin::tag::taglink(shift); + return match_link($page, $glob, linktype => 'tag', @_); } 1 -- cgit v1.2.3 From 752ccf8b48bab173839b5c7892e9868ee71846f0 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 20:08:23 -0400 Subject: fixes --- IkiWiki/Plugin/tag.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index dd7583ab2..a7f37a512 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -79,12 +79,12 @@ sub gentag ($) { my $tagfile = newpagefile($tagpage, $config{default_pageext}); add_autofile($tagfile, "tag", sub { - my $message=sprintf(gettext("creating tag page %s"), $tag); + my $message=sprintf(gettext("creating tag page %s"), $tagpage); debug($message); my $template=template("autotag.tmpl"); - $template->param(tag => IkiWiki::basename($tag)); - $template->param(tagpage => $tagpage); + $template->param(tagname => IkiWiki::basename($tag)); + $template->param(tag => $tag); writefile($tagfile, $config{srcdir}, $template->output); if ($config{rcs}) { IkiWiki::disable_commit_hook(); -- cgit v1.2.3 From d048e9c64aca24b8e064aaf1608862b50c427de2 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 20:39:20 -0400 Subject: turn on tag_autocreate by default if tagbase is set --- IkiWiki/Plugin/tag.pm | 5 +++-- debian/NEWS | 4 ++++ doc/ikiwiki/directive/tag.mdwn | 3 ++- doc/plugins/tag.mdwn | 8 ++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index cd7ecc212..62f030f4e 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -36,7 +36,7 @@ sub getsetup () { }, tag_autocreate => { type => "boolean", - example => 0, + example => 1, description => "autocreate new tag pages?", safe => 1, rebuild => undef, @@ -67,7 +67,8 @@ sub htmllink_tag ($$$;@) { sub gentag ($) { my $tag=shift; - if ($config{tag_autocreate}) { + if ($config{tag_autocreate} || + ($config{tagbase} && ! defined $config{tag_autocreate})) { my $tagpage=taglink($tag); if ($tagpage=~/^\.\/(.*)/) { $tagpage=$1; diff --git a/debian/NEWS b/debian/NEWS index 9fd882ad2..8b87bc601 100644 --- a/debian/NEWS +++ b/debian/NEWS @@ -11,6 +11,10 @@ ikiwiki (3.20100406) unstable; urgency=low not regular wikilinks. If your wiki accidentially relied on the old, buggy behavior, you might need to change pagespecs to use `link()`. + Tag pages can automatically be created as new tags are used. This + feature is enabled by default if you have configured a tagbase. It + can be turned on or off using the `tag_autocreate` setting. + The title_natural sort method (as used by the inline directive, etc) have been moved to the new sortnaturally plugin, which is not enabled by default since it requires the Sort::Naturally perl module. diff --git a/doc/ikiwiki/directive/tag.mdwn b/doc/ikiwiki/directive/tag.mdwn index 807a96f25..c8d9b9816 100644 --- a/doc/ikiwiki/directive/tag.mdwn +++ b/doc/ikiwiki/directive/tag.mdwn @@ -19,7 +19,8 @@ instead: Note that if the wiki is configured to use a tagbase, then the tags will be located under a base directory, such as "tags/". This is a useful way to avoid having to write the full path to tags, if you want to keep them -grouped together out of the way. +grouped together out of the way. Also, since ikiwiki then knows where to put +tags, it will automatically create tag pages when new tags are used. Bear in mind that specifying a tagbase means you will need to incorporate it into the `link()` [[ikiwiki/PageSpec]] you use: e.g., if your tagbase is diff --git a/doc/plugins/tag.mdwn b/doc/plugins/tag.mdwn index bdf39d7e8..8e1286e62 100644 --- a/doc/plugins/tag.mdwn +++ b/doc/plugins/tag.mdwn @@ -8,8 +8,12 @@ These directives allow tagging pages. It also provides the `tagged()` [[ikiwiki/PageSpec]], which can be used to match pages that are tagged with a specific tag. -If the `tag_autocreate` setting is enabled, tag pages will automatically be -created as needed. +The `tagbase` setting can be used to make tags default to being put in a +particular subdirectory. + +The `tag_autocreate` setting can be used to control whether new tag pages +are created as needed. It defaults to being done only if a `tagbase` is +set. [[!if test="enabled(tag)" then=""" This wiki has the tag plugin enabled, so you'll see a note below that this -- cgit v1.2.3 From 17a89d3d19f3a04ca2686ff18df127e5afaf9577 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 21 Apr 2010 21:57:12 -0400 Subject: update --- doc/plugins/tag/discussion.mdwn | 1 + doc/todo/auto-create_tag_pages_according_to_a_template.mdwn | 2 ++ 2 files changed, 3 insertions(+) diff --git a/doc/plugins/tag/discussion.mdwn b/doc/plugins/tag/discussion.mdwn index 03dcb7b2f..dfd749252 100644 --- a/doc/plugins/tag/discussion.mdwn +++ b/doc/plugins/tag/discussion.mdwn @@ -28,3 +28,4 @@ See [[todo/auto-create tag pages according to a template]] -- Jeremy Schultz +`tag_autocreate` can now enable this. --[[Joey]] diff --git a/doc/todo/auto-create_tag_pages_according_to_a_template.mdwn b/doc/todo/auto-create_tag_pages_according_to_a_template.mdwn index 32870dd3d..1e0a910f4 100644 --- a/doc/todo/auto-create_tag_pages_according_to_a_template.mdwn +++ b/doc/todo/auto-create_tag_pages_according_to_a_template.mdwn @@ -247,3 +247,5 @@ I've tested it somewhat. --[[Joey]] [da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0 (commitdiff for da5d29f95f6e693e8c14be1b896cf25cf4fdb3c0) [a358d74bef51dae31332ff27e897fe04834571e6]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=a358d74bef51dae31332ff27e897fe04834571e6 (commitdiff for a358d74bef51dae31332ff27e897fe04834571e6) [981400177d68a279f485727be3f013e68f0bf691]: http://git.liegesta.at/?p=ikiwiki.git;a=commitdiff;h=981400177d68a279f485727be3f013e68f0bf691 (commitdiff for 981400177d68a279f485727be3f013e68f0bf691) + +[[!tag done]] -- cgit v1.2.3