summaryrefslogtreecommitdiff
path: root/dist/patme
diff options
context:
space:
mode:
Diffstat (limited to 'dist/patme')
-rwxr-xr-xdist/patme351
1 files changed, 351 insertions, 0 deletions
diff --git a/dist/patme b/dist/patme
new file mode 100755
index 0000000..0fd50ee
--- /dev/null
+++ b/dist/patme
@@ -0,0 +1,351 @@
+#!/usr/bin/perl
+
+use Getopt::GUI::Long;
+use QWizard;
+use QWizard::API;
+use Data::Dumper;
+use Cwd;
+
+use Getopt::Std;
+Getopt::GUI::Long::Configure(qw(display_help no_ignore_case));
+
+use strict;
+
+our %opts =
+(
+ 'd' => $ENV{'HOME'} . "/src/snmp/patme/",
+ 'b' => 'main,5.6,5.5,5.4,5.3',
+ 'p' => '-p0',
+);
+
+# sets the order shown
+our @codetrees = ('main',
+ '5.6',
+ '5.5',
+ '5.4',
+ '5.3',
+ '5.2',
+ '5.1',
+ '5.0',
+ 'UCD');
+
+our %codetrees = ('5.0' => 'V5-0-patches',
+ '5.1' => 'V5-1-patches',
+ '5.2' => 'V5-2-patches',
+ '5.3' => 'V5-3-patches',
+ '5.4' => 'V5-4-patches',
+ '5.5' => 'V5-5-patches',
+ '5.6' => 'V5-6-patches',
+ 'main' => 'net-snmp',
+ 'UCD' => 'V4-2-patches');
+
+our (@captures, $capfilt, $result, %captures, $capturenum);
+
+GetOptions(\%opts,
+ ['f|file=s', 'Patch file'],
+ ['d|base-directory=s', 'Base directory of checkouts'],
+ ['p|patch-args=s', 'Default patch arguments (-p1)'],
+
+ ['GUI:separator', 'Patch application specifics;'],
+ ['b|braches=s', 'Branches to apply to (eg 5.1,5.2,...)'],
+ ['m|commit-msg=s', 'Default commit message to use'],
+ ['D|subdir=s', 'Apply patches to a subdirectory'],
+ ['u|no-update', 'Do not run svn status/update in the directory first. Only use this if it\'s known clean.'],
+ );
+
+my %bs;
+if ($opts{'b'}) {
+ map { $bs{$_} = 1; } split(/,\s*/,$opts{'b'});
+}
+$opts{'d'} .= "/" if ($opts{'d'} !~ /\/$/);
+
+my $qw = new QWizard();
+my $pris = load_primaries();
+$qw->{'primaries'} = $pris;
+
+$qw->qwparam('svncommit',$opts{'m'}) if ($opts{'m'});
+
+$qw->magic('top');
+
+sub make_tops {
+ my @tops;
+ foreach my $k (@codetrees) {
+ push @tops,
+ qw_checkbox($k, "Apply to $k", 1, 0,
+ default => $qw->qwparam($k) || $bs{$k},
+ override => 1);
+ }
+ return @tops;
+}
+
+sub load_primaries {
+ my @tops = make_tops();
+ return
+ {
+ top =>
+ qw_primary('top','Select packages to apply the patch to:', '',
+ [@tops,
+ qw_text('basedir', 'Base code directory:',
+ default => $opts{'d'}),
+ qw_hidden('no_confirm',1),
+ qw_text('patchfile','Patch file:', default => $opts{f},
+ check_value => sub {
+ return "patch file doesn't exist" if (! -f qwparam('patchfile'))
+ }),
+ qw_checkbox('noupdate','Don\'t run svn update/revert first:',
+ 1, 0, default => $opts{'u'} || 0)],
+ [],[],sub_modules => ['commit', 'commitmsg', 'maketest',
+ 'edit', 'applying', 'check',
+ 'patch_info']),
+
+ patch_info =>
+ qw_primary('check','Checking code directory status:', '',
+ [qw_paragraph('patch pieces:',
+ sub { capture("egrep '^(---|\\+\\+\\+)' " .
+ qwparam('patchfile'))},
+ width => 80,
+ height => 30),
+ qw_text('patchargs','Patch arguments',
+ default => $opts{'p'}),
+ qw_text('subdir', 'Apply in package subdir:',
+ default => $opts{'D'}),
+ qw_paragraph('Note:','Hitting next below will first clean your local repositories which could take a bit (watch the console for deails on what it\'s doing at any moment)', doif => sub {!qwparam('noupdate')}),
+]),
+
+
+ check =>
+ qw_primary('check','Checking code directory status:', '',
+ [qw_paragraph('removed .rej files:',
+ sub { my $it = captureeachdir('find . -name \*.rej');
+ captureeachdir('find . -name \*.rej | xargs rm -f');
+ return $it;
+ },
+ preformatted => 1,
+ width => 80,
+ height => 60,
+ ),
+ qw_paragraph('svn update:',
+ sub {
+ my ($res, $one);
+ foreach my $k (@codetrees) {
+ next if (!qwparam($k));
+ $res .= "$k:\n";
+ $one = capturedir($codetrees{$k},
+ "svn update");
+ $res .= $one;
+ $one = capturedir($codetrees{$k},
+ "svn revert -R .");
+ $res .= $one;
+ }
+ return $res;
+ },
+ preformatted => 1,
+ width => 80,
+ height => 60,
+ doif => sub{!qwparam('noupdate')}
+ ) ],
+ ),
+
+ applying =>
+ qw_primary("applying", 'Applying patches to the code bases', '',
+ [{type => 'table',
+ text => 'Results:',
+ values => sub {
+ my @tab;
+ foreach my $k (@codetrees) {
+ next if (!qwparam($k));
+ push @tab, [$k,
+ qw_paragraph("r$k","",
+ preformatted => 1,
+ width => 80,
+ height => 20,
+ values =>
+ sub { my $cmd = "patch " . qwparam('patchargs') . " < " . qwparam('patchfile');
+ my $results = "Running on $k: $cmd" . "\n" . capturedir($codetrees{$k},$cmd);
+ return $results})];
+ }
+ return [\@tab];
+ }}],[],[]),
+
+ edit =>
+ qw_primary('edit','Fix the following files:','',
+ [qw_paragraph('Fix these (maybe):',
+ sub {
+ $capfilt = '(.*.rej)';
+ my $res =
+ captureeachdir('find . -name \*.rej');
+ print Dumper(\%captures);
+ $capfilt = undef;
+ return $res;
+ },
+ preformatted => 1,
+ width => 80,
+ height => 60,
+ ),
+ qw_label('failed files:',
+ sub { $capturenum = 0;
+ map { $capturenum += $#{$captures{$_}} + 1;
+ } (keys(%captures));
+ return $capturenum;
+ }),
+ qw_checkbox('edithem','Open an editor on the failed files?',
+ 1, 0, doif => sub { return $capturenum > 0 }),
+ qw_text('editor','Editor:',default => $ENV{'EDITOR'} || 'vi',
+ doif => sub { return $capturenum > 0 })],
+ [sub {
+ if (qwparam('edithem')) {
+ foreach my $k (keys(%captures)) {
+ foreach my $f (@{$captures{$k}}) {
+ my $file = qwparam('basedir') .
+ $codetrees{$k} .
+ qwparam('subdir') . '/' . $f->[0];
+ print STDERR "editing: $file\n";
+ system(qwparam('editor') . " " . $file);
+ }
+ }
+ }
+ }]
+ ),
+
+ maketest =>
+ qw_primary("maketest", "Run make?",'',
+ [qw_checkbox('makeit','Run make?', 1, 0),
+ qw_checkbox('maketest', 'Run make test?', 1, 0)
+ ],
+ [sub {
+ if (qwparam('makeit') || qwparam('maketest')) {
+ $_[0]->add_todos(-early, 'domake');
+ }
+ }]
+ ),
+
+ domake =>
+ qw_primary("domake", "Make results",'',
+ [qw_paragraph('Make results:',
+ sub { return captureeachdir('make'); },
+ preformatted => 1,
+ width => 80,
+ height => 20,
+ doif => sub { qwparam('makeit') }
+ ),
+ qw_paragraph('Make test results:',
+ sub { return captureeachdir('make test'); },
+ preformatted => 1,
+ width => 80,
+ height => 20,
+ doif => sub { qwparam('maketest') }
+ )]
+ ),
+
+ commitmsg =>
+ qw_primary("commitmsg", 'Commit info:', '',
+ [qw_text('svncommit','Commit message',
+ default => qwparam('svncommit') || $opts{'m'}),
+ {type => 'dynamic',
+ values => sub { my @tops = make_tops(1); return \@tops}}]),
+
+ commit =>
+ qw_primary("commit", 'running commit:', '',
+ [qw_paragraph('committing files:',
+ sub { my $msg = qwparam('svncommit');
+ $msg =~ s/\'/\'\"\'\"\'/g; # escape 's
+ return capturedir($opts{'d'},
+ 'svn commit -m \'' . $msg . '\' ' . get_codedirs_str()); },
+ preformatted => 1,
+ width => 80,
+ height => 20,
+ )]),
+
+ editing =>
+ qw_primary("applying", 'Edit the following files:', '',
+ [{type => 'table',
+ text => 'Results:',
+ values => sub { return [\@captures]},
+ }],[],[])
+ }
+}
+
+sub capture {
+ my $cmd = join(" ",@_);
+ my $results = "Running: $cmd\n";
+ my @a;
+ print $results;
+ open(I,"$cmd 2>&1|");
+ while (<I>) {
+ $results .= $_;
+ print $_;
+ if ($capfilt) {
+ print "capfilt: $capfilt\n";
+ @a = /$capfilt/;
+ print " capfilt: @a\n";
+ push @captures, [@a];
+ }
+ }
+ close(I);
+ $result = $? >> 8;
+ $results .= "RESULT: " . (($result) ? "FAIL" : "SUCCESS") . "($result)\n";
+ return $results;
+}
+
+sub capturedir {
+ my $dir = shift;
+ $dir .= "/" if ($dir !~ /\/$/);
+ my $basedir = qwparam('basedir');
+ $basedir .= "/" if ($basedir !~ /\/$/);
+ my $olddir = getcwd();
+ my $newdir = "$basedir$dir" . qwparam('subdir');
+ my $res = "changing to: $newdir\n";
+ print $res;
+ chdir($newdir);
+ $res .= capture(@_);
+ chdir($olddir);
+ return $res;
+}
+
+sub get_codedirs_str() {
+ my $res = "";
+ foreach my $k (@codetrees) {
+ next if (!qwparam($k));
+ $res .= " $opts{'d'}$codetrees{$k}";
+ }
+ $res =~ s/^ //;
+ return $res;
+}
+
+sub captureeachdir {
+ my $out;
+ %captures = ();
+ foreach my $k (@codetrees) {
+ next if (!qwparam($k));
+ $out .= "$k:\n";
+ $out .= capturedir($codetrees{$k}, @_) . "\n";
+ if ($#captures > -1) {
+ @{$captures{$k}} = @captures;
+ @captures = ();
+ }
+ }
+ return $out;
+}
+
+sub dodir {
+ my $text = shift;
+ return
+ [{type => 'table',
+ text => $text,
+ values => [[sub {
+ my @tab;
+ foreach my $k (@codetrees) {
+ next if (!qwparam($k));
+ push @tab, [$k,
+ qw_paragraph("r$k","",
+ preformatted => 1,
+ width => 80,
+ height => 20,
+ values =>
+ [[sub { $_->[0]($k)},
+ @_]])];
+ }
+ return [\@tab];
+ }, @_]]
+ }];
+}