#!/usr/bin/perl # Copyright (C) 2007 Eric L. Wilhelm use warnings; use strict; =head1 NAME svn_cherry - cherry-pick a commit from current changes =cut =begin test qw(svnadmin create --fs-type fsfs), "$tmpdir/repo" chdir($tmpdir); qw(svn co), "file://$tmpdir/repo co" # make a file qw(svn add $file) # make some changes # cherry-pick 1-2 of them # commit # check the diff # and with abort # and with multiple changed files =end test =cut package bin::svn_cherry; use IPC::Run (); use File::Temp (); use VCfs; use Getopt::Helpful; sub main { my (@args) = @_; my $patch; my $hopt = Getopt::Helpful->new( usage => 'CALLER [options]', ['p|patch', \$patch, '', 'make a patch instead of commit'], '+help', ); $hopt->Get_from(\@args); my @files = @args or die "need files"; # XXX this can't get much better without getting rather elaborate. # Ideally, you would have a checkout dedicated to cherry-picking, # which would be an exact copy+revert of this directory (thus, the # same version), and the interaction would involve maybe some editing # and running tests or something. my $vc = VCfs->new('.'); my %st = $vc->status(@files); my @changed = grep({$st{$_} =~ m/^M/} @files); #my @diff_prog = qw(gvimdiff -f); my @diff_prog = qw(kompare); my %fmap = map({(my $l = $_) =~ s#/+#-#g; $_ => "$l.local"} @changed); rename($_, $fmap{$_}) for(@changed); system(qw(svn revert -q), $_) for(@changed); system(@diff_prog, $fmap{$_}, $_) for(@changed); if($patch) { system(qw(svn diff), @files); } else { system(qw(svn ci), @files) and die "argh"; } rename($fmap{$_}, $_) for(@changed); # ... ? qw(svn cat -r BASE) $file > #foreach my $file (@files) { # (my $filebase = $file) =~ s#/+#-#g; # my ($fh, $tmp) = File::Temp::tempfile($filebase . '.orig.' . 'X'x8); # IPC::Run::run([qw(svn cat -r BASE)], \undef, '>', $tempfile) or # die "oops $?"; #} } package main; if($0 eq __FILE__) { bin::svn_cherry::main(@ARGV); } # vi:ts=2:sw=2:et:sta my $package = 'bin::svn_cherry';