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>