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