From c4d4cad3befbbd444d094cbeb0b6ebba3910a025 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Fri, 20 Aug 2010 10:13:14 +0200 Subject: Single dot in pagespec translates to 'current page' --- IkiWiki.pm | 3 +++ 1 file changed, 3 insertions(+) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index df8abe2c2..6fd112960 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2401,6 +2401,9 @@ package IkiWiki::PageSpec; sub derel ($$) { my $path=shift; my $from=shift; + if ($path eq '.') { + $path = $from; + } if ($path =~ m!^\./!) { $from=~s#/?[^/]+$## if defined $from; -- cgit v1.2.3 From 991d01f5b53250b962725110903b0324c93fbfb6 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 30 Aug 2010 13:36:00 -0400 Subject: optimise single dot detection Since it already looks for things starting with a dot, I was able to avoid matching against the string twice. This also fixes a minor bug; $from may not be defined. Avoid uninitialized value warnings in this case. --- IkiWiki.pm | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 6fd112960..6da281999 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2401,14 +2401,17 @@ package IkiWiki::PageSpec; sub derel ($$) { my $path=shift; my $from=shift; - if ($path eq '.') { - $path = $from; - } - if ($path =~ m!^\./!) { - $from=~s#/?[^/]+$## if defined $from; - $path=~s#^\./##; - $path="$from/$path" if defined $from && length $from; + if ($path =~ m!^\.(/|$)!) { + if ($1) { + $from=~s#/?[^/]+$## if defined $from; + $path=~s#^\./##; + $path="$from/$path" if defined $from && length $from; + } + else { + $path = $from; + $path = "" unless defined $path; + } } return $path; -- cgit v1.2.3 From 8030ecac02a743e930e480650e8c14413f26d9a2 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 30 Aug 2010 17:58:00 -0400 Subject: Receive: avoid hiding check_canedit error messages Avoid the generic "you are not allowed to change" message, and instead allow check_canedit to propigate out useful error messages. Went back to calling check_canedit in fatal mode, but added a parameter to avoid calling the troublesome subs that might cause a login attempt. --- IkiWiki.pm | 4 +++- IkiWiki/Receive.pm | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 6da281999..d114c9a69 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1455,11 +1455,12 @@ sub filter ($$$) { return $content; } -sub check_canedit ($$$;$) { +sub check_canedit ($$$;$$) { my $page=shift; my $q=shift; my $session=shift; my $nonfatal=shift; + my $nosubs=shift; my $canedit; run_hooks(canedit => sub { @@ -1470,6 +1471,7 @@ sub check_canedit ($$$;$) { $canedit=1; } elsif (ref $ret eq 'CODE') { + error(sprintf(gettext("you are not allowed to change %s"), $page)) if $nosubs && ! $nonfatal; $ret->() unless $nonfatal; $canedit=0; } diff --git a/IkiWiki/Receive.pm b/IkiWiki/Receive.pm index cd746c95f..3a5f91758 100644 --- a/IkiWiki/Receive.pm +++ b/IkiWiki/Receive.pm @@ -95,12 +95,12 @@ sub test () { if ($change->{action} eq 'change' || $change->{action} eq 'add') { if (defined $page) { - next if IkiWiki::check_canedit($page, $cgi, $session, 1); + IkiWiki::check_canedit($page, $cgi, $session, 0, 1); } else { if (IkiWiki::Plugin::attachment->can("check_canattach")) { IkiWiki::Plugin::attachment::check_canattach($session, $file, $change->{path}); - next if IkiWiki::check_canedit($file, $cgi, $session, 1); + IkiWiki::check_canedit($file, $cgi, $session, 0, 1); } } } @@ -116,14 +116,12 @@ sub test () { if (IkiWiki::Plugin::remove->can("check_canremove")) { IkiWiki::Plugin::remove::check_canremove(defined $page ? $page : $file, $cgi, $session); - next if IkiWiki::check_canedit(defined $page ? $page : $file, $cgi, $session, 1); + IkiWiki::check_canedit(defined $page ? $page : $file, $cgi, $session, 0, 1); } } else { error "unknown action ".$change->{action}; } - - error sprintf(gettext("you are not allowed to change %s"), $file); } exit 0; -- cgit v1.2.3 From 2df0999e4033278a6cc8f6e2d00449224aa09efa Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 30 Aug 2010 18:31:56 -0400 Subject: revert check_canedit nosubs thing Abstraction violation. I now think the problem should be treated as a bug in httpauth. --- IkiWiki.pm | 4 +--- IkiWiki/Receive.pm | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index d114c9a69..6da281999 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1455,12 +1455,11 @@ sub filter ($$$) { return $content; } -sub check_canedit ($$$;$$) { +sub check_canedit ($$$;$) { my $page=shift; my $q=shift; my $session=shift; my $nonfatal=shift; - my $nosubs=shift; my $canedit; run_hooks(canedit => sub { @@ -1471,7 +1470,6 @@ sub check_canedit ($$$;$$) { $canedit=1; } elsif (ref $ret eq 'CODE') { - error(sprintf(gettext("you are not allowed to change %s"), $page)) if $nosubs && ! $nonfatal; $ret->() unless $nonfatal; $canedit=0; } diff --git a/IkiWiki/Receive.pm b/IkiWiki/Receive.pm index 972e3578d..e77c477a9 100644 --- a/IkiWiki/Receive.pm +++ b/IkiWiki/Receive.pm @@ -95,13 +95,13 @@ sub test () { if ($change->{action} eq 'change' || $change->{action} eq 'add') { if (defined $page) { - IkiWiki::check_canedit($page, $cgi, $session, 0, 1); + IkiWiki::check_canedit($page, $cgi, $session); next; } else { if (IkiWiki::Plugin::attachment->can("check_canattach")) { IkiWiki::Plugin::attachment::check_canattach($session, $file, $change->{path}); - IkiWiki::check_canedit($file, $cgi, $session, 0, 1); + IkiWiki::check_canedit($file, $cgi, $session); next; } } @@ -118,7 +118,7 @@ sub test () { if (IkiWiki::Plugin::remove->can("check_canremove")) { IkiWiki::Plugin::remove::check_canremove(defined $page ? $page : $file, $cgi, $session); - IkiWiki::check_canedit(defined $page ? $page : $file, $cgi, $session, 0, 1); + IkiWiki::check_canedit(defined $page ? $page : $file, $cgi, $session); next; } } -- cgit v1.2.3 From e22b18aabcb46e3c0eafeb466b51bb3eb18cf1e1 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 27 Sep 2010 15:47:14 -0400 Subject: template_depends: throw nice error message when template cannot be found plovs reported a crash when templates were not installed properly, with a non-useful error about the template object not being defined. I've audited all uses of template_depends(), and template(), and it makes sense for them to throw an error if the template cannot be found. All code with a user-supplied template catches errors already, to handle template parse failures. It did not make sense for template_file to throw errors, as some code uses it to probe if a template file is available. --- IkiWiki.pm | 8 +++++--- IkiWiki/Plugin/edittemplate.pm | 3 --- IkiWiki/Plugin/inline.pm | 5 +---- IkiWiki/Plugin/template.pm | 7 ++----- doc/plugins/write.mdwn | 2 ++ 5 files changed, 10 insertions(+), 15 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 6da281999..66ae86809 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1769,12 +1769,14 @@ sub template_depends ($$;@) { my $page=shift; my ($filename, $tpage, $untrusted)=template_file($name); + if (! defined $filename) { + error(sprintf(gettext("template %s not found"), $name)) + } + if (defined $page && defined $tpage) { add_depends($page, $tpage); } - - return unless defined $filename; - + my @opts=( filter => sub { my $text_ref = shift; diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm index 4f07866e4..576c94be4 100644 --- a/IkiWiki/Plugin/edittemplate.pm +++ b/IkiWiki/Plugin/edittemplate.pm @@ -132,9 +132,6 @@ sub filltemplate ($$) { # up a template that doesn't work. return "[[!pagetemplate ".gettext("failed to process template:")." $@]]"; } - if (! defined $template) { - return; - } $template->param(name => $page); diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 715a3d652..c00aed299 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -336,10 +336,7 @@ sub preprocess_inline (@) { blind_cache => 1); }; if ($@) { - error gettext("failed to process template:")." $@"; - } - if (! $template) { - error sprintf(gettext("template %s not found"), $params{template}.".tmpl"); + error sprintf(gettext("failed to process template %s"), $params{template}.".tmpl").": $@"; } } my $needcontent=$raw || (!($archive && $quick) && $template->query(name => 'content')); diff --git a/IkiWiki/Plugin/template.pm b/IkiWiki/Plugin/template.pm index db26bfe31..3df06e652 100644 --- a/IkiWiki/Plugin/template.pm +++ b/IkiWiki/Plugin/template.pm @@ -41,12 +41,9 @@ sub preprocess (@) { blind_cache => 1); }; if ($@) { - error gettext("failed to process template:")." $@"; - } - if (! $template) { - error sprintf(gettext("%s not found"), + error sprintf(gettext("failed to process template %s"), htmllink($params{page}, $params{destpage}, - "/templates/$params{id}")) + "/templates/$params{id}"))." $@"; } $params{basename}=IkiWiki::basename($params{page}); diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index e60314485..d5bd1dd76 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -740,6 +740,8 @@ with no ".tmpl" extension. Template pages are normally looked for in the templates/ directory. If the page name starts with "/", a page elsewhere in the wiki can be used. +If the template is not found, or contains a syntax error, an error is thrown. + ### `template_depends($$;@)` Use this instead of `template()` if the content of a template is being -- cgit v1.2.3 From acecbad0ff4a8c441da520522710dd5357ab31e0 Mon Sep 17 00:00:00 2001 From: Peter Gammie Date: Wed, 29 Sep 2010 15:14:19 +1000 Subject: First cut at the revert plugin. --- IkiWiki.pm | 12 ++++++++ IkiWiki/Plugin/git.pm | 35 +++++++++++++++++++++ IkiWiki/Plugin/recentchanges.pm | 66 ++++++++++++++++++++++++++++++++++++++++ doc/templates.mdwn | 2 +- doc/wikiicons/revert.png | Bin 0 -> 840 bytes templates/revert.tmpl | 13 ++++++++ 6 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 doc/wikiicons/revert.png create mode 100644 templates/revert.tmpl (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 66ae86809..e2b2ceda3 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1941,6 +1941,18 @@ sub rcs_receive () { $hooks{rcs}{rcs_receive}{call}->(); } +sub rcs_preprevert ($) { + $hooks{rcs}{rcs_preprevert}{call}->(@_); +} + +sub rcs_revert (@) { + $hooks{rcs}{rcs_revert}{call}->(@_); +} + +sub rcs_showpatch ($) { + $hooks{rcs}{rcs_showpatch}{call}->(@_); +} + sub add_depends ($$;$) { my $page=shift; my $pagespec=shift; diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm index fd57ce1e4..a68bd0b0e 100644 --- a/IkiWiki/Plugin/git.pm +++ b/IkiWiki/Plugin/git.pm @@ -27,6 +27,10 @@ sub import { hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime); hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime); hook(type => "rcs", id => "rcs_receive", call => \&rcs_receive); + hook(type => "rcs", id => "rcs_preprevert", call => \&rcs_preprevert); + hook(type => "rcs", id => "rcs_revert", call => \&rcs_revert); + hook(type => "rcs", id => "rcs_showpatch", call => \&rcs_showpatch); + hook(type => "rcs", id => "rcs_revert", call => \&rcs_revert); } sub checkconfig () { @@ -811,4 +815,35 @@ sub rcs_receive () { return reverse @rets; } +sub rcs_preprevert ($) { + # FIXME implement +} + +sub rcs_revert (@) { + # Try to revert the given patch; returns undef on _success_. + # Same parameters as rcs_commit_staged + 'rev', the patch ID to be + # reverted. + my %params = @_; + my $rev = $params{rev}; + + if(run_or_non('git', 'revert', '--no-commit', $rev)) { + debug "Committing revert for patch '$rev'."; + rcs_commit_staged(message => "This reverts commit $rev", @_); + } else { + # No idea what is actually getting reverted, so all we can do is say we failed. + run_or_die('git', 'reset', '--hard'); + return "Failed to revert patch $rev."; + } +} + +sub rcs_showpatch ($) { + # Show the patch with the given revision id. + my ($rev) = @_; + + # FIXME check + my @r = run_or_die('git', 'show', $rev); + + return join "\n", @r; +} + 1 diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 758b98348..2a78566e1 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -60,6 +60,72 @@ sub refresh ($) { } } +sub confirmation_form { + my ($q, $session, $rev) = @_; + + eval q{use CGI::FormBuilder}; + error($@) if $@; + my $f = CGI::FormBuilder->new( + name => "revert", + header => 0, + charset => "utf-8", + method => 'POST', + javascript => 0, + params => $q, + action => $config{cgiurl}, + stylesheet => 1, + template => { template('revert.tmpl') }, + ); + + $f->field(name => "sid", type => "hidden", value => $session->id, + force => 1); + $f->field(name => "do", type => "hidden", value => "revert", force => 1); + $f->field(name => "rev", type => "hidden", value => $rev, force => 1); + + return $f, ["Revert", "Cancel"]; +} + +sub sessioncgi ($$) { + my ($q, $session) = @_; + my $do = $q->param('do'); + my $rev = $q->param('rev'); + + return unless $do eq 'revert' && $rev; + + # FIXME rcs_preprevert ?? + IkiWiki::check_canedit('FIXME', $q, $session); + + my ($form, $buttons) = confirmation_form($q, $session); + IkiWiki::decode_form_utf8($form); + + if($form->submitted eq 'Revert' && $form->validate) { + IkiWiki::checksessionexpiry($q, $session, $q->param('sid')); + + IkiWiki::disable_commit_hook(); + my $r = IkiWiki::rcs_revert( + session => $session, + rev => $rev); + IkiWiki::enable_commit_hook(); + + if($r) { + die "FIXME revert '$rev' failed."; + } else { + IkiWiki::refresh(); + IkiWiki::saveindex(); + # FIXME indicate success. + } + } else { + $form->title(sprintf(gettext("confirm reversion of %s"), $rev)); + my $patch_contents = IkiWiki::rcs_showpatch($rev); + $form->tmpl_param(patch_contents => encode_entities($patch_contents)); + IkiWiki::showform($form, $buttons, $session, $q); + exit 0; + } + + IkiWiki::redirect($q, urlto($config{recentchangespage}, '')); + exit 0; +} + # Enable the recentchanges link. sub pagetemplate (@) { my %params=@_; diff --git a/doc/templates.mdwn b/doc/templates.mdwn index bfb6a439a..4fd2bf501 100644 --- a/doc/templates.mdwn +++ b/doc/templates.mdwn @@ -74,7 +74,7 @@ html out of ikiwiki and in the templates. * `editpage.tmpl`, `editconflict.tmpl`, `editcreationconflict.tmpl`, `editfailedsave.tmpl`, `editpagegone.tmpl`, `pocreatepage.tmpl`, `editcomment.tmpl` `commentmoderation.tmpl`, `renamesummary.tmpl`, - `passwordmail.tmpl`, `openid-selector.tmpl` - Parts of ikiwiki's user + `passwordmail.tmpl`, `openid-selector.tmpl`, `revert.tmpl` - Parts of ikiwiki's user interface; do not normally need to be customised. [[!meta robots="noindex, follow"]] diff --git a/doc/wikiicons/revert.png b/doc/wikiicons/revert.png new file mode 100644 index 000000000..9036046e9 Binary files /dev/null and b/doc/wikiicons/revert.png differ diff --git a/templates/revert.tmpl b/templates/revert.tmpl new file mode 100644 index 000000000..3cf069dca --- /dev/null +++ b/templates/revert.tmpl @@ -0,0 +1,13 @@ +
+
+
+ +
+ + +
+
+ + +
+ -- cgit v1.2.3 From 8024a2636feb60026a79715430a66bb572b9eae8 Mon Sep 17 00:00:00 2001 From: Peter Gammie Date: Fri, 1 Oct 2010 14:06:00 +1000 Subject: Complete rcs_preprevert and lightly test. --- IkiWiki.pm | 4 +- IkiWiki/Plugin/git.pm | 188 +++++++++++++++++++++++----------------- IkiWiki/Plugin/recentchanges.pm | 5 +- IkiWiki/Receive.pm | 32 +++++-- 4 files changed, 136 insertions(+), 93 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index e2b2ceda3..aa4dccac3 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1941,7 +1941,7 @@ sub rcs_receive () { $hooks{rcs}{rcs_receive}{call}->(); } -sub rcs_preprevert ($) { +sub rcs_preprevert (@) { $hooks{rcs}{rcs_preprevert}{call}->(@_); } @@ -1949,7 +1949,7 @@ sub rcs_revert (@) { $hooks{rcs}{rcs_revert}{call}->(@_); } -sub rcs_showpatch ($) { +sub rcs_showpatch (@) { $hooks{rcs}{rcs_showpatch}{call}->(@_); } diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm index a68bd0b0e..46fa7d2e0 100644 --- a/IkiWiki/Plugin/git.pm +++ b/IkiWiki/Plugin/git.pm @@ -722,101 +722,130 @@ sub rcs_getmtime ($) { return findtimes($file, 0); } -sub rcs_receive () { - # The wiki may not be the only thing in the git repo. - # Determine if it is in a subdirectory by examining the srcdir, - # and its parents, looking for the .git directory. - my $subdir=""; - my $dir=$config{srcdir}; - while (! -d "$dir/.git") { - $subdir=IkiWiki::basename($dir)."/".$subdir; - $dir=IkiWiki::dirname($dir); - if (! length $dir) { - error("cannot determine root of git repo"); - } - } +{ +my $git_root; +sub git_find_root { + # The wiki may not be the only thing in the git repo. + # Determine if it is in a subdirectory by examining the srcdir, + # and its parents, looking for the .git directory. + + return $git_root if $git_root; + + my $subdir=""; + my $dir=$config{srcdir}; + while (! -d "$dir/.git") { + $subdir=IkiWiki::basename($dir)."/".$subdir; + $dir=IkiWiki::dirname($dir); + if (! length $dir) { + error("cannot determine root of git repo"); + } + } + + return $subdir; +} +} + +sub git_parse_changes { + my @changes = @_; + + my $subdir = git_find_root(); + my @rets; + foreach my $ci (@changes) { + foreach my $detail (@{ $ci->{'details'} }) { + my $file = $detail->{'file'}; + + # check that all changed files are in the + # subdir + if (length $subdir && + ! ($file =~ s/^\Q$subdir\E//)) { + error sprintf(gettext("you are not allowed to change %s"), $file); + } + + my ($action, $mode, $path); + if ($detail->{'status'} =~ /^[M]+\d*$/) { + $action="change"; + $mode=$detail->{'mode_to'}; + } + elsif ($detail->{'status'} =~ /^[AM]+\d*$/) { + $action="add"; + $mode=$detail->{'mode_to'}; + } + elsif ($detail->{'status'} =~ /^[DAM]+\d*/) { + $action="remove"; + $mode=$detail->{'mode_from'}; + } + else { + error "unknown status ".$detail->{'status'}; + } + + # test that the file mode is ok + if ($mode !~ /^100[64][64][64]$/) { + error sprintf(gettext("you cannot act on a file with mode %s"), $mode); + } + if ($action eq "change") { + if ($detail->{'mode_from'} ne $detail->{'mode_to'}) { + error gettext("you are not allowed to change file modes"); + } + } + + # extract attachment to temp file + if (($action eq 'add' || $action eq 'change') && + ! pagetype($file)) { + + eval q{use File::Temp}; + die $@ if $@; + my $fh; + ($fh, $path)=File::Temp::tempfile("XXXXXXXXXX", UNLINK => 1); + # Ensure we run this in the right place, see comments in rcs_receive. + my $cmd = ($no_chdir ? '' : "cd $config{srcdir} && ") + . "git show $detail->{sha1_to} > '$path'"; + if (system($cmd) != 0) { + error("failed writing temp file '$path'."); + } + } + + push @rets, { + file => $file, + action => $action, + path => $path, + }; + } + } + + return @rets; +} +sub rcs_receive () { my @rets; while (<>) { chomp; my ($oldrev, $newrev, $refname) = split(' ', $_, 3); - + # only allow changes to gitmaster_branch if ($refname !~ /^refs\/heads\/\Q$config{gitmaster_branch}\E$/) { error sprintf(gettext("you are not allowed to change %s"), $refname); } - + # Avoid chdir when running git here, because the changes # are in the master git repo, not the srcdir repo. - # The pre-recieve hook already puts us in the right place. + # The pre-receive hook already puts us in the right place. $no_chdir=1; - my @changes=git_commit_info($oldrev."..".$newrev); + push @rets, git_parse_changes(git_commit_info($oldrev."..".$newrev)); $no_chdir=0; - - foreach my $ci (@changes) { - foreach my $detail (@{ $ci->{'details'} }) { - my $file = $detail->{'file'}; - - # check that all changed files are in the - # subdir - if (length $subdir && - ! ($file =~ s/^\Q$subdir\E//)) { - error sprintf(gettext("you are not allowed to change %s"), $file); - } - - my ($action, $mode, $path); - if ($detail->{'status'} =~ /^[M]+\d*$/) { - $action="change"; - $mode=$detail->{'mode_to'}; - } - elsif ($detail->{'status'} =~ /^[AM]+\d*$/) { - $action="add"; - $mode=$detail->{'mode_to'}; - } - elsif ($detail->{'status'} =~ /^[DAM]+\d*/) { - $action="remove"; - $mode=$detail->{'mode_from'}; - } - else { - error "unknown status ".$detail->{'status'}; - } - - # test that the file mode is ok - if ($mode !~ /^100[64][64][64]$/) { - error sprintf(gettext("you cannot act on a file with mode %s"), $mode); - } - if ($action eq "change") { - if ($detail->{'mode_from'} ne $detail->{'mode_to'}) { - error gettext("you are not allowed to change file modes"); - } - } - - # extract attachment to temp file - if (($action eq 'add' || $action eq 'change') && - ! pagetype($file)) { - eval q{use File::Temp}; - die $@ if $@; - my $fh; - ($fh, $path)=File::Temp::tempfile("XXXXXXXXXX", UNLINK => 1); - if (system("git show ".$detail->{sha1_to}." > '$path'") != 0) { - error("failed writing temp file"); - } - } - - push @rets, { - file => $file, - action => $action, - path => $path, - }; - } - } } return reverse @rets; } -sub rcs_preprevert ($) { - # FIXME implement +sub rcs_preprevert (@) { + # Determine what the effects are of reverting the patch with the + # ID given by 'rev'. Returns the same structure as rcs_receive. + # FIXME note test_changes expects 'cgi' and 'session' parameters. + my %params = @_; + my $rev = $params{rev}; + + require IkiWiki::Receive; + IkiWiki::Receive::test_changes(%params, changes => [git_parse_changes(git_commit_info($rev, 1))]); } sub rcs_revert (@) { @@ -836,9 +865,10 @@ sub rcs_revert (@) { } } -sub rcs_showpatch ($) { +sub rcs_showpatch (@) { # Show the patch with the given revision id. - my ($rev) = @_; + my %params = @_; + my $rev = $params{rev}; # FIXME check my @r = run_or_die('git', 'show', $rev); diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 79d175328..4a8d1bf80 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -92,8 +92,7 @@ sub sessioncgi ($$) { return unless $do eq 'revert' && $rev; - # FIXME rcs_preprevert ?? - IkiWiki::check_canedit('FIXME', $q, $session); + IkiWiki::rcs_preprevert(cgi => $q, session => $session, rev => $rev); my ($form, $buttons) = confirmation_form($q, $session); IkiWiki::decode_form_utf8($form); @@ -117,7 +116,7 @@ sub sessioncgi ($$) { } } else { $form->title(sprintf(gettext("confirm reversion of %s"), $rev)); - my $patch_contents = IkiWiki::rcs_showpatch($rev); + my $patch_contents = IkiWiki::rcs_showpatch(rev => $rev); $form->tmpl_param(patch_contents => encode_entities($patch_contents)); $form->field(name => "rev", type => "hidden", value => $rev, force => 1); IkiWiki::showform($form, $buttons, $session, $q); diff --git a/IkiWiki/Receive.pm b/IkiWiki/Receive.pm index e77c477a9..48228e5f0 100644 --- a/IkiWiki/Receive.pm +++ b/IkiWiki/Receive.pm @@ -48,10 +48,10 @@ EOF sub test () { exit 0 if trusted(); - + IkiWiki::lockwiki(); IkiWiki::loadindex(); - + # Dummy up a cgi environment to use when calling check_canedit # and friends. eval q{use CGI}; @@ -72,10 +72,22 @@ sub test () { regdate => time, }) || error("failed adding user"); } - - my %newfiles; - foreach my $change (IkiWiki::rcs_receive()) { + test_changes(cgi => $cgi, + session => $session, + changes => [IkiWiki::rcs_receive()] + ); + exit 0; +} + +sub test_changes { + my %params = @_; + my $cgi = $params{cgi}; + my $session = $params{session}; + my @changes = @{$params{changes}}; + + my %newfiles; + foreach my $change (@changes) { # This untaint is safe because we check file_pruned and # wiki_file_regexp. my ($file)=$change->{file}=~/$config{wiki_file_regexp}/; @@ -87,7 +99,7 @@ sub test () { my $type=pagetype($file); my $page=pagename($file) if defined $type; - + if ($change->{action} eq 'add') { $newfiles{$file}=1; } @@ -104,6 +116,10 @@ sub test () { IkiWiki::check_canedit($file, $cgi, $session); next; } + else { + use Data::Dumper; + die "fall through test_changes add: " . Data::Dumper::Dumper($change); + } } } elsif ($change->{action} eq 'remove') { @@ -125,11 +141,9 @@ sub test () { else { error "unknown action ".$change->{action}; } - + error sprintf(gettext("you are not allowed to change %s"), $file); } - - exit 0; } 1 -- cgit v1.2.3 From a29f169b1e51feeee83d93fa5713c71e61f2b85c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 4 Oct 2010 16:34:33 -0400 Subject: indentation --- IkiWiki.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index aa4dccac3..466907c9d 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -717,7 +717,7 @@ sub pagename ($) { my $type=pagetype($file); my $page=$file; - $page=~s/\Q.$type\E*$// + $page=~s/\Q.$type\E*$// if defined $type && !$hooks{htmlize}{$type}{keepextension} && !$hooks{htmlize}{$type}{noextension}; if ($config{indexpages} && $page=~/(.*)\/index$/) { @@ -1124,7 +1124,7 @@ sub isselflink ($$) { my $page=shift; my $link=shift; - return $page eq $link; + return $page eq $link; } sub htmllink ($$$;@) { -- cgit v1.2.3 From 237ea79d715fbba5c1be0b73fbe008b3221975fb Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 6 Oct 2010 14:39:10 -0400 Subject: remove rcs_showpatch --- IkiWiki.pm | 4 ---- IkiWiki/Plugin/git.pm | 9 --------- IkiWiki/Plugin/recentchanges.pm | 2 +- doc/plugins/write.mdwn | 6 ------ doc/todo/web_reversion.mdwn | 4 ---- 5 files changed, 1 insertion(+), 24 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 466907c9d..269647eb4 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1949,10 +1949,6 @@ sub rcs_revert (@) { $hooks{rcs}{rcs_revert}{call}->(@_); } -sub rcs_showpatch (@) { - $hooks{rcs}{rcs_showpatch}{call}->(@_); -} - sub add_depends ($$;$) { my $page=shift; my $pagespec=shift; diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm index 5922494bc..3ccaa446a 100644 --- a/IkiWiki/Plugin/git.pm +++ b/IkiWiki/Plugin/git.pm @@ -29,7 +29,6 @@ sub import { hook(type => "rcs", id => "rcs_receive", call => \&rcs_receive); hook(type => "rcs", id => "rcs_preprevert", call => \&rcs_preprevert); hook(type => "rcs", id => "rcs_revert", call => \&rcs_revert); - hook(type => "rcs", id => "rcs_showpatch", call => \&rcs_showpatch); } sub checkconfig () { @@ -865,12 +864,4 @@ sub rcs_revert (@) { } } -sub rcs_showpatch (@) { - # Show the patch with the given revision id. - my %params = @_; - my $rev = $params{rev}; - - return join "\n", run_or_die('git', 'show', $rev); -} - 1 diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 7e71d4fc3..948bb1366 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -117,7 +117,7 @@ sub sessioncgi ($$) { } else { $form->title(sprintf(gettext("confirm reversion of %s"), $rev)); - my $patch_contents = IkiWiki::rcs_showpatch(rev => $rev); + my $patch_contents = IkiWiki::rcs_diff($rev); $form->tmpl_param(patch_contents => encode_entities($patch_contents)); $form->field(name => "rev", type => "hidden", value => $rev, force => 1); IkiWiki::showform($form, $buttons, $session, $q); diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 1bd3b0f87..3eade34ee 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -1212,12 +1212,6 @@ It should try to revert the specified rev, which includes committing the reversion, and returns undef on _success_ and an error message on failure. -#### `rcs_showpatch(@)` - -This is passed a named parameter rev that is a RCS-specific -change ID. It should generate a diff-style patch showing the changes -made and return it. - ### PageSpec plugins It's also possible to write plugins that add new functions to diff --git a/doc/todo/web_reversion.mdwn b/doc/todo/web_reversion.mdwn index 33fa79aad..7cb412f79 100644 --- a/doc/todo/web_reversion.mdwn +++ b/doc/todo/web_reversion.mdwn @@ -55,7 +55,6 @@ Peter Gammie has done an initial implementation of the above. > (The data from `rcs_preprevert` could also be used for a confirmation > prompt -- it doesn't currently include enough info for diffs, but at > least could have a list of changed files.) ->> I added `rcs_showpatch` which simply yields the output of `git show `. -- [[peteg]] > > Note that it's possible for a git repo to have commits that modify wiki > files in a subdir, and code files elsewhere. `rcs_preprevert` should @@ -71,9 +70,6 @@ Peter Gammie has done an initial implementation of the above. >>> (and fixed all the indention..). Issues I noticed but have not gotten >>> to: --[[Joey]] >>>> Please change the git pointer above, then. I will work on your branch. -- [[peteg]] ->>> ->>> * `rcs_diff` already exists; why add `rcs_showpatch`? ->>>> If `rcs_diff` is intended for human consumption, by all means we can use that. -- [[peteg]] >>> * Would it be better for `rcs_revert` to not commit, and >>> `rcs_commit_staged` to then be used? This would work for git, but -- cgit v1.2.3 From 238e8b95a5b084e7131d3314b78419b9404cba4c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 6 Oct 2010 15:08:12 -0400 Subject: convert rcs_revert to only stage the reversion --- IkiWiki.pm | 4 ++-- IkiWiki/Plugin/git.pm | 13 ++++--------- IkiWiki/Plugin/recentchanges.pm | 13 +++++++++---- doc/plugins/write.mdwn | 10 ++++------ doc/todo/web_reversion.mdwn | 4 ---- 5 files changed, 19 insertions(+), 25 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 269647eb4..faf4af5c7 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1941,11 +1941,11 @@ sub rcs_receive () { $hooks{rcs}{rcs_receive}{call}->(); } -sub rcs_preprevert (@) { +sub rcs_preprevert ($) { $hooks{rcs}{rcs_preprevert}{call}->(@_); } -sub rcs_revert (@) { +sub rcs_revert ($) { $hooks{rcs}{rcs_revert}{call}->(@_); } diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm index 3ccaa446a..996ab6fba 100644 --- a/IkiWiki/Plugin/git.pm +++ b/IkiWiki/Plugin/git.pm @@ -846,19 +846,14 @@ sub rcs_preprevert (@) { [git_parse_changes(git_commit_info($rev, 1))]); } -sub rcs_revert (@) { - # Try to revert the given patch; returns undef on _success_. - my %params = @_; - my $rev = $params{rev}; +sub rcs_revert ($) { + # Try to revert the given rev; returns undef on _success_. + my $rev = $shift; if (run_or_non('git', 'revert', '--no-commit', $rev)) { - debug "Committing revert for patch '$rev'."; - rcs_commit_staged(message => - sprintf(gettext("This reverts commit %s"), $rev), @_); + return undef; } else { - # No idea what is actually getting reverted, so all we can - # do is say we failed. run_or_die('git', 'reset', '--hard'); return sprintf(gettext("Failed to revert commit %s"), $rev); } diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 439241b93..44c981548 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -101,12 +101,17 @@ sub sessioncgi ($$) { if ($form->submitted eq 'Revert' && $form->validate) { IkiWiki::checksessionexpiry($q, $session, $q->param('sid')); IkiWiki::disable_commit_hook(); - my $r = IkiWiki::rcs_revert( - session => $session, - rev => $rev); + my $r = IkiWiki::rcs_revert($rev); + if (! defined $r) { # success + rcs_commit_staged( + message => sprintf(gettext("This reverts commit %s"), $rev), + session => $session, + rev => $rev, + ); + } IkiWiki::enable_commit_hook(); - if ($r) { + if (defined $r) { die "Revert '$rev' failed."; } else { diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 3eade34ee..dbbe83851 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -1201,16 +1201,14 @@ Like `rcs_receive`, it should do whatever sanity checks are appropriate for the RCS to limit changes to safe changes, and die if a change would be unsafe to revert. -#### `rcs_revert(@)` +#### `rcs_revert($)` This is called by the revert web interface. It is passed a named parameter rev that is the RCS-specific change ID to revert. -Addition named parameters: `message`, and `session` (optional). - -It should try to revert the specified rev, which includes committing -the reversion, and returns undef on _success_ and an error message -on failure. +It should try to revert the specified rev, and leave the reversion staged +so `rcs_commit_staged` will complete it. It should return undef on _success_ +and an error message on failure. ### PageSpec plugins diff --git a/doc/todo/web_reversion.mdwn b/doc/todo/web_reversion.mdwn index 7cb412f79..784b72e05 100644 --- a/doc/todo/web_reversion.mdwn +++ b/doc/todo/web_reversion.mdwn @@ -71,10 +71,6 @@ Peter Gammie has done an initial implementation of the above. >>> to: --[[Joey]] >>>> Please change the git pointer above, then. I will work on your branch. -- [[peteg]] ->>> * Would it be better for `rcs_revert` to not commit, and ->>> `rcs_commit_staged` to then be used? This would work for git, but ->>> maybe other RCSs would be problimatic. It would simplifiy the ->>> interface and allow for future mulitple-revert interfaces. >>> * I quite don't understand why one caller of `git_parse_changes` >>> needs it to chdir, and not the other one. It's running >>> in the same git repo either way, and git doesn't need -- cgit v1.2.3 From 84111d96c461a5d31a615ebf64cae751e6fd9aef Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 8 Oct 2010 17:54:12 -0400 Subject: make revert hooks optional I removed the IkiWiki::rcs_ stubs for the revert hooks. Instead recentchanges tests to see if the hooks are available and calls them directly. --- IkiWiki.pm | 8 -------- IkiWiki/Plugin/recentchanges.pm | 9 ++++++--- doc/plugins/write.mdwn | 5 +++-- templates/change.tmpl | 2 ++ 4 files changed, 11 insertions(+), 13 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index faf4af5c7..1f6d70ba3 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1941,14 +1941,6 @@ sub rcs_receive () { $hooks{rcs}{rcs_receive}{call}->(); } -sub rcs_preprevert ($) { - $hooks{rcs}{rcs_preprevert}{call}->(@_); -} - -sub rcs_revert ($) { - $hooks{rcs}{rcs_revert}{call}->(@_); -} - sub add_depends ($$;$) { my $page=shift; my $pagespec=shift; diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 44c981548..a6d7f9fce 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -93,7 +93,8 @@ sub sessioncgi ($$) { return unless $do eq 'revert' && $rev; - IkiWiki::rcs_preprevert(cgi => $q, session => $session, rev => $rev); + $IkiWiki::hooks{rcs}{rcs_preprevert}{call}->( + cgi => $q, session => $session, rev => $rev); my ($form, $buttons) = confirmation_form($q, $session); IkiWiki::decode_form_utf8($form); @@ -101,7 +102,7 @@ sub sessioncgi ($$) { if ($form->submitted eq 'Revert' && $form->validate) { IkiWiki::checksessionexpiry($q, $session, $q->param('sid')); IkiWiki::disable_commit_hook(); - my $r = IkiWiki::rcs_revert($rev); + my $r = $IkiWiki::hooks{rcs}{rcs_revert}{call}->($rev); if (! defined $r) { # success rcs_commit_staged( message => sprintf(gettext("This reverts commit %s"), $rev), @@ -186,7 +187,9 @@ sub store ($$$) { ]; push @{$change->{pages}}, { link => '...' } if $is_excess; - if (length $config{cgiurl}) { + if (length $config{cgiurl} && + exists $IkiWiki::hooks{rcs}{rcs_preprevert} && + exists $IkiWiki::hooks{rcs}{rcs_revert}) { $change->{reverturl} = IkiWiki::cgiurl( do => "revert", rev => $change->{rev} diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index dbbe83851..6b751f0cd 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -1154,8 +1154,6 @@ context, and the whole diff in scalar context. This is used to get the page creation time for a file from the RCS, by looking it up in the history. -It's ok if this is not implemented, and throws an error. - If the RCS cannot determine a ctime for the file, return 0. #### `rcs_getmtime($)` @@ -1210,6 +1208,9 @@ It should try to revert the specified rev, and leave the reversion staged so `rcs_commit_staged` will complete it. It should return undef on _success_ and an error message on failure. +This hook and `rcs_preprevert` are optional, if not implemented, no revert +web interface will be available. + ### PageSpec plugins It's also possible to write plugins that add new functions to diff --git a/templates/change.tmpl b/templates/change.tmpl index 4525402a7..60a9d94b5 100644 --- a/templates/change.tmpl +++ b/templates/change.tmpl @@ -28,9 +28,11 @@
+ [[revert|wikiicons/revert.png]] +
-- cgit v1.2.3 From faf94b578729387f85af2b2b248959debe2fa4b8 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 8 Oct 2010 18:06:38 -0400 Subject: refactor check_canchange into IkiWiki library --- IkiWiki.pm | 63 +++++++++++++++++++++++++++++++++++++++ IkiWiki/Plugin/recentchanges.pm | 3 +- IkiWiki/Receive.pm | 65 ++--------------------------------------- 3 files changed, 66 insertions(+), 65 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 1f6d70ba3..2190f008c 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1519,6 +1519,69 @@ sub check_content (@) { return defined $ok ? $ok : 1; } +sub check_canchange (@) { + my %params = @_; + my $cgi = $params{cgi}; + my $session = $params{session}; + my @changes = @{$params{changes}}; + + my %newfiles; + foreach my $change (@changes) { + # This untaint is safe because we check file_pruned and + # wiki_file_regexp. + my ($file)=$change->{file}=~/$config{wiki_file_regexp}/; + $file=possibly_foolish_untaint($file); + if (! defined $file || ! length $file || + file_pruned($file)) { + error(gettext("bad file name %s"), $file); + } + + my $type=pagetype($file); + my $page=pagename($file) if defined $type; + + if ($change->{action} eq 'add') { + $newfiles{$file}=1; + } + + if ($change->{action} eq 'change' || + $change->{action} eq 'add') { + if (defined $page) { + check_canedit($page, $cgi, $session); + next; + } + else { + if (IkiWiki::Plugin::attachment->can("check_canattach")) { + IkiWiki::Plugin::attachment::check_canattach($session, $file, $change->{path}); + check_canedit($file, $cgi, $session); + next; + } + } + } + elsif ($change->{action} eq 'remove') { + # check_canremove tests to see if the file is present + # on disk. This will fail when a single commit adds a + # file and then removes it again. Avoid the problem + # by not testing the removal in such pairs of changes. + # (The add is still tested, just to make sure that + # no data is added to the repo that a web edit + # could not add.) + next if $newfiles{$file}; + + if (IkiWiki::Plugin::remove->can("check_canremove")) { + IkiWiki::Plugin::remove::check_canremove(defined $page ? $page : $file, $cgi, $session); + check_canedit(defined $page ? $page : $file, $cgi, $session); + next; + } + } + else { + error "unknown action ".$change->{action}; + } + + error sprintf(gettext("you are not allowed to change %s"), $file); + } +} + + my $wikilock; sub lockwiki () { diff --git a/IkiWiki/Plugin/recentchanges.pm b/IkiWiki/Plugin/recentchanges.pm index 56e17dcca..fe414d865 100644 --- a/IkiWiki/Plugin/recentchanges.pm +++ b/IkiWiki/Plugin/recentchanges.pm @@ -94,8 +94,7 @@ sub sessioncgi ($$) { return unless $do eq 'revert' && $rev; my @changes=$IkiWiki::hooks{rcs}{rcs_preprevert}{call}->($rev); - require IkiWiki::Receive; - IkiWiki::Receive::test_changes( + IkiWiki::check_canchange( cgi => $q, session => $session, changes => \@changes, diff --git a/IkiWiki/Receive.pm b/IkiWiki/Receive.pm index 88fb49725..225f2b9ab 100644 --- a/IkiWiki/Receive.pm +++ b/IkiWiki/Receive.pm @@ -73,73 +73,12 @@ sub test () { }) || error("failed adding user"); } - test_changes(cgi => $cgi, + check_canchange( + cgi => $cgi, session => $session, changes => [IkiWiki::rcs_receive()] ); exit 0; } -sub test_changes { - my %params = @_; - my $cgi = $params{cgi}; - my $session = $params{session}; - my @changes = @{$params{changes}}; - - my %newfiles; - foreach my $change (@changes) { - # This untaint is safe because we check file_pruned and - # wiki_file_regexp. - my ($file)=$change->{file}=~/$config{wiki_file_regexp}/; - $file=IkiWiki::possibly_foolish_untaint($file); - if (! defined $file || ! length $file || - IkiWiki::file_pruned($file)) { - error(gettext("bad file name %s"), $file); - } - - my $type=pagetype($file); - my $page=pagename($file) if defined $type; - - if ($change->{action} eq 'add') { - $newfiles{$file}=1; - } - - if ($change->{action} eq 'change' || - $change->{action} eq 'add') { - if (defined $page) { - IkiWiki::check_canedit($page, $cgi, $session); - next; - } - else { - if (IkiWiki::Plugin::attachment->can("check_canattach")) { - IkiWiki::Plugin::attachment::check_canattach($session, $file, $change->{path}); - IkiWiki::check_canedit($file, $cgi, $session); - next; - } - } - } - elsif ($change->{action} eq 'remove') { - # check_canremove tests to see if the file is present - # on disk. This will fail when a single commit adds a - # file and then removes it again. Avoid the problem - # by not testing the removal in such pairs of changes. - # (The add is still tested, just to make sure that - # no data is added to the repo that a web edit - # could not add.) - next if $newfiles{$file}; - - if (IkiWiki::Plugin::remove->can("check_canremove")) { - IkiWiki::Plugin::remove::check_canremove(defined $page ? $page : $file, $cgi, $session); - IkiWiki::check_canedit(defined $page ? $page : $file, $cgi, $session); - next; - } - } - else { - error "unknown action ".$change->{action}; - } - - error sprintf(gettext("you are not allowed to change %s"), $file); - } -} - 1 -- cgit v1.2.3 From 4a75dee651390b79ce4ceb1d951b02e28b3ce83a Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 20 Oct 2010 18:52:46 -0400 Subject: avoid perl warning when passed bad non-numeric year/month/day --- IkiWiki.pm | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 2190f008c..941ee13c4 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2608,6 +2608,10 @@ sub match_created_after ($$;@) { } sub match_creation_day ($$;@) { + my $d=shift; + if ($d !~ /^\d+$/) { + return IkiWiki::FailReason->new('invalid day'); + } if ((localtime($IkiWiki::pagectime{shift()}))[3] == shift) { return IkiWiki::SuccessReason->new('creation_day matched'); } @@ -2617,6 +2621,10 @@ sub match_creation_day ($$;@) { } sub match_creation_month ($$;@) { + my $m=shift; + if ($m !~ /^\d+$/) { + return IkiWiki::FailReason->new('invalid month'); + } if ((localtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) { return IkiWiki::SuccessReason->new('creation_month matched'); } @@ -2626,7 +2634,11 @@ sub match_creation_month ($$;@) { } sub match_creation_year ($$;@) { - if ((localtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift) { + my $y=shift; + if ($y !~ /^\d+$/) { + return IkiWiki::FailReason->new('invalid year'); + } + if ((localtime($IkiWiki::pagectime{shift()}))[5] + 1900 == $y) { return IkiWiki::SuccessReason->new('creation_year matched'); } else { -- cgit v1.2.3 From 7e8064e9fa8b3f2c3c0bd0aa5458f00552398e06 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 20 Oct 2010 18:53:50 -0400 Subject: add a hint that creation_month takes a number, not a month name --- IkiWiki.pm | 6 +++--- doc/ikiwiki/pagespec.mdwn | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 941ee13c4..1fa89586e 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2610,7 +2610,7 @@ sub match_created_after ($$;@) { sub match_creation_day ($$;@) { my $d=shift; if ($d !~ /^\d+$/) { - return IkiWiki::FailReason->new('invalid day'); + return IkiWiki::ErrorReason->new("invalid day $d"); } if ((localtime($IkiWiki::pagectime{shift()}))[3] == shift) { return IkiWiki::SuccessReason->new('creation_day matched'); @@ -2623,7 +2623,7 @@ sub match_creation_day ($$;@) { sub match_creation_month ($$;@) { my $m=shift; if ($m !~ /^\d+$/) { - return IkiWiki::FailReason->new('invalid month'); + return IkiWiki::ErrorReason->new("invalid month $m"); } if ((localtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) { return IkiWiki::SuccessReason->new('creation_month matched'); @@ -2636,7 +2636,7 @@ sub match_creation_month ($$;@) { sub match_creation_year ($$;@) { my $y=shift; if ($y !~ /^\d+$/) { - return IkiWiki::FailReason->new('invalid year'); + return IkiWiki::ErrorReason->new("invalid year $y"); } if ((localtime($IkiWiki::pagectime{shift()}))[5] + 1900 == $y) { return IkiWiki::SuccessReason->new('creation_year matched'); diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn index 6aec561ae..fe1af4c15 100644 --- a/doc/ikiwiki/pagespec.mdwn +++ b/doc/ikiwiki/pagespec.mdwn @@ -32,6 +32,7 @@ Some more elaborate limits can be added to what matches using these functions: tags matched by a glob) * "`backlink(page)`" - matches only pages that a given page links to * "`creation_month(month)`" - matches only files created on the given month + number * "`creation_day(mday)`" - or day of the month * "`creation_year(year)`" - or year * "`created_after(page)`" - matches only files created after the given page -- cgit v1.2.3 From 0cc2a36f593fd14b6345ad2c0b446edb2bafbe2e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 23 Oct 2010 16:47:19 -0400 Subject: bugfix --- IkiWiki.pm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 1fa89586e..08a3d7875 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2608,11 +2608,12 @@ sub match_created_after ($$;@) { } sub match_creation_day ($$;@) { + my $page=shift; my $d=shift; if ($d !~ /^\d+$/) { return IkiWiki::ErrorReason->new("invalid day $d"); } - if ((localtime($IkiWiki::pagectime{shift()}))[3] == shift) { + if ((localtime($IkiWiki::pagectime{$page}))[3] == $d) { return IkiWiki::SuccessReason->new('creation_day matched'); } else { @@ -2621,11 +2622,12 @@ sub match_creation_day ($$;@) { } sub match_creation_month ($$;@) { + my $page=shift; my $m=shift; if ($m !~ /^\d+$/) { return IkiWiki::ErrorReason->new("invalid month $m"); } - if ((localtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) { + if ((localtime($IkiWiki::pagectime{$page}))[4] + 1 == $m) { return IkiWiki::SuccessReason->new('creation_month matched'); } else { @@ -2634,11 +2636,12 @@ sub match_creation_month ($$;@) { } sub match_creation_year ($$;@) { + my $page=shift; my $y=shift; if ($y !~ /^\d+$/) { return IkiWiki::ErrorReason->new("invalid year $y"); } - if ((localtime($IkiWiki::pagectime{shift()}))[5] + 1900 == $y) { + if ((localtime($IkiWiki::pagectime{$page}))[5] + 1900 == $y) { return IkiWiki::SuccessReason->new('creation_year matched'); } else { -- cgit v1.2.3 From ff0e244701a6ead7f5a0b5826ac39bd42bad55ff Mon Sep 17 00:00:00 2001 From: Kathryn Andersen Date: Sun, 14 Nov 2010 16:22:15 +0000 Subject: Improve the speed of match_glob --- IkiWiki.pm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 08a3d7875..75b7a7b3e 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2482,6 +2482,8 @@ sub derel ($$) { return $path; } +my %glob_cache; + sub match_glob ($$;@) { my $page=shift; my $glob=shift; @@ -2489,8 +2491,14 @@ sub match_glob ($$;@) { $glob=derel($glob, $params{location}); - my $regexp=IkiWiki::glob2re($glob); - if ($page=~/^$regexp$/i) { + # Instead of converting the glob to a regex every time, + # cache the compiled regex to save time. + if (!exists $glob_cache{$glob} + or !defined $glob_cache{$glob}) { + my $re = IkiWiki::glob2re($glob); + $glob_cache{$glob} = qr/^$re$/i; + } + if ($page=~ $glob_cache{$glob}) { if (! IkiWiki::isinternal($page) || $params{internal}) { return IkiWiki::SuccessReason->new("$glob matches $page"); } -- cgit v1.2.3 From 321bf7ec19641d12626c71f87792b4edf40aa306 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 17 Nov 2010 20:04:55 +0000 Subject: match_glob: streamline glob cache slightly --- IkiWiki.pm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 75b7a7b3e..57e23fda8 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2493,8 +2493,7 @@ sub match_glob ($$;@) { # Instead of converting the glob to a regex every time, # cache the compiled regex to save time. - if (!exists $glob_cache{$glob} - or !defined $glob_cache{$glob}) { + if (!defined $glob_cache{$glob}) { my $re = IkiWiki::glob2re($glob); $glob_cache{$glob} = qr/^$re$/i; } -- cgit v1.2.3 From 788105e2a73a3be0f9a05a390702ee28318a5673 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 19 Nov 2010 23:59:04 +0000 Subject: glob2re: return a precompiled, anchored case-insensitive regex In practice every use of glob2re uses it like that. --- IkiWiki.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 57e23fda8..bb7d46ccf 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2388,7 +2388,7 @@ sub glob2re ($) { my $re=quotemeta(shift); $re=~s/\\\*/.*/g; $re=~s/\\\?/./g; - return $re; + return qr/^$re$/i; } package IkiWiki::FailReason; -- cgit v1.2.3 From 55515050e1f3aad13dc96796a347cefa98e8e472 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Sat, 20 Nov 2010 00:02:49 +0000 Subject: make use of precompiled regex objects --- IkiWiki.pm | 4 ++-- IkiWiki/Plugin/filecheck.pm | 2 +- IkiWiki/Plugin/meta.pm | 2 +- IkiWiki/Plugin/po.pm | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index bb7d46ccf..e5370f4a6 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2495,7 +2495,7 @@ sub match_glob ($$;@) { # cache the compiled regex to save time. if (!defined $glob_cache{$glob}) { my $re = IkiWiki::glob2re($glob); - $glob_cache{$glob} = qr/^$re$/i; + $glob_cache{$glob} = $re; } if ($page=~ $glob_cache{$glob}) { if (! IkiWiki::isinternal($page) || $params{internal}) { @@ -2667,7 +2667,7 @@ sub match_user ($$;@) { return IkiWiki::ErrorReason->new("no user specified"); } - if (defined $params{user} && $params{user}=~/^$regexp$/i) { + if (defined $params{user} && $params{user}=~$regexp) { return IkiWiki::SuccessReason->new("user is $user"); } elsif (! defined $params{user}) { diff --git a/IkiWiki/Plugin/filecheck.pm b/IkiWiki/Plugin/filecheck.pm index 3b0a7b314..4f4e67489 100644 --- a/IkiWiki/Plugin/filecheck.pm +++ b/IkiWiki/Plugin/filecheck.pm @@ -161,7 +161,7 @@ sub match_mimetype ($$;@) { } my $regexp=IkiWiki::glob2re($wanted); - if ($mimetype!~/^$regexp$/i) { + if ($mimetype!~$regexp) { return IkiWiki::FailReason->new("file MIME type is $mimetype, not $wanted"); } else { diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index 5cfa72833..47007afe2 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -355,7 +355,7 @@ sub match { } if (defined $val) { - if ($val=~/^$re$/i) { + if ($val=~$re) { return IkiWiki::SuccessReason->new("$re matches $field of $page", $page => $IkiWiki::DEPEND_CONTENT, "" => 1); } else { diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm index a79e7d7f0..79142ed1f 100644 --- a/IkiWiki/Plugin/po.pm +++ b/IkiWiki/Plugin/po.pm @@ -1297,7 +1297,7 @@ sub match_lang ($$;@) { my $regexp=IkiWiki::glob2re($wanted); my $lang=IkiWiki::Plugin::po::lang($page); - if ($lang !~ /^$regexp$/i) { + if ($lang !~ $regexp) { return IkiWiki::FailReason->new("file language is $lang, not $wanted"); } else { -- cgit v1.2.3 From b3bca318ef11ce9d0609d952a72849243b591b9d Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 20 Nov 2010 12:25:52 -0400 Subject: avoid an unnecessary hash lookup --- IkiWiki.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index e5370f4a6..f57ef8c6c 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -2493,11 +2493,11 @@ sub match_glob ($$;@) { # Instead of converting the glob to a regex every time, # cache the compiled regex to save time. - if (!defined $glob_cache{$glob}) { - my $re = IkiWiki::glob2re($glob); - $glob_cache{$glob} = $re; + my $re=$glob_cache{$glob}; + unless (defined $re) { + $glob_cache{$glob} = $re = IkiWiki::glob2re($glob); } - if ($page=~ $glob_cache{$glob}) { + if ($page =~ $re) { if (! IkiWiki::isinternal($page) || $params{internal}) { return IkiWiki::SuccessReason->new("$glob matches $page"); } -- cgit v1.2.3 From 8f64c69e084c698a389565203bd18bccb33f5d69 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:13:52 +0000 Subject: Compute local paths to the top of the wiki "local" here is short for "locally valid" - the idea is that we can use URLs that are relative in the sense of only having the path part, but absolute in the sense that they start from '/', such as '/~smcv/ikiwiki.cgi'. There's no particularly good name that I can find for these between-relative-and-absolute URLs. They're useful because in the common case where the pages and the CGI script have the same scheme and authority component, each page is identified by the same locally-valid URL when linking from any page or from the CGI, without hard-coding a choice between HTTP and HTTPS, or between multiple virtual hostnames with the same path layout. As such, we can use them in many situations that previously used an absolute URL. If there's no suitable semi-absolute value for local_url (for instance, if your pages and your CGI reside on different servers), we can just fall back to using the absolute URL. I append '/' because $config{url} doesn't end with '/', but the common case for local_url (on all branchable.com sites, for instance) is that it's just '/'. --- IkiWiki.pm | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index f57ef8c6c..1d37e7f8e 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -501,6 +501,12 @@ sub defaultconfig () { return @ret; } +# URL to top of wiki as a path starting with /, valid from any wiki page or +# the CGI; if that's not possible, an absolute URL. Either way, it ends with / +my $local_url; +# URL to CGI script, similar to $local_url +my $local_cgiurl; + sub checkconfig () { # locale stuff; avoid LC_ALL since it overrides everything if (defined $ENV{LC_ALL}) { @@ -537,7 +543,30 @@ sub checkconfig () { if ($config{cgi} && ! length $config{url}) { error(gettext("Must specify url to wiki with --url when using --cgi")); } - + + if (length $config{url}) { + eval q{use URI}; + my $baseurl = URI->new($config{url}); + + $local_url = $baseurl->path . "/"; + $local_cgiurl = undef; + + if (length $config{cgiurl}) { + my $cgiurl = URI->new($config{cgiurl}); + + $local_cgiurl = $cgiurl->path; + + if ($cgiurl->scheme ne $baseurl->scheme or + $cgiurl->authority ne $baseurl->authority) { + # too far apart, fall back to absolute URLs + $local_url = "$config{url}/"; + $local_cgiurl = $config{cgiurl}; + } + } + + $local_url =~ s{//$}{/}; + } + $config{wikistatedir}="$config{srcdir}/.ikiwiki" unless exists $config{wikistatedir} && defined $config{wikistatedir}; -- cgit v1.2.3 From 200c599dcaeb4dde77564b84022b67bf71cd6bfa Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:16:59 +0000 Subject: cgiurl: don't append "?" if there are no parameters This means we can use cgiurl() instead of $config{cgiurl} if an absolute URL isn't desired. --- IkiWiki.pm | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 1d37e7f8e..989f3bee7 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1044,6 +1044,11 @@ sub cgiurl (@) { $cgiurl=$params{cgiurl}; delete $params{cgiurl}; } + + unless (%params) { + return $cgiurl; + } + return $cgiurl."?". join("&", map $_."=".uri_escape_utf8($params{$_}), keys %params); } -- cgit v1.2.3 From 6be4e6d1a501fa10d7894ff46b4a812cddb26d49 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:20:32 +0000 Subject: cgiurl(): return a locally-valid path by default To get an absolute version you can use cgiurl(cgiurl => $config{cgiurl}). The only place in IkiWiki that seems to actually need an absolute URL is the openid plugin, and that already uses the named parameter. --- IkiWiki.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 989f3bee7..41e9e3f82 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1039,7 +1039,8 @@ sub linkpage ($) { sub cgiurl (@) { my %params=@_; - my $cgiurl=$config{cgiurl}; + my $cgiurl=$local_cgiurl; + if (exists $params{cgiurl}) { $cgiurl=$params{cgiurl}; delete $params{cgiurl}; -- cgit v1.2.3 From f032bce79158005032c09e4db75093abaca45751 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:25:45 +0000 Subject: baseurl(): return local path, not absolute URL, if the argument is undef --- IkiWiki.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 41e9e3f82..a4afef8e0 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1057,7 +1057,7 @@ sub cgiurl (@) { sub baseurl (;$) { my $page=shift; - return "$config{url}/" if ! defined $page; + return $local_url if ! defined $page; $page=htmlpage($page); $page=~s/[^\/]+$//; -- cgit v1.2.3 From 4c224ae143ebc4b13f824fe1782561a5cd165864 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 22 Nov 2010 23:33:13 +0000 Subject: urlto(): if $from is undef, return a local path, not an absolute URL --- IkiWiki.pm | 6 ++++++ doc/plugins/write.mdwn | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index a4afef8e0..ee0b1f1ea 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1148,6 +1148,12 @@ sub urlto ($$;$) { return $config{url}.beautify_urlpath("/".$to); } + if (! defined $from) { + my $u = $local_url; + $u =~ s{/$}{}; + return $u.beautify_urlpath("/".$to); + } + my $link = abs2rel($to, dirname(htmlpage($from))); return beautify_urlpath($link); diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 6b751f0cd..33db3e707 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -988,6 +988,10 @@ Construct a relative url to the first parameter from the page named by the second. The first parameter can be either a page name, or some other destination file, as registered by `will_render`. +If the second parameter is `undef`, the URL will be valid from any page on the +wiki, or from the CGI; if possible it'll be a path starting with `/`, but an +absolute URL will be used if the wiki and the CGI are on different servers. + If the third parameter is passed and is true, an absolute url will be constructed instead of the default relative url. -- cgit v1.2.3 From d01334b8e9c229895ecb6d0b0a7acda86515df71 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 23 Nov 2010 22:21:31 +0000 Subject: If cgiurl is set, but url isn't, use an absolute $local_cgiurl --- IkiWiki.pm | 3 +++ 1 file changed, 3 insertions(+) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index ee0b1f1ea..140f7f740 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -566,6 +566,9 @@ sub checkconfig () { $local_url =~ s{//$}{/}; } + else { + $local_cgiurl = $config{cgiurl}; + } $config{wikistatedir}="$config{srcdir}/.ikiwiki" unless exists $config{wikistatedir} && defined $config{wikistatedir}; -- cgit v1.2.3 From e4c6f5bcbe9edbf8091584fca9fbfe82e1175dac Mon Sep 17 00:00:00 2001 From: Craig Lennox Date: Sat, 27 Nov 2010 17:29:49 -0500 Subject: check that user is defined before regexp compare --- IkiWiki.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index 08a3d7875..b3d47ed6a 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1201,7 +1201,7 @@ sub userpage ($) { sub openiduser ($) { my $user=shift; - if ($user =~ m!^https?://! && + if (defined $user && $user =~ m!^https?://! && eval q{use Net::OpenID::VerifiedIdentity; 1} && !$@) { my $display; -- cgit v1.2.3 From 53d466a07f542dca86732764ab4f13608d701a1c Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 29 Nov 2010 14:59:48 -0400 Subject: second parameter of urlto is optional --- IkiWiki.pm | 2 +- doc/plugins/write.mdwn | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'IkiWiki.pm') diff --git a/IkiWiki.pm b/IkiWiki.pm index a893edb3b..97946bfcf 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -1134,7 +1134,7 @@ sub beautify_urlpath ($) { return $url; } -sub urlto ($$;$) { +sub urlto ($;$$) { my $to=shift; my $from=shift; my $absolute=shift; diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 726ace8d3..ccdf9f393 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -982,7 +982,7 @@ This is the standard gettext function, although slightly optimised. This is the standard ngettext function, although slightly optimised. -### `urlto($$;$)` +### `urlto($;$$)` Construct a relative url to the first parameter from the page named by the second. The first parameter can be either a page name, or some other -- cgit v1.2.3