&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'skip-check' => \( my $skip_branch_check ),
+ 'shell|s' => \( my $launch_shell ),
'gen:s' => \( my $incl_generated_files ),
'help|h' => \( my $help_opt ),
);
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
die "No '.git' directory present in the current dir.\n" unless -d '.git';
-unless ($skip_branch_check) {
- open(IN, '-|', 'git status') or die $!;
- my $status = join('', <IN>);
- close IN;
- die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
- die "The checkout is not on the master branch.\n" unless $status =~ /^# On branch master\n/;
+my($status, $is_clean, $starting_branch) = &check_git_status;
+if (!$skip_branch_check && !$is_clean) {
+ die "The checkout is not clean:\n", $status;
}
my @extra_files;
}
my $last_touch = time;
-my(@patches, %local_patch);
+my(%patches, %local_patch);
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-a') or die $!;
while (<PIPE>) {
if (m# origin/patch/(.*)#) {
- push(@patches, $1);
+ $patches{$1} = 1;
} elsif (m# patch/(.*)#) {
- $local_patch{$1} = 1;
+ $patches{$1} = $local_patch{$1} = 1;
}
}
close PIPE;
+my @patches = sort keys %patches;
+
my(%parent, %description);
foreach my $patch (@patches) {
my $branch = ($local_patch{$patch} ? '' : 'origin/') . "patch/$patch";
my %completed;
foreach my $patch (@patches) {
next if $completed{$patch}++;
- update_patch($patch);
+ last unless update_patch($patch);
}
if ($incl_generated_files) {
}
sleep 1 if $last_touch == time;
-system "git checkout master" and exit 1;
+system "git checkout $starting_branch" and exit 1;
exit;
sleep 1 if $incl_generated_files && $last_touch == time;
if ($local_patch{$patch}) {
- system "git checkout patch/$patch" and exit 1;
+ system "git checkout patch/$patch" and return 0;
} else {
- system "git checkout --track -b patch/$patch origin/patch/$patch" and exit 1;
+ system "git checkout --track -b patch/$patch origin/patch/$patch" and return 0;
}
- open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
- print OUT $description{$patch}, "\n";
-
- if (system("git merge $parent") != 0) {
- print qq|"git merge $parent" incomplete -- please fix.\n|;
+ my $ok = system("git merge $parent") == 0;
+ if (!$ok || $launch_shell) {
+ print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
$ENV{PS1} = "[$parent] patch/$patch: ";
- system $ENV{SHELL} and exit 1;
+ while (1) {
+ if (system($ENV{SHELL}) != 0) {
+ print "Abort? [n/y] ";
+ $_ = <STDIN>;
+ next unless /^y/i;
+ return 0;
+ }
+ ($status, $is_clean) = &check_git_status;
+ last if $is_clean;
+ print $status;
+ }
}
+ open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
+ print OUT $description{$patch}, "\n";
+
if ($incl_generated_files) {
- system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
+ system "./config.status Makefile && make gen && rsync -a @extra_files $tmp_dir/$patch/";
}
$last_touch = time;
}
close OUT;
+
+ 1;
}
exit;
+sub check_git_status
+{
+ open(IN, '-|', 'git status') or die $!;
+ my $status = join('', <IN>);
+ close IN;
+ my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
+ my($starting_branch) = $status =~ /^# On branch (.+)\n/;
+ ($status, $is_clean, $starting_branch);
+}
+
sub usage
{
die <<EOT;
Usage: patch-update [OPTIONS]
--gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
---skip-check Skip the check that ensures starting with a clean master branch.
+--skip-check Skip the check that ensures starting with a clean branch.
EOT
}