Lines 10-26
use List::Util qw( first );
Link Here
|
10 |
use Getopt::Long; |
10 |
use Getopt::Long; |
11 |
use Pod::Usage; |
11 |
use Pod::Usage; |
12 |
use Try::Tiny; |
12 |
use Try::Tiny; |
|
|
13 |
use REST::Client; |
14 |
use JSON qw( decode_json ); |
13 |
$Term::ANSIColor::AUTOLOCAL = 1; |
15 |
$Term::ANSIColor::AUTOLOCAL = 1; |
14 |
|
16 |
|
15 |
my $git_dir = '.'; |
17 |
my $git_dir = '.'; |
16 |
my $target_branch = 'main'; |
18 |
my $target_branch = 'main'; |
17 |
my ( $new_branch, $nb_commits, $help ); |
19 |
my ( $new_branch, $nb_commits, $bug_number, $help ); |
18 |
|
20 |
|
19 |
GetOptions( |
21 |
GetOptions( |
20 |
'git-dir=s' => \$git_dir, |
22 |
'git-dir=s' => \$git_dir, |
21 |
'target-branch=s' => \$target_branch, |
23 |
'target-branch=s' => \$target_branch, |
22 |
'new-branch=s' => \$new_branch, |
24 |
'new-branch=s' => \$new_branch, |
23 |
'n=s' => \$nb_commits, |
25 |
'n=s' => \$nb_commits, |
|
|
26 |
'bugzilla=s' => \$bug_number, |
24 |
'help|?' => \$help, |
27 |
'help|?' => \$help, |
25 |
) or pod2usage(2); |
28 |
) or pod2usage(2); |
26 |
|
29 |
|
Lines 56-62
try {
Link Here
|
56 |
exit 2; |
59 |
exit 2; |
57 |
}; |
60 |
}; |
58 |
|
61 |
|
59 |
my ($source_branch) = $git->RUN( 'symbolic-ref', '--short', 'HEAD' ); |
62 |
my $source_branch; |
|
|
63 |
if ($bug_number) { |
64 |
$source_branch = "bug_$bug_number"; |
65 |
switch_branch($source_branch); |
66 |
} else { |
67 |
($source_branch) = $git->RUN( 'symbolic-ref', '--short', 'HEAD' ); |
68 |
} |
60 |
|
69 |
|
61 |
# Bug 38664 is "Tidy the whole codebase" |
70 |
# Bug 38664 is "Tidy the whole codebase" |
62 |
my @tidy_commits = grep { m{\|Bug 38664: } } $git->RUN( 'log', '--format=%h|%s', $target_branch ); |
71 |
my @tidy_commits = grep { m{\|Bug 38664: } } $git->RUN( 'log', '--format=%h|%s', $target_branch ); |
Lines 68-94
my ($tidy_commit) = split '\|', $tidy_commits[0];
Link Here
|
68 |
my ($commit_before_tidy) = split '\|', $tidy_commits[-1]; |
77 |
my ($commit_before_tidy) = split '\|', $tidy_commits[-1]; |
69 |
$commit_before_tidy .= '^1'; |
78 |
$commit_before_tidy .= '^1'; |
70 |
|
79 |
|
71 |
# Do not do anything if we have the tidy commits in the git log |
|
|
72 |
if ( $git->branch( $source_branch, '--contains', $tidy_commit ) ) { |
73 |
say GREEN "No need to rebase, your branch already contains the tidy commits!"; |
74 |
exit; |
75 |
} |
76 |
|
77 |
my $tmp_src_branch = "$source_branch-tmp"; |
80 |
my $tmp_src_branch = "$source_branch-tmp"; |
78 |
$new_branch ||= "$source_branch-rebased"; |
81 |
$new_branch ||= "$source_branch-rebased"; |
79 |
|
82 |
|
80 |
say BLUE "Creating a temporary branch '$tmp_src_branch'..."; |
83 |
say BLUE "Creating a temporary branch '$tmp_src_branch'..."; |
81 |
try { |
84 |
switch_branch($tmp_src_branch); |
82 |
$git->checkout( '-b', $tmp_src_branch ); |
85 |
|
83 |
} catch { |
86 |
if ($bug_number) { |
84 |
say MAGENTA $_->error; |
87 |
say BLUE sprintf "Guessing a date to use from bugzilla's bug %s", $bug_number; |
85 |
say RED sprintf "Cannot create and checkout branch '%s'.", $tmp_src_branch; |
88 |
my $client = REST::Client->new( |
86 |
if ( $_->error =~ m{already exists} ) { |
89 |
{ |
87 |
say RED "Delete it and try again."; |
90 |
host => 'https://bugs.koha-community.org/bugzilla3/rest', |
88 |
say sprintf "\t\$ git branch -D %s", $tmp_src_branch; |
91 |
} |
|
|
92 |
); |
93 |
|
94 |
$client->GET("/bug/$bug_number/attachment?include_fields=is_patch,is_obsolete,creation_time,summary"); |
95 |
my $response = decode_json( $client->responseContent ); |
96 |
|
97 |
my $time; |
98 |
foreach my $attachment ( @{ $response->{bugs}->{$bug_number} } ) { |
99 |
next if ( $attachment->{is_obsolete} ); |
100 |
next if ( !$attachment->{is_patch} ); |
101 |
|
102 |
$time = $attachment->{creation_time}; |
103 |
last; |
89 |
} |
104 |
} |
90 |
exit 2; |
105 |
|
91 |
}; |
106 |
unless ($time) { |
|
|
107 |
say RED sprintf "No non-obsolete patch found on bug %s", $bug_number; |
108 |
exit 2; |
109 |
} |
110 |
say GREEN sprintf "First patch from this bug was applied at %s", $time; |
111 |
|
112 |
my ($commit) = $git->rev_list( '-n', 1, '--before', $time, $target_branch ); |
113 |
unless ($commit) { |
114 |
say RED sprintf "No commit found before %s on '%s'", $time, $target_branch; |
115 |
exit 2; |
116 |
} |
117 |
|
118 |
say BLUE "Resetting HEAD to where origin/main was at $time (commit $commit)"; |
119 |
$git->reset( '--hard', $commit ); |
120 |
try { |
121 |
say BLUE "Applying patches using git bz"; |
122 |
$git->bz( 'apply', $bug_number, '--confirm' ); |
123 |
} catch { |
124 |
say MAGENTA $_->error; |
125 |
say RED "Cannot apply the patches cleanly"; |
126 |
say BLUE |
127 |
"You can continue git-bz operation without this script. Once all the patches are applied retry without --bugzilla."; |
128 |
exit 2; |
129 |
} |
130 |
} |
131 |
|
132 |
# Do not do anything if we have the tidy commits in the git log |
133 |
if ( $git->branch( $tmp_src_branch, '--contains', $tidy_commit ) ) { |
134 |
say GREEN "No need to rebase, your branch already contains the tidy commits!"; |
135 |
exit; |
136 |
} |
92 |
|
137 |
|
93 |
# Rebase the branch up to before the tidy work |
138 |
# Rebase the branch up to before the tidy work |
94 |
unless ( $git->branch( $source_branch, '--contains', $commit_before_tidy ) ) { |
139 |
unless ( $git->branch( $source_branch, '--contains', $commit_before_tidy ) ) { |
Lines 111-127
unless ( $git->branch( $source_branch, '--contains', $commit_before_tidy ) ) {
Link Here
|
111 |
|
156 |
|
112 |
# Create a new branch |
157 |
# Create a new branch |
113 |
say BLUE "Creating a new branch '$new_branch' starting at the end of the tidy commits..."; |
158 |
say BLUE "Creating a new branch '$new_branch' starting at the end of the tidy commits..."; |
114 |
try { |
159 |
switch_branch( $new_branch, $tidy_commit ); |
115 |
$git->checkout( '-b', $new_branch, $tidy_commit ); |
|
|
116 |
} catch { |
117 |
say MAGENTA $_->error; |
118 |
say RED sprintf "Cannot create and checkout branch '%s'.", $new_branch; |
119 |
if ( $_->error =~ m{already exists} ) { |
120 |
say RED "Delete it and try again."; |
121 |
say sprintf "\t\$ git branch -D %s", $new_branch; |
122 |
} |
123 |
exit 2; |
124 |
}; |
125 |
|
160 |
|
126 |
# Get the list of commits from the source branch |
161 |
# Get the list of commits from the source branch |
127 |
say BLUE "Getting commit list from branch '$tmp_src_branch'..."; |
162 |
say BLUE "Getting commit list from branch '$tmp_src_branch'..."; |
Lines 228-233
sub get_commit_info {
Link Here
|
228 |
return ( $author, $date, $message ); |
263 |
return ( $author, $date, $message ); |
229 |
} |
264 |
} |
230 |
|
265 |
|
|
|
266 |
sub switch_branch { |
267 |
my ( $branch, $commit ) = @_; |
268 |
try { |
269 |
$git->checkout( '-b', $branch, $commit || () ); |
270 |
} catch { |
271 |
say MAGENTA $_->error; |
272 |
say RED sprintf "Cannot create and checkout branch '%s'.", $branch; |
273 |
if ( $_->error =~ m{already exists} ) { |
274 |
say RED "Delete it and try again."; |
275 |
say sprintf "\t\$ git branch -D %s", $branch; |
276 |
} |
277 |
exit 2; |
278 |
}; |
279 |
} |
280 |
|
231 |
=head1 NAME |
281 |
=head1 NAME |
232 |
|
282 |
|
233 |
auto_rebase.pl - Automate rebasing and resolving conflicts during Git rebases. |
283 |
auto_rebase.pl - Automate rebasing and resolving conflicts during Git rebases. |
Lines 241-246
auto_rebase.pl [options]
Link Here
|
241 |
--target-branch Target branch to rebase onto (default: main) |
291 |
--target-branch Target branch to rebase onto (default: main) |
242 |
--new-branch The resulting branch (default: ${source-branch}-rebased) |
292 |
--new-branch The resulting branch (default: ${source-branch}-rebased) |
243 |
-n The number of commits to pick for rebase from the source branch |
293 |
-n The number of commits to pick for rebase from the source branch |
|
|
294 |
--bugzilla Pull patches from bugzilla |
244 |
--help Show this help message |
295 |
--help Show this help message |
245 |
|
296 |
|
246 |
=head1 DESCRIPTION |
297 |
=head1 DESCRIPTION |
Lines 253-263
The source branch is the branch that is currently checked out.
Link Here
|
253 |
|
304 |
|
254 |
=head1 EXAMPLES |
305 |
=head1 EXAMPLES |
255 |
|
306 |
|
256 |
First you need to retrieve this script from the main branch, do not place it under misc/devel/auto_rebase.pl or you will get an error (`The following untracked working tree files would be overwritten by checkout`). |
|
|
257 |
|
258 |
git show origin/main:misc/devel/auto_rebase.pl > auto_rebase.pl |
259 |
chmod +x auto_rebase.pl |
260 |
|
261 |
Rebase onto 'main' in the current repository: |
307 |
Rebase onto 'main' in the current repository: |
262 |
|
308 |
|
263 |
./auto_rebase.pl |
309 |
./auto_rebase.pl |
Lines 274-279
Rebase onto 'main' the last 42 commits of the current branch
Link Here
|
274 |
|
320 |
|
275 |
./auto_rebase.pl -n 42 |
321 |
./auto_rebase.pl -n 42 |
276 |
|
322 |
|
|
|
323 |
Rebase onto 'main' the patches from bugzilla's bug 42424 |
324 |
|
325 |
./auto_rebase.pl --bugzilla 42424 |
326 |
|
277 |
=head1 AUTHOR |
327 |
=head1 AUTHOR |
278 |
|
328 |
|
279 |
Jonathan Druart <jonathan.druart@bugs.koha-community.org> |
329 |
Jonathan Druart <jonathan.druart@bugs.koha-community.org> |
280 |
- |
|
|