Annotation of embedaddon/rsync/packaging/branch-from-patch, revision 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>