document new rcs reversion support functions

master
Joey Hess 2010-10-04 16:22:50 -04:00
parent 68670cad82
commit 3f3aab3793
3 changed files with 116 additions and 84 deletions

View File

@ -748,73 +748,72 @@ sub git_find_root {
}
sub git_parse_changes {
my @changes = @_;
my @changes = @_;
my $subdir = git_find_root();
my @rets;
foreach my $ci (@changes) {
foreach my $detail (@{ $ci->{'details'} }) {
my $file = $detail->{'file'};
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);
}
# 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'};
}
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");
}
}
# 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)) {
# 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'.");
}
}
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,
};
}
}
push @rets, {
file => $file,
action => $action,
path => $path,
};
}
}
return @rets;
return @rets;
}
sub rcs_receive () {
@ -832,7 +831,7 @@ sub rcs_receive () {
# are in the master git repo, not the srcdir repo.
# The pre-receive hook already puts us in the right place.
$no_chdir=1;
push @rets, git_parse_changes(git_commit_info($oldrev."..".$newrev));
push @rets, git_parse_changes(git_commit_info($oldrev."..".$newrev));
$no_chdir=0;
}
@ -840,31 +839,31 @@ sub rcs_receive () {
}
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.
# Note test_changes expects 'cgi' and 'session' parameters.
my %params = @_;
my $rev = $params{rev};
my %params = @_;
my $rev = $params{rev};
require IkiWiki::Receive;
IkiWiki::Receive::test_changes(%params, changes => [git_parse_changes(git_commit_info($rev, 1))]);
# Note test_changes expects 'cgi' and 'session' parameters.
require IkiWiki::Receive;
IkiWiki::Receive::test_changes(%params, changes =>
[git_parse_changes(git_commit_info($rev, 1))]);
}
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};
# Try to revert the given patch; returns undef on _success_.
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.";
}
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), @_);
}
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);
}
}
sub rcs_showpatch (@) {

View File

@ -1176,9 +1176,9 @@ sense to implement for all RCSs.
It should examine the incoming changes, and do any sanity
checks that are appropriate for the RCS to limit changes to safe file adds,
removes, and changes. If something bad is found, it should exit
nonzero, to abort the push. Otherwise, it should return a list of
files that were changed, in the form:
removes, and changes. If something bad is found, it should die, to abort
the push. Otherwise, it should return a list of files that were changed,
in the form:
{
file => # name of file that was changed
@ -1191,6 +1191,33 @@ files that were changed, in the form:
The list will then be checked to make sure that each change is one that
is allowed to be made via the web interface.
#### `rcs_preprevert($)`
This is called by the revert web interface. It is passed a RCS-specific
change ID, and should determine what the effects would be of reverting
that change, and return the same data structure as `rcs_receive`.
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(@)`
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.
#### `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

View File

@ -65,3 +65,9 @@ Peter Gammie has done an initial implementation of the above.
>> gets used to check whether attachments are allowed -- there really should be a hook for that.
>>
>> Please look it over and tell me what else needs fixing... -- [[peteg]]
>>> I have made my own revert branch and put a few fixes in there. Issues
>>> I noticed but have not gotten to:
>>>
>>> * `rcs_diff` already exists; why add `rcs_showpatch`?
>>> *