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//^[/g;
+	s//^G/g;
+	s/^(Index:|diff|---|\+\+\+) /$1 /;
+	s/^@@ /@@ /;
+	s/^-/-/;
+	s/^\+/+/;
+	s/
/^M/g;
+	#s/	/    /g;
+	s/(\S)(\s+)$/$1$2/;
+	s/$//;
+	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