Annotation of embedaddon/rsync/packaging/branch-from-patch, revision 1.1.1.1

1.1       misho       1: #!/usr/bin/perl
                      2: 
                      3: use strict;
                      4: use warnings;
                      5: use Getopt::Long;
                      6: 
                      7: &Getopt::Long::Configure('bundling');
                      8: &usage if !&GetOptions(
                      9:     'branch|b=s' => \( my $master_branch = 'master' ),
                     10:     'skip-check' => \( my $skip_branch_check ),
                     11:     'delete' => \( my $delete_local_branches ),
                     12:     'help|h' => \( my $help_opt ),
                     13: );
                     14: &usage if $help_opt;
                     15: 
                     16: require 'packaging/git-status.pl';
                     17: check_git_state($master_branch, !$skip_branch_check, 1);
                     18: 
                     19: my %local_branch;
                     20: open PIPE, '-|', 'git branch -l' or die "Unable to fork: $!\n";
                     21: while (<PIPE>) {
                     22:     if (m# patch/\Q$master_branch\E/(.*)#o) {
                     23:        $local_branch{$1} = 1;
                     24:     }
                     25: }
                     26: close PIPE;
                     27: 
                     28: if ($delete_local_branches) {
                     29:     foreach my $name (sort keys %local_branch) {
                     30:        my $branch = "patch/$master_branch/$name";
                     31:        system 'git', 'branch', '-D', $branch and exit 1;
                     32:     }
                     33:     %local_branch = ( );
                     34: }
                     35: 
                     36: my @patch_list;
                     37: foreach (@ARGV) {
                     38:     if (!-f $_) {
                     39:        die "File not found: $_\n";
                     40:     }
                     41:     die "Filename is not a .diff file: $_\n" unless /\.diff$/;
                     42:     push @patch_list, $_;
                     43: }
                     44: 
                     45: exit unless @patch_list;
                     46: 
                     47: my(%scanned, %created, %info);
                     48: 
                     49: foreach my $patch (@patch_list) {
                     50:     my($where, $name) = $patch =~ m{^(.*?)([^/]+)\.diff$};
                     51:     next if $scanned{$name}++;
                     52: 
                     53:     open IN, '<', $patch or die "Unable to open $patch: $!\n";
                     54: 
                     55:     my $info = '';
                     56:     my $commit;
                     57:     while (<IN>) {
                     58:        if (m#^based-on: (\S+)#) {
                     59:            $commit = $1;
                     60:            last;
                     61:        }
                     62:        last if m#^index .*\.\..* \d#;
                     63:        last if m#^diff --git #;
                     64:        last if m#^--- (old|a)/#;
                     65:        $info .= $_;
                     66:     }
                     67:     close IN;
                     68: 
                     69:     $info =~ s/\s+\Z/\n/;
                     70: 
                     71:     my $parent = $master_branch;
                     72:     my @patches = $info =~ m#patch -p1 <patches/(\S+)\.diff#g;
                     73:     if (@patches) {
                     74:        if ($patches[-1] eq $name) {
                     75:            pop @patches;
                     76:        } else {
                     77:            warn "No identity patch line in $patch\n";
                     78:        }
                     79:        if (@patches) {
                     80:            $parent = pop @patches;
                     81:            if (!$scanned{$parent}) {
                     82:                unless (-f "$where$parent.diff") {
                     83:                    die "Unknown parent of $patch: $parent\n";
                     84:                }
                     85:                # Add parent to @patch_list so that we will look for the
                     86:                # parent's parent.  Any duplicates will just be ignored.
                     87:                push @patch_list, "$where$parent.diff";
                     88:            }
                     89:        }
                     90:     } else {
                     91:        warn "No patch lines found in $patch\n";
                     92:     }
                     93: 
                     94:     $info{$name} = [ $parent, $info, $commit ];
                     95: }
                     96: 
                     97: foreach my $patch (@patch_list) {
                     98:     create_branch($patch);
                     99: }
                    100: 
                    101: system 'git', 'checkout', $master_branch and exit 1;
                    102: 
                    103: exit;
                    104: 
                    105: sub create_branch
                    106: {
                    107:     my($patch) = @_;
                    108:     my($where, $name) = $patch =~ m{^(.*?)([^/]+)\.diff$};
                    109: 
                    110:     return if $created{$name}++;
                    111: 
                    112:     my $ref = $info{$name};
                    113:     my($parent, $info, $commit) = @$ref;
                    114: 
                    115:     my $parent_branch;
                    116:     if ($parent eq $master_branch) {
                    117:        $parent_branch = $master_branch;
                    118:        $parent_branch = $commit if defined $commit;
                    119:     } else {
                    120:        create_branch("$where/$parent.diff");
                    121:        $parent_branch = "patch/$master_branch/$parent";
                    122:     }
                    123: 
                    124:     my $branch = "patch/$master_branch/$name";
                    125:     print "\n", '=' x 64, "\nProcessing $branch ($parent_branch)\n";
                    126: 
                    127:     if ($local_branch{$name}) {
                    128:        system 'git', 'branch', '-D', $branch and exit 1;
                    129:     }
                    130: 
                    131:     system 'git', 'checkout', '-b', $branch, $parent_branch and exit 1;
                    132: 
                    133:     open OUT, '>', "PATCH.$name" or die $!;
                    134:     print OUT $info;
                    135:     close OUT;
                    136:     system 'git', 'add', "PATCH.$name" and exit 1;
                    137: 
                    138:     open IN, '<', $patch or die "Unable to open $patch: $!\n";
                    139:     $_ = join('', <IN>);
                    140:     close IN;
                    141: 
                    142:     open PIPE, '|-', 'patch -p1' or die $!;
                    143:     print PIPE $_;
                    144:     close PIPE;
                    145: 
                    146:     system 'rm -f *.orig */*.orig';
                    147: 
                    148:     while (m#\nnew file mode (\d+)\s+--- /dev/null\s+\Q+++\E b/(.*)#g) {
                    149:        chmod oct($1), $2;
                    150:        system 'git', 'add', $2;
                    151:     }
                    152: 
                    153:     while (1) {
                    154:        system 'git status';
                    155:        print 'Press Enter to commit, Ctrl-C to abort, or type a wild-name to add a new file: ';
                    156:        $_ = <STDIN>;
                    157:        last if /^$/;
                    158:        chomp;
                    159:        system "git add $_";
                    160:     }
                    161: 
                    162:     while (system 'git', 'commit', '-a', '-m', "Creating branch from $name.diff.") {
                    163:        exit 1 if system '/bin/zsh';
                    164:     }
                    165: }
                    166: 
                    167: sub usage
                    168: {
                    169:     die <<EOT;
                    170: Usage branch-from-patch [OPTIONS] patches/DIFF...
                    171: 
                    172: Options:
                    173: -b, --branch=BRANCH  Create branches relative to BRANCH if no "based-on"
                    174:                      header was found in the patch file.
                    175:     --skip-check     Skip the check that ensures starting with a clean branch.
                    176:     --delete         Delete all the local patch/BASE/* branches, not just the ones
                    177:                      that are being recreated.
                    178: -h, --help           Output this help message.
                    179: EOT
                    180: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>