SPECS: patchtool.pl (NEW) - NEW, helper for patch creation and upd...
sparky
sparky at pld-linux.org
Fri Aug 4 00:45:16 CEST 2006
Author: sparky Date: Thu Aug 3 22:45:16 2006 GMT
Module: SPECS Tag: HEAD
---- Log message:
- NEW, helper for patch creation and updates
---- Files affected:
SPECS:
patchtool.pl (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SPECS/patchtool.pl
diff -u /dev/null SPECS/patchtool.pl:1.1
--- /dev/null Fri Aug 4 00:45:16 2006
+++ SPECS/patchtool.pl Fri Aug 4 00:45:10 2006
@@ -0,0 +1,276 @@
+#!/usr/bin/perl
+#
+# Licensed under GPL
+# (c) 2006 PLD Linux Distribution
+#
+use strict;
+use warnings;
+
+my $spec = shift @ARGV or die "No spec file specified\n";
+my $patch_name = shift @ARGV || "";
+(my $pkgname = $spec) =~ s/\.spec$//;
+
+
+sub dml {
+ my $out;
+ $out .= "Work on existing patch:<br>\n";
+ $out .= "<menu id=existing_patch>\n";
+ foreach my $pn (sort keys %{$_[0]}) {
+ (my $patch = $_[0]->{$pn}) =~ s/_/__/g;
+ $out .= "<item id=$pn> $patch\n";
+ }
+ $out .= "</menu>\n";
+
+ $out .= "Create new: <br>\n";
+ $out .= "<input id=new_patch><br>\n";
+ $out .= "<button>";
+
+ my $ret = undef;
+ open DML_IN, "-|", "dml", "-t", "sed to patch", "$out";
+ while (<DML_IN>) {
+ $ret = $1
+ if not defined $ret and /existing_patch="([0-9]+)"/;
+ $ret = $1 if /new_patch="(.+)"/;
+ }
+ close DML_IN || die "child died\n";
+ return $ret;
+}
+
+my %patches = ();
+my $last_patch_num = -1;
+{
+ open F_IN, $spec or die "Can't open $spec: $!\n";
+ while (<F_IN>) {
+ chop;
+ last if $_ eq "\%description";
+ if ( /Patch([0-9]+):\s*(.*)/ ) {
+ my $n = $1;
+ ($patches{$n} = $2) =~ s/\%{name}/$pkgname/;
+ $last_patch_num = $n if $n > $last_patch_num;
+ }
+ }
+ close F_IN;
+}
+
+my $patch = undef;
+my $patch_file = undef;
+my $patch_num = undef;
+do {
+ $patch = dml(\%patches);
+} until (defined $patch);
+
+
+print "D: patch '$patch'\n";
+if ($patch =~ /^([0-9]+)$/) {
+ print "D: existing patch\n";
+ $patch_num = $patch;
+ $patch_file = $patches{$patch_num};
+ ($patch = $patch_file) =~ s/\.(diff|patch)$//;
+ $patch =~ s/^$pkgname([-_]?)//;
+ die "Can't find $patch_file file.\n"
+ unless -r "../SOURCES/$patch_file";
+} else {
+ print "D: new patch\n";
+ $patch =~ s/\.(diff|patch)$//;
+ $patch =~ s/^$pkgname([-_])//;
+ $patch_file = "$pkgname-$patch.patch";
+ warn "File $patch_file already exists, using it.\n"
+ if -r "../SOURCES/$patch_file";
+ $patch_num = $last_patch_num + 1;
+}
+
+
+my $patch_opts = "";
+{ # create new spec file and temporary spec
+ open F_IN, $spec;
+ open F_OUT_TEMP, ">", "patchtool.spec";
+ open F_OUT_NEW, ">", "$spec.new";
+ sub print2($) {
+ print F_OUT_TEMP $_[0];
+ print F_OUT_NEW $_[0];
+ }
+ while (<F_IN>) {
+ last if /^Patch$patch_num:/;
+ if (/^(URL:|BuildRequires:|Requires|Provides:|Obsoletes:|BuildRoot:)/) {
+ print F_OUT_NEW "Patch$patch_num:\t";
+ print F_OUT_NEW "\t" if $patch_num < 10;
+ print F_OUT_NEW "\%{name}-$patch.patch\n";
+ last;
+ }
+ print2($_);
+ }
+ print2($_);
+
+ while (<F_IN>) {
+ print2($_);
+ last if /\%prep/;
+ }
+ my @buf = ();
+ sub flush_buf() {
+ while (my $l = shift @buf) {
+ print2($l);
+ }
+ }
+ while (<F_IN>) {
+ flush_buf() if /^(#?\s*%?\%patch|\%setup)/;
+ push @buf, $_;
+
+ if (/^#?\s*%?\%patch$patch_num\s+(.*)/ or /^\%build/) {
+ $patch_opts = $1 || "-p1";
+ if (/^\%build/) {
+ # print first buffer line, as it's %setup or %patch
+ print2(shift @buf);
+ } else {
+ # avoid printing %patch twice
+ shift @buf;
+ flush_buf();
+ }
+ print F_OUT_TEMP "echo \$PWD > $ENV{PWD}/patchtool.srcdir\nexit 1\n";
+ print F_OUT_NEW "\%patch$patch_num -p1\n";
+ last;
+ }
+
+ }
+ flush_buf();
+ while (<F_IN>) {
+ print2($_);
+ }
+
+ close F_OUT_TEMP;
+ close F_OUT_NEW;
+ close F_IN;
+}
+
+unlink "patchtool.srcdir";
+system( qw(./builder -nn -bp patchtool.spec) );
+print "=============================================================\n";
+open F_IN, "patchtool.srcdir" or die;
+my $builddir = <F_IN>;
+close F_IN;
+die unless length $builddir;
+chomp $builddir;
+
+my $rpmSPECS = $ENV{PWD};
+(my $rpmBUILD = $builddir) =~ s#/BUILD/.*#/BUILD#;
+(my $srcdir = $builddir) =~ s#.*/BUILD/+##;
+$srcdir =~ s#/.*##;
+
+chdir $rpmBUILD;
+system("find '$srcdir' -name *.orig -or -name *~ -print0 | xargs -0 -r -l512 rm -f");
+
+my $srcorig = $srcdir.".orig";
+my $srcpatch = $srcdir.".".$patch;
+system(qw(rm -rf), $srcorig);
+rename($srcdir, $srcorig);
+system(qw(rm -rf), $srcpatch);
+my @cp = (qw(cp -a), $srcorig, $srcpatch);
+system(@cp);
+die "Can't copy from $srcorig to $srcpatch: $!\n" if $?;
+
+quotemeta $srcdir;
+$builddir =~ s#$srcdir#$srcpatch#;
+chdir $builddir;
+
+if (-r "$rpmSPECS/../SOURCES/$patch_file") {
+ unless (length $patch_opts) {
+ print "trying to guess -pN option\n";
+ $patch_opts = "-p1";
+ }
+ system("patch $patch_opts < '$rpmSPECS/../SOURCES/$patch_file'");
+}
+
+sub diffcol {
+ $_ = $_[0];
+ chomp;
+ s//[44m^[[49m/g;
+ s//[44m^G[49m/g;
+ s/^(Index:|diff|---|\+\+\+) /[32m$1 /;
+ s/^@@ /[33m@@ /;
+ s/^-/[35m-/;
+ s/^\+/[36m+/;
+ s/
/[44m^M[49m/g;
+ #s/ / /g;
+ s/(\S)(\s+)$/$1[41m$2[49m/;
+ s/$/[0m/;
+ print $_."\n";
+}
+
+sub make_patch() {
+ chdir $builddir;
+ system("find -name *.orig -or -name *~ -print0 | xargs -0 -r -l512 rm -f");
+ chdir $rpmBUILD;
+ system("diff -Nur '$srcorig' '$srcpatch' > '$rpmSPECS/../SOURCES/$patch_file'");
+}
+
+sub show_patch() {
+ open F_IN, "$rpmSPECS/../SOURCES/$patch_file";
+ while (<F_IN>) {
+ diffcol($_);
+ }
+ close F_IN;
+}
+
+sub compile() {
+ chdir $rpmSPECS;
+ system( qw(./builder -nn -bb), $spec.".new" );
+}
+
+sub finish() {
+ chdir $rpmSPECS;
+ rename $spec, $spec.".orig";
+ rename $spec.".new", $spec;
+}
+
+{ # prepare bashrc file
+ open F_OUT, ">", "$ENV{HOME}/.bash_patchtool"
+ or die "Can't create rc file: $!\n";
+ print F_OUT <<'EOF';
+if [ -f ~/.bash_profile ]; then
+ . ~/.bash_profile
+elif [ -f ~/.bashrc ]; then
+ . ~/.bashrc
+fi
+
+PS1='\[\033[1m\][\[\033[31m\]patchtool \[\033[34m\]\W\[\033[37m\]]$\[\033[0m\] '
+export PS1
+
+# allways return 0 on exit
+alias exit=":; exit"
+alias show="exit 133"
+alias compile="exit 134"
+alias finish="exit 135"
+alias quit="exit 136"
+cat << 'EOF'
+
+Commands:
+quit - exit without applying changes
+finish - apply changes and exit
+compile - apply changes and try to compile, don't exit
+show - show resulting patch
+EOF
+ close F_OUT;
+}
+
+
+my $ret = 0;
+for (;;) {
+ chdir $builddir;
+ system(qw(bash --rcfile), $ENV{HOME}."/.bash_patchtool");
+ $ret = $?>>8;
+ redo if $ret == 0;
+ if ($ret == 133) { # show
+ make_patch();
+ show_patch();
+ } elsif ($ret == 134) { # compile
+ make_patch();
+ compile();
+ } elsif ($ret == 135) { # finish
+ make_patch();
+ finish();
+ exit 0;
+ } elsif ($ret == 136) { # quit
+ exit 0;
+ } else {
+ print "unrecognized return code: $ret\n";
+ }
+}
================================================================
More information about the pld-cvs-commit
mailing list