View | Details | Raw Unified | Return to bug 39106
Collapse All | Expand All

(-)a/misc/devel/auto_rebase.pl (-35 / +84 lines)
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
- 

Return to bug 39106