|
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 |
- |
|
|