Blame dist/patme

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