[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: little scripts to generate and apply diff series for Subversion

From: Liu Yubao <yubao.liu_at_gmail.com>
Date: 2007-01-09 06:25:03 CET

Liu Yubao wrote:
> Liu Yubao wrote:
>> Hi,
>>
>> I wrote two little scripts to generate and apply diff series for Subversion,
>> you need Subversion command line client and patch utility program to run it.
>> Windows users can download the latter from http://gnuwin32.sourceforge.net or
>> http://unxutils.sourceforge.net. I hope they are useful for you.
>>
>
> I got a notification said my attachments had been blocked, so I embed them
> in mail body.
>
> Here is svn-diffs.pl, svn-patches.pl will be next mail.

svn-patches.pl:
--------------------------------
#!/usr/bin/perl -w
#
# svn-patches.pl:
# apply a diff series generated by another little Perl script svn-diffs.pl.
#
# set environment variables "SVNUSER" and "SVNPASSWD" to provide
# user name and password if needed.
#
# note:
# svn properties are ignored, merge is done with GNU patch, no 3-way
# merge.
#
# 2007-01-09 Liu Yubao <yubao.liu@gmail.com>
#
use strict;
use warnings;
use File::Copy;
use File::Spec;

my $diffsDIR = shift;

die "Usage: perl $0 diffsDIR\n" if !defined $diffsDIR;

my $LANG=$ENV{LANG};
$ENV{LANG} = "en_US.UTF-8"; # make parsing easy
my $svncmd = "svn";
if (exists $ENV{SVNUSER} && exists $ENV{SVNPASSWD}) {
    $svncmd .= " --username $ENV{SVNUSER} --password $ENV{SVNPASSWD} ";
}

######################################################
# check whether svn has been installed
#
if (! qx/svn --version/) {
    die "[svn-patches] Can't execute 'svn': $!\n";
}

######################################################
# check whether patch has been installer
#
if (! qx/patch --version/) {
    die "[svn-patches] Can't execute 'patch': $!\n";
}

######################################################
# check whether we are in a clean working copy
#
die "[svn-patches] Not a clean working copy.\n" if `svn status`;

######################################################
# retrieve last applied diff
#
my $svnadminDIR = ".svn";
$svnadminDIR = "_svn" if exists $ENV{SVN_ASP_DOT_NET_HACK};

my $prevDIFF;
my $prevDIFF_file = File::Spec->catfile($svnadminDIR, "_prevDIFF_");
if (-e $prevDIFF_file) {
    open F, "<$prevDIFF_file" || die "[svn-patches] Can't open $prevDIFF_file: $!\n";
    $prevDIFF = <F>;
    chomp $prevDIFF;
    close F;
}

######################################################
# apply diffs as many as possible or only one
#
my @diffs = glob(File::Spec->catfile($diffsDIR, "*.diff"));
die "[svn-patches] No .diff found in $diffsDIR.\n" if @diffs < 1;

@diffs = sort {
    my ($a1) = $a =~ /\d+-\d+-(\d+)\.diff$/;
    my ($b1) = $b =~ /\d+-\d+-(\d+)\.diff$/;
    $a1 <=> $b1;
} @diffs;

my $nextDIFF; # diff being applied
if (!defined $prevDIFF) {
    $nextDIFF = 0;
} else {
    for ($nextDIFF = 0; $nextDIFF < @diffs; ++$nextDIFF) {
        last if $diffs[$nextDIFF] eq $prevDIFF;
    }
    if ($nextDIFF == @diffs) {
        print "[svn-patches] Can't find previous diff '$prevDIFF', can't go on patching\n";
        exit -1;
    } elsif ($nextDIFF == @diffs - 1) {
        print "[svn-patches] All patches have been applied, great!\n";
        unlink $prevDIFF_file;
        exit 0;
    } else {
        ++$nextDIFF;
    }
}

my $ret = 0;
while ($nextDIFF < @diffs) {
    print "------------------------------------------------------\n";
    print "[svn-patches] Applying '$diffs[$nextDIFF]'...\n";
    $ret = system "patch -N -p0 <" . $diffs[$nextDIFF];
    if ($ret < 0) {
        print "[svn-patches] Error happened when executed 'patch -p0': $!\n";
        print "[svn-patches] run me again after you have fixed the problem.\n";
        last;
    } elsif ($ret > 0) { # conflict
        $prevDIFF = $diffs[$nextDIFF];
        copy_binary_files();
        save_state();
        print "[svn-patches] run me again after you have resolved conflicts.\n";
        last;
    } else {
        $prevDIFF = $diffs[$nextDIFF];
        copy_binary_files();
        save_state();
        ++$nextDIFF;
        print "[svn-patches] Successfully applied, great!\n";
        # print "[svn-patches] Try to commit it...\n";
            print "[svn-patches] run me again after you have checked and committed these changes.\n";
            last;
    }
}

######################################################
#
sub save_state {
    print "[svn-patches] Save applying state to $prevDIFF_file.\n";
    open F, ">$prevDIFF_file" || die "[svn-patches] Can't write $prevDIFF_file: $!\n";
    print F "$prevDIFF\n";
    close F;
}

######################################################
#
sub copy_binary_files {
    my $idx = $prevDIFF;
    $idx =~ s/\.diff$/\.idx/;

    if (-e $idx) {
        open F, "<$idx" || die "[svn-patches] Can't read $idx: $!\n";
        my (@files, $prefix, $f);
        @files = <F>;
        chomp @files;
        $prefix = $idx;
        $prefix =~ s/\.idx$//;
        for (my $i = 0; $i < @files; ++$i) {
            $f = "$prefix-$i.bin";
            print "[svn-patches] Copy $f to $files[$i].\n";
            copy $f, $files[$i] || die "[svn-patches] Can't copy '$f' to '$files[$i]': $!\n";
        }
        close F;
    }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Tue Jan 9 06:27:05 2007

This is an archived mail posted to the Subversion Users mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.