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 ),
16 require 'packaging/git-status.pl';
17 check_git_state
($master_branch, !$skip_branch_check, 1);
20 open PIPE
, '-|', 'git branch -l' or die "Unable to fork: $!\n";
22 if (m
# patch/\Q$master_branch\E/(.*)#o) {
23 $local_branch{$1} = 1;
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;
39 die "File not found: $_\n";
41 die "Filename is not a .diff file: $_\n" unless /\.diff$/;
45 exit unless @patch_list;
47 my(%scanned, %created, %info);
49 foreach my $patch (@patch_list) {
50 my($where, $name) = $patch =~ m{^(.*?)([^/]+)\.diff$};
51 next if $scanned{$name}++;
53 open IN
, '<', $patch or die "Unable to open $patch: $!\n";
58 if (m
#^based-on: (\S+)#) {
62 last if m
#^index .*\.\..* \d#;
63 last if m
#^diff --git #;
64 last if m
#^--- (old|a)/#;
71 my $parent = $master_branch;
72 my @patches = $info =~ m
#patch -p1 <patches/(\S+)\.diff#g;
74 if ($patches[-1] eq $name) {
77 warn "No identity patch line in $patch\n";
80 $parent = pop @patches;
81 if (!$scanned{$parent}) {
82 unless (-f
"$where$parent.diff") {
83 die "Unknown parent of $patch: $parent\n";
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";
91 warn "No patch lines found in $patch\n";
94 $info{$name} = [ $parent, $info, $commit ];
97 foreach my $patch (@patch_list) {
98 create_branch
($patch);
101 system 'git', 'checkout', $master_branch and exit 1;
108 my($where, $name) = $patch =~ m{^(.*?)([^/]+)\.diff$};
110 return if $created{$name}++;
112 my $ref = $info{$name};
113 my($parent, $info, $commit) = @
$ref;
116 if ($parent eq $master_branch) {
117 $parent_branch = $master_branch;
118 $parent_branch = $commit if defined $commit;
120 create_branch
("$where/$parent.diff");
121 $parent_branch = "patch/$master_branch/$parent";
124 my $branch = "patch/$master_branch/$name";
125 print "\n", '=' x
64, "\nProcessing $branch ($parent_branch)\n";
127 if ($local_branch{$name}) {
128 system 'git', 'branch', '-D', $branch and exit 1;
131 system 'git', 'checkout', '-b', $branch, $parent_branch and exit 1;
133 open OUT
, '>', "PATCH.$name" or die $!;
136 system 'git', 'add', "PATCH.$name" and exit 1;
138 open IN
, '<', $patch or die "Unable to open $patch: $!\n";
142 open PIPE
, '|-', 'patch -p1' or die $!;
146 system 'rm -f *.orig */*.orig';
148 while (m
#\nnew file mode (\d+)\s+--- /dev/null\s+\Q+++\E b/(.*)#g) {
150 system 'git', 'add', $2;
155 print 'Press Enter to commit, Ctrl-C to abort, or type a wild-name to add a new file: ';
162 while (system 'git', 'commit', '-a', '-m', "Creating branch from $name.diff.") {
163 exit 1 if system '/bin/zsh';
170 Usage branch-from-patch [OPTIONS] patches/DIFF...
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.