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

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

Return to bug 39106