Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 1 | /* |
| 2 | * "git rebase" builtin command |
| 3 | * |
| 4 | * Copyright (c) 2018 Pratik Karki |
| 5 | */ |
| 6 | |
| 7 | #include "builtin.h" |
| 8 | #include "run-command.h" |
| 9 | #include "exec-cmd.h" |
| 10 | #include "argv-array.h" |
| 11 | #include "dir.h" |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 12 | #include "packfile.h" |
| 13 | #include "refs.h" |
| 14 | #include "quote.h" |
| 15 | #include "config.h" |
| 16 | #include "cache-tree.h" |
| 17 | #include "unpack-trees.h" |
| 18 | #include "lockfile.h" |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 19 | #include "parse-options.h" |
Pratik Karki | 075bc85 | 2018-09-04 14:27:09 -0700 | [diff] [blame] | 20 | #include "commit.h" |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 21 | #include "diff.h" |
Pratik Karki | e0333e5 | 2018-09-04 14:27:14 -0700 | [diff] [blame] | 22 | #include "wt-status.h" |
Pratik Karki | 9a48a61 | 2018-09-04 14:27:16 -0700 | [diff] [blame] | 23 | #include "revision.h" |
Pratik Karki | 122420c | 2018-08-08 20:51:17 +0545 | [diff] [blame] | 24 | #include "rerere.h" |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 25 | |
| 26 | static char const * const builtin_rebase_usage[] = { |
| 27 | N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] " |
| 28 | "[<upstream>] [<branch>]"), |
| 29 | N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] " |
| 30 | "--root [<branch>]"), |
| 31 | N_("git rebase --continue | --abort | --skip | --edit-todo"), |
| 32 | NULL |
| 33 | }; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 34 | |
| 35 | static GIT_PATH_FUNC(apply_dir, "rebase-apply") |
| 36 | static GIT_PATH_FUNC(merge_dir, "rebase-merge") |
| 37 | |
| 38 | enum rebase_type { |
| 39 | REBASE_UNSPECIFIED = -1, |
| 40 | REBASE_AM, |
| 41 | REBASE_MERGE, |
| 42 | REBASE_INTERACTIVE, |
| 43 | REBASE_PRESERVE_MERGES |
| 44 | }; |
Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 45 | |
| 46 | static int use_builtin_rebase(void) |
| 47 | { |
| 48 | struct child_process cp = CHILD_PROCESS_INIT; |
| 49 | struct strbuf out = STRBUF_INIT; |
| 50 | int ret; |
| 51 | |
| 52 | argv_array_pushl(&cp.args, |
| 53 | "config", "--bool", "rebase.usebuiltin", NULL); |
| 54 | cp.git_cmd = 1; |
| 55 | if (capture_command(&cp, &out, 6)) { |
| 56 | strbuf_release(&out); |
Pratik Karki | 5541bd5 | 2018-08-08 21:38:02 +0545 | [diff] [blame^] | 57 | return 1; |
Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | strbuf_trim(&out); |
| 61 | ret = !strcmp("true", out.buf); |
| 62 | strbuf_release(&out); |
| 63 | return ret; |
| 64 | } |
| 65 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 66 | struct rebase_options { |
| 67 | enum rebase_type type; |
| 68 | const char *state_dir; |
| 69 | struct commit *upstream; |
| 70 | const char *upstream_name; |
Pratik Karki | 06e4775 | 2018-09-04 14:27:10 -0700 | [diff] [blame] | 71 | const char *upstream_arg; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 72 | char *head_name; |
| 73 | struct object_id orig_head; |
| 74 | struct commit *onto; |
| 75 | const char *onto_name; |
| 76 | const char *revisions; |
Pratik Karki | e65123a | 2018-09-04 14:27:21 -0700 | [diff] [blame] | 77 | const char *switch_to; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 78 | int root; |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 79 | struct object_id *squash_onto; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 80 | struct commit *restrict_revision; |
| 81 | int dont_finish_rebase; |
Pratik Karki | b4c8eb0 | 2018-09-04 14:27:12 -0700 | [diff] [blame] | 82 | enum { |
| 83 | REBASE_NO_QUIET = 1<<0, |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 84 | REBASE_VERBOSE = 1<<1, |
| 85 | REBASE_DIFFSTAT = 1<<2, |
Pratik Karki | 1ed9c14 | 2018-09-04 14:27:17 -0700 | [diff] [blame] | 86 | REBASE_FORCE = 1<<3, |
Pratik Karki | c54dacb | 2018-09-04 14:27:18 -0700 | [diff] [blame] | 87 | REBASE_INTERACTIVE_EXPLICIT = 1<<4, |
Pratik Karki | b4c8eb0 | 2018-09-04 14:27:12 -0700 | [diff] [blame] | 88 | } flags; |
| 89 | struct strbuf git_am_opt; |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 90 | const char *action; |
Pratik Karki | 73d51ed | 2018-09-04 14:59:50 -0700 | [diff] [blame] | 91 | int signoff; |
Pratik Karki | ead98c1 | 2018-09-04 14:59:52 -0700 | [diff] [blame] | 92 | int allow_rerere_autoupdate; |
Pratik Karki | 002ee2f | 2018-09-04 14:59:57 -0700 | [diff] [blame] | 93 | int keep_empty; |
Pratik Karki | 051910a | 2018-09-04 14:59:58 -0700 | [diff] [blame] | 94 | int autosquash; |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 95 | char *gpg_sign_opt; |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 96 | int autostash; |
Pratik Karki | 68e46d7 | 2018-09-04 15:00:04 -0700 | [diff] [blame] | 97 | char *cmd; |
Pratik Karki | 9b3a448 | 2018-09-04 15:00:05 -0700 | [diff] [blame] | 98 | int allow_empty_message; |
Pratik Karki | 3c3588c | 2018-09-04 15:00:07 -0700 | [diff] [blame] | 99 | int rebase_merges, rebase_cousins; |
Pratik Karki | ba1905a | 2018-09-04 15:00:11 -0700 | [diff] [blame] | 100 | char *strategy, *strategy_opts; |
Pratik Karki | cda614e | 2018-08-08 21:21:33 +0545 | [diff] [blame] | 101 | struct strbuf git_format_patch_opt; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 102 | }; |
| 103 | |
Pratik Karki | 9a48a61 | 2018-09-04 14:27:16 -0700 | [diff] [blame] | 104 | static int is_interactive(struct rebase_options *opts) |
| 105 | { |
| 106 | return opts->type == REBASE_INTERACTIVE || |
| 107 | opts->type == REBASE_PRESERVE_MERGES; |
| 108 | } |
| 109 | |
Pratik Karki | 002ee2f | 2018-09-04 14:59:57 -0700 | [diff] [blame] | 110 | static void imply_interactive(struct rebase_options *opts, const char *option) |
| 111 | { |
| 112 | switch (opts->type) { |
| 113 | case REBASE_AM: |
| 114 | die(_("%s requires an interactive rebase"), option); |
| 115 | break; |
| 116 | case REBASE_INTERACTIVE: |
| 117 | case REBASE_PRESERVE_MERGES: |
| 118 | break; |
| 119 | case REBASE_MERGE: |
| 120 | /* we silently *upgrade* --merge to --interactive if needed */ |
| 121 | default: |
| 122 | opts->type = REBASE_INTERACTIVE; /* implied */ |
| 123 | break; |
| 124 | } |
| 125 | } |
| 126 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 127 | /* Returns the filename prefixed by the state_dir */ |
| 128 | static const char *state_dir_path(const char *filename, struct rebase_options *opts) |
| 129 | { |
| 130 | static struct strbuf path = STRBUF_INIT; |
| 131 | static size_t prefix_len; |
| 132 | |
| 133 | if (!prefix_len) { |
| 134 | strbuf_addf(&path, "%s/", opts->state_dir); |
| 135 | prefix_len = path.len; |
| 136 | } |
| 137 | |
| 138 | strbuf_setlen(&path, prefix_len); |
| 139 | strbuf_addstr(&path, filename); |
| 140 | return path.buf; |
| 141 | } |
| 142 | |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 143 | /* Read one file, then strip line endings */ |
| 144 | static int read_one(const char *path, struct strbuf *buf) |
| 145 | { |
| 146 | if (strbuf_read_file(buf, path, 0) < 0) |
| 147 | return error_errno(_("could not read '%s'"), path); |
| 148 | strbuf_trim_trailing_newline(buf); |
| 149 | return 0; |
| 150 | } |
| 151 | |
| 152 | /* Initialize the rebase options from the state directory. */ |
| 153 | static int read_basic_state(struct rebase_options *opts) |
| 154 | { |
| 155 | struct strbuf head_name = STRBUF_INIT; |
| 156 | struct strbuf buf = STRBUF_INIT; |
| 157 | struct object_id oid; |
| 158 | |
| 159 | if (read_one(state_dir_path("head-name", opts), &head_name) || |
| 160 | read_one(state_dir_path("onto", opts), &buf)) |
| 161 | return -1; |
| 162 | opts->head_name = starts_with(head_name.buf, "refs/") ? |
| 163 | xstrdup(head_name.buf) : NULL; |
| 164 | strbuf_release(&head_name); |
| 165 | if (get_oid(buf.buf, &oid)) |
| 166 | return error(_("could not get 'onto': '%s'"), buf.buf); |
| 167 | opts->onto = lookup_commit_or_die(&oid, buf.buf); |
| 168 | |
| 169 | /* |
| 170 | * We always write to orig-head, but interactive rebase used to write to |
| 171 | * head. Fall back to reading from head to cover for the case that the |
| 172 | * user upgraded git with an ongoing interactive rebase. |
| 173 | */ |
| 174 | strbuf_reset(&buf); |
| 175 | if (file_exists(state_dir_path("orig-head", opts))) { |
| 176 | if (read_one(state_dir_path("orig-head", opts), &buf)) |
| 177 | return -1; |
| 178 | } else if (read_one(state_dir_path("head", opts), &buf)) |
| 179 | return -1; |
| 180 | if (get_oid(buf.buf, &opts->orig_head)) |
| 181 | return error(_("invalid orig-head: '%s'"), buf.buf); |
| 182 | |
| 183 | strbuf_reset(&buf); |
| 184 | if (read_one(state_dir_path("quiet", opts), &buf)) |
| 185 | return -1; |
| 186 | if (buf.len) |
| 187 | opts->flags &= ~REBASE_NO_QUIET; |
| 188 | else |
| 189 | opts->flags |= REBASE_NO_QUIET; |
| 190 | |
| 191 | if (file_exists(state_dir_path("verbose", opts))) |
| 192 | opts->flags |= REBASE_VERBOSE; |
| 193 | |
Pratik Karki | 73d51ed | 2018-09-04 14:59:50 -0700 | [diff] [blame] | 194 | if (file_exists(state_dir_path("signoff", opts))) { |
| 195 | opts->signoff = 1; |
| 196 | opts->flags |= REBASE_FORCE; |
| 197 | } |
| 198 | |
Pratik Karki | ead98c1 | 2018-09-04 14:59:52 -0700 | [diff] [blame] | 199 | if (file_exists(state_dir_path("allow_rerere_autoupdate", opts))) { |
| 200 | strbuf_reset(&buf); |
| 201 | if (read_one(state_dir_path("allow_rerere_autoupdate", opts), |
| 202 | &buf)) |
| 203 | return -1; |
| 204 | if (!strcmp(buf.buf, "--rerere-autoupdate")) |
| 205 | opts->allow_rerere_autoupdate = 1; |
| 206 | else if (!strcmp(buf.buf, "--no-rerere-autoupdate")) |
| 207 | opts->allow_rerere_autoupdate = 0; |
| 208 | else |
| 209 | warning(_("ignoring invalid allow_rerere_autoupdate: " |
| 210 | "'%s'"), buf.buf); |
| 211 | } else |
| 212 | opts->allow_rerere_autoupdate = -1; |
| 213 | |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 214 | if (file_exists(state_dir_path("gpg_sign_opt", opts))) { |
| 215 | strbuf_reset(&buf); |
| 216 | if (read_one(state_dir_path("gpg_sign_opt", opts), |
| 217 | &buf)) |
| 218 | return -1; |
| 219 | free(opts->gpg_sign_opt); |
| 220 | opts->gpg_sign_opt = xstrdup(buf.buf); |
| 221 | } |
| 222 | |
Pratik Karki | ba1905a | 2018-09-04 15:00:11 -0700 | [diff] [blame] | 223 | if (file_exists(state_dir_path("strategy", opts))) { |
| 224 | strbuf_reset(&buf); |
| 225 | if (read_one(state_dir_path("strategy", opts), &buf)) |
| 226 | return -1; |
| 227 | free(opts->strategy); |
| 228 | opts->strategy = xstrdup(buf.buf); |
| 229 | } |
| 230 | |
| 231 | if (file_exists(state_dir_path("strategy_opts", opts))) { |
| 232 | strbuf_reset(&buf); |
| 233 | if (read_one(state_dir_path("strategy_opts", opts), &buf)) |
| 234 | return -1; |
| 235 | free(opts->strategy_opts); |
| 236 | opts->strategy_opts = xstrdup(buf.buf); |
| 237 | } |
| 238 | |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 239 | strbuf_release(&buf); |
| 240 | |
| 241 | return 0; |
| 242 | } |
| 243 | |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 244 | static int apply_autostash(struct rebase_options *opts) |
| 245 | { |
| 246 | const char *path = state_dir_path("autostash", opts); |
| 247 | struct strbuf autostash = STRBUF_INIT; |
| 248 | struct child_process stash_apply = CHILD_PROCESS_INIT; |
| 249 | |
| 250 | if (!file_exists(path)) |
| 251 | return 0; |
| 252 | |
| 253 | if (read_one(state_dir_path("autostash", opts), &autostash)) |
| 254 | return error(_("Could not read '%s'"), path); |
| 255 | argv_array_pushl(&stash_apply.args, |
| 256 | "stash", "apply", autostash.buf, NULL); |
| 257 | stash_apply.git_cmd = 1; |
| 258 | stash_apply.no_stderr = stash_apply.no_stdout = |
| 259 | stash_apply.no_stdin = 1; |
| 260 | if (!run_command(&stash_apply)) |
| 261 | printf(_("Applied autostash.\n")); |
| 262 | else { |
| 263 | struct argv_array args = ARGV_ARRAY_INIT; |
| 264 | int res = 0; |
| 265 | |
| 266 | argv_array_pushl(&args, |
| 267 | "stash", "store", "-m", "autostash", "-q", |
| 268 | autostash.buf, NULL); |
| 269 | if (run_command_v_opt(args.argv, RUN_GIT_CMD)) |
| 270 | res = error(_("Cannot store %s"), autostash.buf); |
| 271 | argv_array_clear(&args); |
| 272 | strbuf_release(&autostash); |
| 273 | if (res) |
| 274 | return res; |
| 275 | |
| 276 | fprintf(stderr, |
| 277 | _("Applying autostash resulted in conflicts.\n" |
| 278 | "Your changes are safe in the stash.\n" |
| 279 | "You can run \"git stash pop\" or \"git stash drop\" " |
| 280 | "at any time.\n")); |
| 281 | } |
| 282 | |
| 283 | strbuf_release(&autostash); |
| 284 | return 0; |
| 285 | } |
| 286 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 287 | static int finish_rebase(struct rebase_options *opts) |
| 288 | { |
| 289 | struct strbuf dir = STRBUF_INIT; |
| 290 | const char *argv_gc_auto[] = { "gc", "--auto", NULL }; |
| 291 | |
| 292 | delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF); |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 293 | apply_autostash(opts); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 294 | close_all_packs(the_repository->objects); |
| 295 | /* |
| 296 | * We ignore errors in 'gc --auto', since the |
| 297 | * user should see them. |
| 298 | */ |
| 299 | run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); |
| 300 | strbuf_addstr(&dir, opts->state_dir); |
| 301 | remove_dir_recursively(&dir, 0); |
| 302 | strbuf_release(&dir); |
| 303 | |
| 304 | return 0; |
| 305 | } |
| 306 | |
| 307 | static struct commit *peel_committish(const char *name) |
| 308 | { |
| 309 | struct object *obj; |
| 310 | struct object_id oid; |
| 311 | |
| 312 | if (get_oid(name, &oid)) |
| 313 | return NULL; |
| 314 | obj = parse_object(the_repository, &oid); |
| 315 | return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT); |
| 316 | } |
| 317 | |
| 318 | static void add_var(struct strbuf *buf, const char *name, const char *value) |
| 319 | { |
| 320 | if (!value) |
| 321 | strbuf_addf(buf, "unset %s; ", name); |
| 322 | else { |
| 323 | strbuf_addf(buf, "%s=", name); |
| 324 | sq_quote_buf(buf, value); |
| 325 | strbuf_addstr(buf, "; "); |
| 326 | } |
| 327 | } |
| 328 | |
Johannes Schindelin | bc24382 | 2018-10-05 08:54:38 -0700 | [diff] [blame] | 329 | static const char *resolvemsg = |
| 330 | N_("Resolve all conflicts manually, mark them as resolved with\n" |
| 331 | "\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n" |
| 332 | "You can instead skip this commit: run \"git rebase --skip\".\n" |
| 333 | "To abort and get back to the state before \"git rebase\", run " |
| 334 | "\"git rebase --abort\"."); |
| 335 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 336 | static int run_specific_rebase(struct rebase_options *opts) |
| 337 | { |
| 338 | const char *argv[] = { NULL, NULL }; |
| 339 | struct strbuf script_snippet = STRBUF_INIT; |
| 340 | int status; |
| 341 | const char *backend, *backend_func; |
| 342 | |
Johannes Schindelin | bc24382 | 2018-10-05 08:54:38 -0700 | [diff] [blame] | 343 | if (opts->type == REBASE_INTERACTIVE) { |
| 344 | /* Run builtin interactive rebase */ |
| 345 | struct child_process child = CHILD_PROCESS_INIT; |
| 346 | |
| 347 | argv_array_pushf(&child.env_array, "GIT_CHERRY_PICK_HELP=%s", |
| 348 | resolvemsg); |
| 349 | if (!(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) { |
| 350 | argv_array_push(&child.env_array, "GIT_EDITOR=:"); |
| 351 | opts->autosquash = 0; |
| 352 | } |
| 353 | |
| 354 | child.git_cmd = 1; |
| 355 | argv_array_push(&child.args, "rebase--interactive"); |
| 356 | |
| 357 | if (opts->action) |
| 358 | argv_array_pushf(&child.args, "--%s", opts->action); |
| 359 | if (opts->keep_empty) |
| 360 | argv_array_push(&child.args, "--keep-empty"); |
| 361 | if (opts->rebase_merges) |
| 362 | argv_array_push(&child.args, "--rebase-merges"); |
| 363 | if (opts->rebase_cousins) |
| 364 | argv_array_push(&child.args, "--rebase-cousins"); |
| 365 | if (opts->autosquash) |
| 366 | argv_array_push(&child.args, "--autosquash"); |
| 367 | if (opts->flags & REBASE_VERBOSE) |
| 368 | argv_array_push(&child.args, "--verbose"); |
| 369 | if (opts->flags & REBASE_FORCE) |
| 370 | argv_array_push(&child.args, "--no-ff"); |
| 371 | if (opts->restrict_revision) |
| 372 | argv_array_pushf(&child.args, |
| 373 | "--restrict-revision=^%s", |
| 374 | oid_to_hex(&opts->restrict_revision->object.oid)); |
| 375 | if (opts->upstream) |
| 376 | argv_array_pushf(&child.args, "--upstream=%s", |
| 377 | oid_to_hex(&opts->upstream->object.oid)); |
| 378 | if (opts->onto) |
| 379 | argv_array_pushf(&child.args, "--onto=%s", |
| 380 | oid_to_hex(&opts->onto->object.oid)); |
| 381 | if (opts->squash_onto) |
| 382 | argv_array_pushf(&child.args, "--squash-onto=%s", |
| 383 | oid_to_hex(opts->squash_onto)); |
| 384 | if (opts->onto_name) |
| 385 | argv_array_pushf(&child.args, "--onto-name=%s", |
| 386 | opts->onto_name); |
| 387 | argv_array_pushf(&child.args, "--head-name=%s", |
| 388 | opts->head_name ? |
| 389 | opts->head_name : "detached HEAD"); |
| 390 | if (opts->strategy) |
| 391 | argv_array_pushf(&child.args, "--strategy=%s", |
| 392 | opts->strategy); |
| 393 | if (opts->strategy_opts) |
| 394 | argv_array_pushf(&child.args, "--strategy-opts=%s", |
| 395 | opts->strategy_opts); |
| 396 | if (opts->switch_to) |
| 397 | argv_array_pushf(&child.args, "--switch-to=%s", |
| 398 | opts->switch_to); |
| 399 | if (opts->cmd) |
| 400 | argv_array_pushf(&child.args, "--cmd=%s", opts->cmd); |
| 401 | if (opts->allow_empty_message) |
| 402 | argv_array_push(&child.args, "--allow-empty-message"); |
| 403 | if (opts->allow_rerere_autoupdate > 0) |
| 404 | argv_array_push(&child.args, "--rerere-autoupdate"); |
| 405 | else if (opts->allow_rerere_autoupdate == 0) |
| 406 | argv_array_push(&child.args, "--no-rerere-autoupdate"); |
| 407 | if (opts->gpg_sign_opt) |
| 408 | argv_array_push(&child.args, opts->gpg_sign_opt); |
| 409 | if (opts->signoff) |
| 410 | argv_array_push(&child.args, "--signoff"); |
| 411 | |
| 412 | status = run_command(&child); |
| 413 | goto finished_rebase; |
| 414 | } |
| 415 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 416 | add_var(&script_snippet, "GIT_DIR", absolute_path(get_git_dir())); |
| 417 | add_var(&script_snippet, "state_dir", opts->state_dir); |
| 418 | |
| 419 | add_var(&script_snippet, "upstream_name", opts->upstream_name); |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 420 | add_var(&script_snippet, "upstream", opts->upstream ? |
| 421 | oid_to_hex(&opts->upstream->object.oid) : NULL); |
Pratik Karki | d4c569f | 2018-09-04 14:27:20 -0700 | [diff] [blame] | 422 | add_var(&script_snippet, "head_name", |
| 423 | opts->head_name ? opts->head_name : "detached HEAD"); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 424 | add_var(&script_snippet, "orig_head", oid_to_hex(&opts->orig_head)); |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 425 | add_var(&script_snippet, "onto", opts->onto ? |
| 426 | oid_to_hex(&opts->onto->object.oid) : NULL); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 427 | add_var(&script_snippet, "onto_name", opts->onto_name); |
| 428 | add_var(&script_snippet, "revisions", opts->revisions); |
| 429 | add_var(&script_snippet, "restrict_revision", opts->restrict_revision ? |
| 430 | oid_to_hex(&opts->restrict_revision->object.oid) : NULL); |
Pratik Karki | b4c8eb0 | 2018-09-04 14:27:12 -0700 | [diff] [blame] | 431 | add_var(&script_snippet, "GIT_QUIET", |
| 432 | opts->flags & REBASE_NO_QUIET ? "" : "t"); |
| 433 | add_var(&script_snippet, "git_am_opt", opts->git_am_opt.buf); |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 434 | add_var(&script_snippet, "verbose", |
| 435 | opts->flags & REBASE_VERBOSE ? "t" : ""); |
| 436 | add_var(&script_snippet, "diffstat", |
| 437 | opts->flags & REBASE_DIFFSTAT ? "t" : ""); |
Pratik Karki | 1ed9c14 | 2018-09-04 14:27:17 -0700 | [diff] [blame] | 438 | add_var(&script_snippet, "force_rebase", |
| 439 | opts->flags & REBASE_FORCE ? "t" : ""); |
Pratik Karki | e65123a | 2018-09-04 14:27:21 -0700 | [diff] [blame] | 440 | if (opts->switch_to) |
| 441 | add_var(&script_snippet, "switch_to", opts->switch_to); |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 442 | add_var(&script_snippet, "action", opts->action ? opts->action : ""); |
Pratik Karki | 73d51ed | 2018-09-04 14:59:50 -0700 | [diff] [blame] | 443 | add_var(&script_snippet, "signoff", opts->signoff ? "--signoff" : ""); |
Pratik Karki | ead98c1 | 2018-09-04 14:59:52 -0700 | [diff] [blame] | 444 | add_var(&script_snippet, "allow_rerere_autoupdate", |
| 445 | opts->allow_rerere_autoupdate < 0 ? "" : |
| 446 | opts->allow_rerere_autoupdate ? |
| 447 | "--rerere-autoupdate" : "--no-rerere-autoupdate"); |
Pratik Karki | 002ee2f | 2018-09-04 14:59:57 -0700 | [diff] [blame] | 448 | add_var(&script_snippet, "keep_empty", opts->keep_empty ? "yes" : ""); |
Pratik Karki | 051910a | 2018-09-04 14:59:58 -0700 | [diff] [blame] | 449 | add_var(&script_snippet, "autosquash", opts->autosquash ? "t" : ""); |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 450 | add_var(&script_snippet, "gpg_sign_opt", opts->gpg_sign_opt); |
Pratik Karki | 68e46d7 | 2018-09-04 15:00:04 -0700 | [diff] [blame] | 451 | add_var(&script_snippet, "cmd", opts->cmd); |
Pratik Karki | 9b3a448 | 2018-09-04 15:00:05 -0700 | [diff] [blame] | 452 | add_var(&script_snippet, "allow_empty_message", |
| 453 | opts->allow_empty_message ? "--allow-empty-message" : ""); |
Pratik Karki | 3c3588c | 2018-09-04 15:00:07 -0700 | [diff] [blame] | 454 | add_var(&script_snippet, "rebase_merges", |
| 455 | opts->rebase_merges ? "t" : ""); |
| 456 | add_var(&script_snippet, "rebase_cousins", |
| 457 | opts->rebase_cousins ? "t" : ""); |
Pratik Karki | ba1905a | 2018-09-04 15:00:11 -0700 | [diff] [blame] | 458 | add_var(&script_snippet, "strategy", opts->strategy); |
| 459 | add_var(&script_snippet, "strategy_opts", opts->strategy_opts); |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 460 | add_var(&script_snippet, "rebase_root", opts->root ? "t" : ""); |
| 461 | add_var(&script_snippet, "squash_onto", |
| 462 | opts->squash_onto ? oid_to_hex(opts->squash_onto) : ""); |
Pratik Karki | cda614e | 2018-08-08 21:21:33 +0545 | [diff] [blame] | 463 | add_var(&script_snippet, "git_format_patch_opt", |
| 464 | opts->git_format_patch_opt.buf); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 465 | |
Pratik Karki | 3dba9d0 | 2018-08-08 21:21:34 +0545 | [diff] [blame] | 466 | if (is_interactive(opts) && |
| 467 | !(opts->flags & REBASE_INTERACTIVE_EXPLICIT)) { |
| 468 | strbuf_addstr(&script_snippet, |
| 469 | "GIT_EDITOR=:; export GIT_EDITOR; "); |
| 470 | opts->autosquash = 0; |
| 471 | } |
| 472 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 473 | switch (opts->type) { |
| 474 | case REBASE_AM: |
| 475 | backend = "git-rebase--am"; |
| 476 | backend_func = "git_rebase__am"; |
| 477 | break; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 478 | case REBASE_MERGE: |
| 479 | backend = "git-rebase--merge"; |
| 480 | backend_func = "git_rebase__merge"; |
| 481 | break; |
| 482 | case REBASE_PRESERVE_MERGES: |
| 483 | backend = "git-rebase--preserve-merges"; |
| 484 | backend_func = "git_rebase__preserve_merges"; |
| 485 | break; |
| 486 | default: |
| 487 | BUG("Unhandled rebase type %d", opts->type); |
| 488 | break; |
| 489 | } |
| 490 | |
| 491 | strbuf_addf(&script_snippet, |
| 492 | ". git-sh-setup && . git-rebase--common &&" |
| 493 | " . %s && %s", backend, backend_func); |
| 494 | argv[0] = script_snippet.buf; |
| 495 | |
| 496 | status = run_command_v_opt(argv, RUN_USING_SHELL); |
Johannes Schindelin | bc24382 | 2018-10-05 08:54:38 -0700 | [diff] [blame] | 497 | finished_rebase: |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 498 | if (opts->dont_finish_rebase) |
| 499 | ; /* do nothing */ |
Johannes Schindelin | bc24382 | 2018-10-05 08:54:38 -0700 | [diff] [blame] | 500 | else if (opts->type == REBASE_INTERACTIVE) |
| 501 | ; /* interactive rebase cleans up after itself */ |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 502 | else if (status == 0) { |
| 503 | if (!file_exists(state_dir_path("stopped-sha", opts))) |
| 504 | finish_rebase(opts); |
| 505 | } else if (status == 2) { |
| 506 | struct strbuf dir = STRBUF_INIT; |
| 507 | |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 508 | apply_autostash(opts); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 509 | strbuf_addstr(&dir, opts->state_dir); |
| 510 | remove_dir_recursively(&dir, 0); |
| 511 | strbuf_release(&dir); |
| 512 | die("Nothing to do"); |
| 513 | } |
| 514 | |
| 515 | strbuf_release(&script_snippet); |
| 516 | |
| 517 | return status ? -1 : 0; |
| 518 | } |
| 519 | |
| 520 | #define GIT_REFLOG_ACTION_ENVIRONMENT "GIT_REFLOG_ACTION" |
| 521 | |
| 522 | static int reset_head(struct object_id *oid, const char *action, |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 523 | const char *switch_to_branch, int detach_head, |
| 524 | const char *reflog_orig_head, const char *reflog_head) |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 525 | { |
| 526 | struct object_id head_oid; |
| 527 | struct tree_desc desc; |
| 528 | struct lock_file lock = LOCK_INIT; |
| 529 | struct unpack_trees_options unpack_tree_opts; |
| 530 | struct tree *tree; |
| 531 | const char *reflog_action; |
| 532 | struct strbuf msg = STRBUF_INIT; |
| 533 | size_t prefix_len; |
| 534 | struct object_id *orig = NULL, oid_orig, |
| 535 | *old_orig = NULL, oid_old_orig; |
| 536 | int ret = 0; |
| 537 | |
Pratik Karki | d4c569f | 2018-09-04 14:27:20 -0700 | [diff] [blame] | 538 | if (switch_to_branch && !starts_with(switch_to_branch, "refs/")) |
| 539 | BUG("Not a fully qualified branch: '%s'", switch_to_branch); |
| 540 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 541 | if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) |
| 542 | return -1; |
| 543 | |
| 544 | if (!oid) { |
| 545 | if (get_oid("HEAD", &head_oid)) { |
| 546 | rollback_lock_file(&lock); |
| 547 | return error(_("could not determine HEAD revision")); |
| 548 | } |
| 549 | oid = &head_oid; |
| 550 | } |
| 551 | |
| 552 | memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts)); |
| 553 | setup_unpack_trees_porcelain(&unpack_tree_opts, action); |
| 554 | unpack_tree_opts.head_idx = 1; |
| 555 | unpack_tree_opts.src_index = the_repository->index; |
| 556 | unpack_tree_opts.dst_index = the_repository->index; |
| 557 | unpack_tree_opts.fn = oneway_merge; |
| 558 | unpack_tree_opts.update = 1; |
| 559 | unpack_tree_opts.merge = 1; |
| 560 | if (!detach_head) |
| 561 | unpack_tree_opts.reset = 1; |
| 562 | |
| 563 | if (read_index_unmerged(the_repository->index) < 0) { |
| 564 | rollback_lock_file(&lock); |
| 565 | return error(_("could not read index")); |
| 566 | } |
| 567 | |
| 568 | if (!fill_tree_descriptor(&desc, oid)) { |
| 569 | error(_("failed to find tree of %s"), oid_to_hex(oid)); |
| 570 | rollback_lock_file(&lock); |
| 571 | free((void *)desc.buffer); |
| 572 | return -1; |
| 573 | } |
| 574 | |
| 575 | if (unpack_trees(1, &desc, &unpack_tree_opts)) { |
| 576 | rollback_lock_file(&lock); |
| 577 | free((void *)desc.buffer); |
| 578 | return -1; |
| 579 | } |
| 580 | |
| 581 | tree = parse_tree_indirect(oid); |
| 582 | prime_cache_tree(the_repository->index, tree); |
| 583 | |
| 584 | if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK) < 0) |
| 585 | ret = error(_("could not write index")); |
| 586 | free((void *)desc.buffer); |
| 587 | |
| 588 | if (ret) |
| 589 | return ret; |
| 590 | |
| 591 | reflog_action = getenv(GIT_REFLOG_ACTION_ENVIRONMENT); |
| 592 | strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase"); |
| 593 | prefix_len = msg.len; |
| 594 | |
| 595 | if (!get_oid("ORIG_HEAD", &oid_old_orig)) |
| 596 | old_orig = &oid_old_orig; |
| 597 | if (!get_oid("HEAD", &oid_orig)) { |
| 598 | orig = &oid_orig; |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 599 | if (!reflog_orig_head) { |
| 600 | strbuf_addstr(&msg, "updating ORIG_HEAD"); |
| 601 | reflog_orig_head = msg.buf; |
| 602 | } |
| 603 | update_ref(reflog_orig_head, "ORIG_HEAD", orig, old_orig, 0, |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 604 | UPDATE_REFS_MSG_ON_ERR); |
| 605 | } else if (old_orig) |
| 606 | delete_ref(NULL, "ORIG_HEAD", old_orig, 0); |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 607 | if (!reflog_head) { |
| 608 | strbuf_setlen(&msg, prefix_len); |
| 609 | strbuf_addstr(&msg, "updating HEAD"); |
| 610 | reflog_head = msg.buf; |
| 611 | } |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 612 | if (!switch_to_branch) |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 613 | ret = update_ref(reflog_head, "HEAD", oid, orig, REF_NO_DEREF, |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 614 | UPDATE_REFS_MSG_ON_ERR); |
| 615 | else { |
| 616 | ret = create_symref("HEAD", switch_to_branch, msg.buf); |
| 617 | if (!ret) |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 618 | ret = update_ref(reflog_head, "HEAD", oid, NULL, 0, |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 619 | UPDATE_REFS_MSG_ON_ERR); |
| 620 | } |
| 621 | |
| 622 | strbuf_release(&msg); |
| 623 | return ret; |
| 624 | } |
| 625 | |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 626 | static int rebase_config(const char *var, const char *value, void *data) |
| 627 | { |
| 628 | struct rebase_options *opts = data; |
| 629 | |
| 630 | if (!strcmp(var, "rebase.stat")) { |
| 631 | if (git_config_bool(var, value)) |
| 632 | opts->flags |= REBASE_DIFFSTAT; |
| 633 | else |
| 634 | opts->flags &= !REBASE_DIFFSTAT; |
| 635 | return 0; |
| 636 | } |
| 637 | |
Pratik Karki | 051910a | 2018-09-04 14:59:58 -0700 | [diff] [blame] | 638 | if (!strcmp(var, "rebase.autosquash")) { |
| 639 | opts->autosquash = git_config_bool(var, value); |
| 640 | return 0; |
| 641 | } |
| 642 | |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 643 | if (!strcmp(var, "commit.gpgsign")) { |
| 644 | free(opts->gpg_sign_opt); |
| 645 | opts->gpg_sign_opt = git_config_bool(var, value) ? |
| 646 | xstrdup("-S") : NULL; |
| 647 | return 0; |
| 648 | } |
| 649 | |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 650 | if (!strcmp(var, "rebase.autostash")) { |
| 651 | opts->autostash = git_config_bool(var, value); |
| 652 | return 0; |
| 653 | } |
| 654 | |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 655 | return git_default_config(var, value, data); |
| 656 | } |
| 657 | |
Pratik Karki | 9a48a61 | 2018-09-04 14:27:16 -0700 | [diff] [blame] | 658 | /* |
| 659 | * Determines whether the commits in from..to are linear, i.e. contain |
| 660 | * no merge commits. This function *expects* `from` to be an ancestor of |
| 661 | * `to`. |
| 662 | */ |
| 663 | static int is_linear_history(struct commit *from, struct commit *to) |
| 664 | { |
| 665 | while (to && to != from) { |
| 666 | parse_commit(to); |
| 667 | if (!to->parents) |
| 668 | return 1; |
| 669 | if (to->parents->next) |
| 670 | return 0; |
| 671 | to = to->parents->item; |
| 672 | } |
| 673 | return 1; |
| 674 | } |
| 675 | |
| 676 | static int can_fast_forward(struct commit *onto, struct object_id *head_oid, |
| 677 | struct object_id *merge_base) |
| 678 | { |
| 679 | struct commit *head = lookup_commit(the_repository, head_oid); |
| 680 | struct commit_list *merge_bases; |
| 681 | int res; |
| 682 | |
| 683 | if (!head) |
| 684 | return 0; |
| 685 | |
| 686 | merge_bases = get_merge_bases(onto, head); |
| 687 | if (merge_bases && !merge_bases->next) { |
| 688 | oidcpy(merge_base, &merge_bases->item->object.oid); |
| 689 | res = !oidcmp(merge_base, &onto->object.oid); |
| 690 | } else { |
| 691 | oidcpy(merge_base, &null_oid); |
| 692 | res = 0; |
| 693 | } |
| 694 | free_commit_list(merge_bases); |
| 695 | return res && is_linear_history(onto, head); |
| 696 | } |
| 697 | |
Pratik Karki | 361badd | 2018-09-04 14:59:49 -0700 | [diff] [blame] | 698 | /* -i followed by -m is still -i */ |
| 699 | static int parse_opt_merge(const struct option *opt, const char *arg, int unset) |
| 700 | { |
| 701 | struct rebase_options *opts = opt->value; |
| 702 | |
| 703 | if (!is_interactive(opts)) |
| 704 | opts->type = REBASE_MERGE; |
| 705 | |
| 706 | return 0; |
| 707 | } |
| 708 | |
| 709 | /* -i followed by -p is still explicitly interactive, but -p alone is not */ |
| 710 | static int parse_opt_interactive(const struct option *opt, const char *arg, |
| 711 | int unset) |
| 712 | { |
| 713 | struct rebase_options *opts = opt->value; |
| 714 | |
| 715 | opts->type = REBASE_INTERACTIVE; |
| 716 | opts->flags |= REBASE_INTERACTIVE_EXPLICIT; |
| 717 | |
| 718 | return 0; |
| 719 | } |
| 720 | |
Pratik Karki | 8f5986d | 2018-08-08 21:21:30 +0545 | [diff] [blame] | 721 | static void NORETURN error_on_missing_default_upstream(void) |
| 722 | { |
| 723 | struct branch *current_branch = branch_get(NULL); |
| 724 | |
| 725 | printf(_("%s\n" |
| 726 | "Please specify which branch you want to rebase against.\n" |
| 727 | "See git-rebase(1) for details.\n" |
| 728 | "\n" |
| 729 | " git rebase '<branch>'\n" |
| 730 | "\n"), |
| 731 | current_branch ? _("There is no tracking information for " |
| 732 | "the current branch.") : |
| 733 | _("You are not currently on a branch.")); |
| 734 | |
| 735 | if (current_branch) { |
| 736 | const char *remote = current_branch->remote_name; |
| 737 | |
| 738 | if (!remote) |
| 739 | remote = _("<remote>"); |
| 740 | |
| 741 | printf(_("If you wish to set tracking information for this " |
| 742 | "branch you can do so with:\n" |
| 743 | "\n" |
| 744 | " git branch --set-upstream-to=%s/<branch> %s\n" |
| 745 | "\n"), |
| 746 | remote, current_branch->name); |
| 747 | } |
| 748 | exit(1); |
| 749 | } |
| 750 | |
Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 751 | int cmd_rebase(int argc, const char **argv, const char *prefix) |
| 752 | { |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 753 | struct rebase_options options = { |
| 754 | .type = REBASE_UNSPECIFIED, |
Pratik Karki | b4c8eb0 | 2018-09-04 14:27:12 -0700 | [diff] [blame] | 755 | .flags = REBASE_NO_QUIET, |
| 756 | .git_am_opt = STRBUF_INIT, |
Pratik Karki | ead98c1 | 2018-09-04 14:59:52 -0700 | [diff] [blame] | 757 | .allow_rerere_autoupdate = -1, |
Pratik Karki | 9b3a448 | 2018-09-04 15:00:05 -0700 | [diff] [blame] | 758 | .allow_empty_message = 1, |
Pratik Karki | cda614e | 2018-08-08 21:21:33 +0545 | [diff] [blame] | 759 | .git_format_patch_opt = STRBUF_INIT, |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 760 | }; |
| 761 | const char *branch_name; |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 762 | int ret, flags, total_argc, in_progress = 0; |
Pratik Karki | 06e4775 | 2018-09-04 14:27:10 -0700 | [diff] [blame] | 763 | int ok_to_skip_pre_rebase = 0; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 764 | struct strbuf msg = STRBUF_INIT; |
| 765 | struct strbuf revisions = STRBUF_INIT; |
Pratik Karki | c54dacb | 2018-09-04 14:27:18 -0700 | [diff] [blame] | 766 | struct strbuf buf = STRBUF_INIT; |
Pratik Karki | 075bc85 | 2018-09-04 14:27:09 -0700 | [diff] [blame] | 767 | struct object_id merge_base; |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 768 | enum { |
| 769 | NO_ACTION, |
| 770 | ACTION_CONTINUE, |
Pratik Karki | 122420c | 2018-08-08 20:51:17 +0545 | [diff] [blame] | 771 | ACTION_SKIP, |
Pratik Karki | 5e5d961 | 2018-08-08 20:51:18 +0545 | [diff] [blame] | 772 | ACTION_ABORT, |
Pratik Karki | 5a61494 | 2018-08-08 20:51:19 +0545 | [diff] [blame] | 773 | ACTION_QUIT, |
Pratik Karki | 51e9ea6 | 2018-08-08 20:51:20 +0545 | [diff] [blame] | 774 | ACTION_EDIT_TODO, |
| 775 | ACTION_SHOW_CURRENT_PATCH, |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 776 | } action = NO_ACTION; |
Pratik Karki | 38dbcef | 2018-09-04 14:59:53 -0700 | [diff] [blame] | 777 | int committer_date_is_author_date = 0; |
Pratik Karki | 53f9e5b | 2018-09-04 14:59:56 -0700 | [diff] [blame] | 778 | int ignore_date = 0; |
Pratik Karki | 99d8cc7 | 2018-09-04 14:59:54 -0700 | [diff] [blame] | 779 | int ignore_whitespace = 0; |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 780 | const char *gpg_sign = NULL; |
Pratik Karki | 7998dbe | 2018-09-04 15:00:01 -0700 | [diff] [blame] | 781 | int opt_c = -1; |
| 782 | struct string_list whitespace = STRING_LIST_INIT_NODUP; |
Pratik Karki | 68e46d7 | 2018-09-04 15:00:04 -0700 | [diff] [blame] | 783 | struct string_list exec = STRING_LIST_INIT_NODUP; |
Pratik Karki | 3c3588c | 2018-09-04 15:00:07 -0700 | [diff] [blame] | 784 | const char *rebase_merges = NULL; |
Pratik Karki | 92d0d74 | 2018-09-04 15:00:09 -0700 | [diff] [blame] | 785 | int fork_point = -1; |
Pratik Karki | ba1905a | 2018-09-04 15:00:11 -0700 | [diff] [blame] | 786 | struct string_list strategy_options = STRING_LIST_INIT_NODUP; |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 787 | struct object_id squash_onto; |
| 788 | char *squash_onto_name = NULL; |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 789 | struct option builtin_rebase_options[] = { |
| 790 | OPT_STRING(0, "onto", &options.onto_name, |
| 791 | N_("revision"), |
| 792 | N_("rebase onto given branch instead of upstream")), |
Pratik Karki | 06e4775 | 2018-09-04 14:27:10 -0700 | [diff] [blame] | 793 | OPT_BOOL(0, "no-verify", &ok_to_skip_pre_rebase, |
| 794 | N_("allow pre-rebase hook to run")), |
Pratik Karki | b4c8eb0 | 2018-09-04 14:27:12 -0700 | [diff] [blame] | 795 | OPT_NEGBIT('q', "quiet", &options.flags, |
| 796 | N_("be quiet. implies --no-stat"), |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 797 | REBASE_NO_QUIET| REBASE_VERBOSE | REBASE_DIFFSTAT), |
| 798 | OPT_BIT('v', "verbose", &options.flags, |
| 799 | N_("display a diffstat of what changed upstream"), |
| 800 | REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT), |
| 801 | {OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL, |
| 802 | N_("do not show diffstat of what changed upstream"), |
| 803 | PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT }, |
Pratik Karki | 99d8cc7 | 2018-09-04 14:59:54 -0700 | [diff] [blame] | 804 | OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace, |
| 805 | N_("passed to 'git apply'")), |
Pratik Karki | 73d51ed | 2018-09-04 14:59:50 -0700 | [diff] [blame] | 806 | OPT_BOOL(0, "signoff", &options.signoff, |
| 807 | N_("add a Signed-off-by: line to each commit")), |
Pratik Karki | 38dbcef | 2018-09-04 14:59:53 -0700 | [diff] [blame] | 808 | OPT_BOOL(0, "committer-date-is-author-date", |
| 809 | &committer_date_is_author_date, |
| 810 | N_("passed to 'git am'")), |
Pratik Karki | 53f9e5b | 2018-09-04 14:59:56 -0700 | [diff] [blame] | 811 | OPT_BOOL(0, "ignore-date", &ignore_date, |
| 812 | N_("passed to 'git am'")), |
Pratik Karki | 1ed9c14 | 2018-09-04 14:27:17 -0700 | [diff] [blame] | 813 | OPT_BIT('f', "force-rebase", &options.flags, |
| 814 | N_("cherry-pick all commits, even if unchanged"), |
| 815 | REBASE_FORCE), |
| 816 | OPT_BIT(0, "no-ff", &options.flags, |
| 817 | N_("cherry-pick all commits, even if unchanged"), |
| 818 | REBASE_FORCE), |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 819 | OPT_CMDMODE(0, "continue", &action, N_("continue"), |
| 820 | ACTION_CONTINUE), |
Pratik Karki | 122420c | 2018-08-08 20:51:17 +0545 | [diff] [blame] | 821 | OPT_CMDMODE(0, "skip", &action, |
| 822 | N_("skip current patch and continue"), ACTION_SKIP), |
Pratik Karki | 5e5d961 | 2018-08-08 20:51:18 +0545 | [diff] [blame] | 823 | OPT_CMDMODE(0, "abort", &action, |
| 824 | N_("abort and check out the original branch"), |
| 825 | ACTION_ABORT), |
Pratik Karki | 5a61494 | 2018-08-08 20:51:19 +0545 | [diff] [blame] | 826 | OPT_CMDMODE(0, "quit", &action, |
| 827 | N_("abort but keep HEAD where it is"), ACTION_QUIT), |
Pratik Karki | 51e9ea6 | 2018-08-08 20:51:20 +0545 | [diff] [blame] | 828 | OPT_CMDMODE(0, "edit-todo", &action, N_("edit the todo list " |
| 829 | "during an interactive rebase"), ACTION_EDIT_TODO), |
| 830 | OPT_CMDMODE(0, "show-current-patch", &action, |
| 831 | N_("show the patch file being applied or merged"), |
| 832 | ACTION_SHOW_CURRENT_PATCH), |
Pratik Karki | 361badd | 2018-09-04 14:59:49 -0700 | [diff] [blame] | 833 | { OPTION_CALLBACK, 'm', "merge", &options, NULL, |
| 834 | N_("use merging strategies to rebase"), |
| 835 | PARSE_OPT_NOARG | PARSE_OPT_NONEG, |
| 836 | parse_opt_merge }, |
| 837 | { OPTION_CALLBACK, 'i', "interactive", &options, NULL, |
| 838 | N_("let the user edit the list of commits to rebase"), |
| 839 | PARSE_OPT_NOARG | PARSE_OPT_NONEG, |
| 840 | parse_opt_interactive }, |
| 841 | OPT_SET_INT('p', "preserve-merges", &options.type, |
| 842 | N_("try to recreate merges instead of ignoring " |
| 843 | "them"), REBASE_PRESERVE_MERGES), |
Pratik Karki | ead98c1 | 2018-09-04 14:59:52 -0700 | [diff] [blame] | 844 | OPT_BOOL(0, "rerere-autoupdate", |
| 845 | &options.allow_rerere_autoupdate, |
| 846 | N_("allow rerere to update index with resolved " |
| 847 | "conflict")), |
Pratik Karki | 002ee2f | 2018-09-04 14:59:57 -0700 | [diff] [blame] | 848 | OPT_BOOL('k', "keep-empty", &options.keep_empty, |
| 849 | N_("preserve empty commits during rebase")), |
Pratik Karki | 051910a | 2018-09-04 14:59:58 -0700 | [diff] [blame] | 850 | OPT_BOOL(0, "autosquash", &options.autosquash, |
| 851 | N_("move commits that begin with " |
| 852 | "squash!/fixup! under -i")), |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 853 | { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"), |
| 854 | N_("GPG-sign commits"), |
| 855 | PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, |
Pratik Karki | 7998dbe | 2018-09-04 15:00:01 -0700 | [diff] [blame] | 856 | OPT_STRING_LIST(0, "whitespace", &whitespace, |
| 857 | N_("whitespace"), N_("passed to 'git apply'")), |
| 858 | OPT_SET_INT('C', NULL, &opt_c, N_("passed to 'git apply'"), |
| 859 | REBASE_AM), |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 860 | OPT_BOOL(0, "autostash", &options.autostash, |
| 861 | N_("automatically stash/stash pop before and after")), |
Pratik Karki | 68e46d7 | 2018-09-04 15:00:04 -0700 | [diff] [blame] | 862 | OPT_STRING_LIST('x', "exec", &exec, N_("exec"), |
| 863 | N_("add exec lines after each commit of the " |
| 864 | "editable list")), |
Pratik Karki | 9b3a448 | 2018-09-04 15:00:05 -0700 | [diff] [blame] | 865 | OPT_BOOL(0, "allow-empty-message", |
| 866 | &options.allow_empty_message, |
| 867 | N_("allow rebasing commits with empty messages")), |
Pratik Karki | 3c3588c | 2018-09-04 15:00:07 -0700 | [diff] [blame] | 868 | {OPTION_STRING, 'r', "rebase-merges", &rebase_merges, |
| 869 | N_("mode"), |
| 870 | N_("try to rebase merges instead of skipping them"), |
| 871 | PARSE_OPT_OPTARG, NULL, (intptr_t)""}, |
Pratik Karki | 92d0d74 | 2018-09-04 15:00:09 -0700 | [diff] [blame] | 872 | OPT_BOOL(0, "fork-point", &fork_point, |
| 873 | N_("use 'merge-base --fork-point' to refine upstream")), |
Pratik Karki | ba1905a | 2018-09-04 15:00:11 -0700 | [diff] [blame] | 874 | OPT_STRING('s', "strategy", &options.strategy, |
| 875 | N_("strategy"), N_("use the given merge strategy")), |
| 876 | OPT_STRING_LIST('X', "strategy-option", &strategy_options, |
| 877 | N_("option"), |
| 878 | N_("pass the argument through to the merge " |
| 879 | "strategy")), |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 880 | OPT_BOOL(0, "root", &options.root, |
| 881 | N_("rebase all reachable commits up to the root(s)")), |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 882 | OPT_END(), |
| 883 | }; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 884 | |
Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 885 | /* |
| 886 | * NEEDSWORK: Once the builtin rebase has been tested enough |
| 887 | * and git-legacy-rebase.sh is retired to contrib/, this preamble |
| 888 | * can be removed. |
| 889 | */ |
| 890 | |
| 891 | if (!use_builtin_rebase()) { |
| 892 | const char *path = mkpath("%s/git-legacy-rebase", |
| 893 | git_exec_path()); |
| 894 | |
| 895 | if (sane_execvp(path, (char **)argv) < 0) |
| 896 | die_errno(_("could not exec %s"), path); |
| 897 | else |
| 898 | BUG("sane_execvp() returned???"); |
| 899 | } |
| 900 | |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 901 | if (argc == 2 && !strcmp(argv[1], "-h")) |
| 902 | usage_with_options(builtin_rebase_usage, |
| 903 | builtin_rebase_options); |
| 904 | |
Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 905 | prefix = setup_git_directory(); |
| 906 | trace_repo_setup(prefix); |
| 907 | setup_work_tree(); |
| 908 | |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 909 | git_config(rebase_config, &options); |
| 910 | |
Pratik Karki | 0eabf4b | 2018-08-08 20:51:22 +0545 | [diff] [blame] | 911 | strbuf_reset(&buf); |
| 912 | strbuf_addf(&buf, "%s/applying", apply_dir()); |
| 913 | if(file_exists(buf.buf)) |
| 914 | die(_("It looks like 'git am' is in progress. Cannot rebase.")); |
| 915 | |
Pratik Karki | c54dacb | 2018-09-04 14:27:18 -0700 | [diff] [blame] | 916 | if (is_directory(apply_dir())) { |
| 917 | options.type = REBASE_AM; |
| 918 | options.state_dir = apply_dir(); |
| 919 | } else if (is_directory(merge_dir())) { |
| 920 | strbuf_reset(&buf); |
| 921 | strbuf_addf(&buf, "%s/rewritten", merge_dir()); |
| 922 | if (is_directory(buf.buf)) { |
| 923 | options.type = REBASE_PRESERVE_MERGES; |
| 924 | options.flags |= REBASE_INTERACTIVE_EXPLICIT; |
| 925 | } else { |
| 926 | strbuf_reset(&buf); |
| 927 | strbuf_addf(&buf, "%s/interactive", merge_dir()); |
| 928 | if(file_exists(buf.buf)) { |
| 929 | options.type = REBASE_INTERACTIVE; |
| 930 | options.flags |= REBASE_INTERACTIVE_EXPLICIT; |
| 931 | } else |
| 932 | options.type = REBASE_MERGE; |
| 933 | } |
| 934 | options.state_dir = merge_dir(); |
| 935 | } |
| 936 | |
| 937 | if (options.type != REBASE_UNSPECIFIED) |
| 938 | in_progress = 1; |
| 939 | |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 940 | total_argc = argc; |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 941 | argc = parse_options(argc, argv, prefix, |
| 942 | builtin_rebase_options, |
| 943 | builtin_rebase_usage, 0); |
| 944 | |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 945 | if (action != NO_ACTION && total_argc != 2) { |
| 946 | usage_with_options(builtin_rebase_usage, |
| 947 | builtin_rebase_options); |
| 948 | } |
| 949 | |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 950 | if (argc > 2) |
| 951 | usage_with_options(builtin_rebase_usage, |
| 952 | builtin_rebase_options); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 953 | |
Pratik Karki | d732a57 | 2018-08-08 20:51:21 +0545 | [diff] [blame] | 954 | if (action != NO_ACTION && !in_progress) |
| 955 | die(_("No rebase in progress?")); |
| 956 | |
Pratik Karki | 51e9ea6 | 2018-08-08 20:51:20 +0545 | [diff] [blame] | 957 | if (action == ACTION_EDIT_TODO && !is_interactive(&options)) |
| 958 | die(_("The --edit-todo action can only be used during " |
| 959 | "interactive rebase.")); |
| 960 | |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 961 | switch (action) { |
| 962 | case ACTION_CONTINUE: { |
| 963 | struct object_id head; |
| 964 | struct lock_file lock_file = LOCK_INIT; |
| 965 | int fd; |
| 966 | |
| 967 | options.action = "continue"; |
| 968 | |
| 969 | /* Sanity check */ |
| 970 | if (get_oid("HEAD", &head)) |
| 971 | die(_("Cannot read HEAD")); |
| 972 | |
| 973 | fd = hold_locked_index(&lock_file, 0); |
| 974 | if (read_index(the_repository->index) < 0) |
| 975 | die(_("could not read index")); |
| 976 | refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, |
| 977 | NULL); |
| 978 | if (0 <= fd) |
| 979 | update_index_if_able(the_repository->index, |
| 980 | &lock_file); |
| 981 | rollback_lock_file(&lock_file); |
| 982 | |
| 983 | if (has_unstaged_changes(1)) { |
| 984 | puts(_("You must edit all merge conflicts and then\n" |
| 985 | "mark them as resolved using git add")); |
| 986 | exit(1); |
| 987 | } |
| 988 | if (read_basic_state(&options)) |
| 989 | exit(1); |
| 990 | goto run_rebase; |
| 991 | } |
Pratik Karki | 122420c | 2018-08-08 20:51:17 +0545 | [diff] [blame] | 992 | case ACTION_SKIP: { |
| 993 | struct string_list merge_rr = STRING_LIST_INIT_DUP; |
| 994 | |
| 995 | options.action = "skip"; |
| 996 | |
| 997 | rerere_clear(&merge_rr); |
| 998 | string_list_clear(&merge_rr, 1); |
| 999 | |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 1000 | if (reset_head(NULL, "reset", NULL, 0, NULL, NULL) < 0) |
Pratik Karki | 122420c | 2018-08-08 20:51:17 +0545 | [diff] [blame] | 1001 | die(_("could not discard worktree changes")); |
| 1002 | if (read_basic_state(&options)) |
| 1003 | exit(1); |
| 1004 | goto run_rebase; |
| 1005 | } |
Pratik Karki | 5e5d961 | 2018-08-08 20:51:18 +0545 | [diff] [blame] | 1006 | case ACTION_ABORT: { |
| 1007 | struct string_list merge_rr = STRING_LIST_INIT_DUP; |
| 1008 | options.action = "abort"; |
| 1009 | |
| 1010 | rerere_clear(&merge_rr); |
| 1011 | string_list_clear(&merge_rr, 1); |
| 1012 | |
| 1013 | if (read_basic_state(&options)) |
| 1014 | exit(1); |
| 1015 | if (reset_head(&options.orig_head, "reset", |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 1016 | options.head_name, 0, NULL, NULL) < 0) |
Pratik Karki | 5e5d961 | 2018-08-08 20:51:18 +0545 | [diff] [blame] | 1017 | die(_("could not move back to %s"), |
| 1018 | oid_to_hex(&options.orig_head)); |
| 1019 | ret = finish_rebase(&options); |
| 1020 | goto cleanup; |
| 1021 | } |
Pratik Karki | 5a61494 | 2018-08-08 20:51:19 +0545 | [diff] [blame] | 1022 | case ACTION_QUIT: { |
| 1023 | strbuf_reset(&buf); |
| 1024 | strbuf_addstr(&buf, options.state_dir); |
| 1025 | ret = !!remove_dir_recursively(&buf, 0); |
| 1026 | if (ret) |
| 1027 | die(_("could not remove '%s'"), options.state_dir); |
| 1028 | goto cleanup; |
| 1029 | } |
Pratik Karki | 51e9ea6 | 2018-08-08 20:51:20 +0545 | [diff] [blame] | 1030 | case ACTION_EDIT_TODO: |
| 1031 | options.action = "edit-todo"; |
| 1032 | options.dont_finish_rebase = 1; |
| 1033 | goto run_rebase; |
| 1034 | case ACTION_SHOW_CURRENT_PATCH: |
| 1035 | options.action = "show-current-patch"; |
| 1036 | options.dont_finish_rebase = 1; |
| 1037 | goto run_rebase; |
| 1038 | case NO_ACTION: |
| 1039 | break; |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 1040 | default: |
Pratik Karki | 51e9ea6 | 2018-08-08 20:51:20 +0545 | [diff] [blame] | 1041 | BUG("action: %d", action); |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 1042 | } |
| 1043 | |
Pratik Karki | c54dacb | 2018-09-04 14:27:18 -0700 | [diff] [blame] | 1044 | /* Make sure no rebase is in progress */ |
| 1045 | if (in_progress) { |
| 1046 | const char *last_slash = strrchr(options.state_dir, '/'); |
| 1047 | const char *state_dir_base = |
| 1048 | last_slash ? last_slash + 1 : options.state_dir; |
| 1049 | const char *cmd_live_rebase = |
| 1050 | "git rebase (--continue | --abort | --skip)"; |
| 1051 | strbuf_reset(&buf); |
| 1052 | strbuf_addf(&buf, "rm -fr \"%s\"", options.state_dir); |
| 1053 | die(_("It seems that there is already a %s directory, and\n" |
| 1054 | "I wonder if you are in the middle of another rebase. " |
| 1055 | "If that is the\n" |
| 1056 | "case, please try\n\t%s\n" |
| 1057 | "If that is not the case, please\n\t%s\n" |
| 1058 | "and run me again. I am stopping in case you still " |
| 1059 | "have something\n" |
| 1060 | "valuable there.\n"), |
| 1061 | state_dir_base, cmd_live_rebase, buf.buf); |
| 1062 | } |
| 1063 | |
Pratik Karki | b4c8eb0 | 2018-09-04 14:27:12 -0700 | [diff] [blame] | 1064 | if (!(options.flags & REBASE_NO_QUIET)) |
| 1065 | strbuf_addstr(&options.git_am_opt, " -q"); |
| 1066 | |
Pratik Karki | 38dbcef | 2018-09-04 14:59:53 -0700 | [diff] [blame] | 1067 | if (committer_date_is_author_date) { |
| 1068 | strbuf_addstr(&options.git_am_opt, |
| 1069 | " --committer-date-is-author-date"); |
| 1070 | options.flags |= REBASE_FORCE; |
| 1071 | } |
| 1072 | |
Pratik Karki | 99d8cc7 | 2018-09-04 14:59:54 -0700 | [diff] [blame] | 1073 | if (ignore_whitespace) |
| 1074 | strbuf_addstr(&options.git_am_opt, " --ignore-whitespace"); |
| 1075 | |
Pratik Karki | 53f9e5b | 2018-09-04 14:59:56 -0700 | [diff] [blame] | 1076 | if (ignore_date) { |
| 1077 | strbuf_addstr(&options.git_am_opt, " --ignore-date"); |
| 1078 | options.flags |= REBASE_FORCE; |
| 1079 | } |
| 1080 | |
Pratik Karki | 002ee2f | 2018-09-04 14:59:57 -0700 | [diff] [blame] | 1081 | if (options.keep_empty) |
| 1082 | imply_interactive(&options, "--keep-empty"); |
| 1083 | |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 1084 | if (gpg_sign) { |
| 1085 | free(options.gpg_sign_opt); |
| 1086 | options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign); |
| 1087 | } |
| 1088 | |
Pratik Karki | 7998dbe | 2018-09-04 15:00:01 -0700 | [diff] [blame] | 1089 | if (opt_c >= 0) |
| 1090 | strbuf_addf(&options.git_am_opt, " -C%d", opt_c); |
| 1091 | |
| 1092 | if (whitespace.nr) { |
| 1093 | int i; |
| 1094 | |
| 1095 | for (i = 0; i < whitespace.nr; i++) { |
| 1096 | const char *item = whitespace.items[i].string; |
| 1097 | |
| 1098 | strbuf_addf(&options.git_am_opt, " --whitespace=%s", |
| 1099 | item); |
| 1100 | |
| 1101 | if ((!strcmp(item, "fix")) || (!strcmp(item, "strip"))) |
| 1102 | options.flags |= REBASE_FORCE; |
| 1103 | } |
| 1104 | } |
| 1105 | |
Pratik Karki | 68e46d7 | 2018-09-04 15:00:04 -0700 | [diff] [blame] | 1106 | if (exec.nr) { |
| 1107 | int i; |
| 1108 | |
| 1109 | imply_interactive(&options, "--exec"); |
| 1110 | |
| 1111 | strbuf_reset(&buf); |
| 1112 | for (i = 0; i < exec.nr; i++) |
| 1113 | strbuf_addf(&buf, "exec %s\n", exec.items[i].string); |
| 1114 | options.cmd = xstrdup(buf.buf); |
| 1115 | } |
| 1116 | |
Pratik Karki | 3c3588c | 2018-09-04 15:00:07 -0700 | [diff] [blame] | 1117 | if (rebase_merges) { |
| 1118 | if (!*rebase_merges) |
| 1119 | ; /* default mode; do nothing */ |
| 1120 | else if (!strcmp("rebase-cousins", rebase_merges)) |
| 1121 | options.rebase_cousins = 1; |
| 1122 | else if (strcmp("no-rebase-cousins", rebase_merges)) |
| 1123 | die(_("Unknown mode: %s"), rebase_merges); |
| 1124 | options.rebase_merges = 1; |
| 1125 | imply_interactive(&options, "--rebase-merges"); |
| 1126 | } |
| 1127 | |
Pratik Karki | ba1905a | 2018-09-04 15:00:11 -0700 | [diff] [blame] | 1128 | if (strategy_options.nr) { |
| 1129 | int i; |
| 1130 | |
| 1131 | if (!options.strategy) |
| 1132 | options.strategy = "recursive"; |
| 1133 | |
| 1134 | strbuf_reset(&buf); |
| 1135 | for (i = 0; i < strategy_options.nr; i++) |
| 1136 | strbuf_addf(&buf, " --%s", |
| 1137 | strategy_options.items[i].string); |
| 1138 | options.strategy_opts = xstrdup(buf.buf); |
| 1139 | } |
| 1140 | |
| 1141 | if (options.strategy) { |
| 1142 | options.strategy = xstrdup(options.strategy); |
| 1143 | switch (options.type) { |
| 1144 | case REBASE_AM: |
| 1145 | die(_("--strategy requires --merge or --interactive")); |
| 1146 | case REBASE_MERGE: |
| 1147 | case REBASE_INTERACTIVE: |
| 1148 | case REBASE_PRESERVE_MERGES: |
| 1149 | /* compatible */ |
| 1150 | break; |
| 1151 | case REBASE_UNSPECIFIED: |
| 1152 | options.type = REBASE_MERGE; |
| 1153 | break; |
| 1154 | default: |
| 1155 | BUG("unhandled rebase type (%d)", options.type); |
| 1156 | } |
| 1157 | } |
| 1158 | |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 1159 | if (options.root && !options.onto_name) |
| 1160 | imply_interactive(&options, "--root without --onto"); |
| 1161 | |
Pratik Karki | cda614e | 2018-08-08 21:21:33 +0545 | [diff] [blame] | 1162 | if (isatty(2) && options.flags & REBASE_NO_QUIET) |
| 1163 | strbuf_addstr(&options.git_format_patch_opt, " --progress"); |
| 1164 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1165 | switch (options.type) { |
| 1166 | case REBASE_MERGE: |
| 1167 | case REBASE_INTERACTIVE: |
| 1168 | case REBASE_PRESERVE_MERGES: |
| 1169 | options.state_dir = merge_dir(); |
| 1170 | break; |
| 1171 | case REBASE_AM: |
| 1172 | options.state_dir = apply_dir(); |
| 1173 | break; |
| 1174 | default: |
| 1175 | /* the default rebase backend is `--am` */ |
| 1176 | options.type = REBASE_AM; |
| 1177 | options.state_dir = apply_dir(); |
| 1178 | break; |
| 1179 | } |
| 1180 | |
Pratik Karki | b361bd7 | 2018-08-08 21:21:35 +0545 | [diff] [blame] | 1181 | if (options.git_am_opt.len) { |
| 1182 | const char *p; |
| 1183 | |
| 1184 | /* all am options except -q are compatible only with --am */ |
| 1185 | strbuf_reset(&buf); |
| 1186 | strbuf_addbuf(&buf, &options.git_am_opt); |
| 1187 | strbuf_addch(&buf, ' '); |
| 1188 | while ((p = strstr(buf.buf, " -q "))) |
| 1189 | strbuf_splice(&buf, p - buf.buf, 4, " ", 1); |
| 1190 | strbuf_trim(&buf); |
| 1191 | |
| 1192 | if (is_interactive(&options) && buf.len) |
| 1193 | die(_("error: cannot combine interactive options " |
| 1194 | "(--interactive, --exec, --rebase-merges, " |
| 1195 | "--preserve-merges, --keep-empty, --root + " |
| 1196 | "--onto) with am options (%s)"), buf.buf); |
| 1197 | if (options.type == REBASE_MERGE && buf.len) |
| 1198 | die(_("error: cannot combine merge options (--merge, " |
| 1199 | "--strategy, --strategy-option) with am options " |
| 1200 | "(%s)"), buf.buf); |
| 1201 | } |
| 1202 | |
Pratik Karki | 73d51ed | 2018-09-04 14:59:50 -0700 | [diff] [blame] | 1203 | if (options.signoff) { |
| 1204 | if (options.type == REBASE_PRESERVE_MERGES) |
| 1205 | die("cannot combine '--signoff' with " |
| 1206 | "'--preserve-merges'"); |
| 1207 | strbuf_addstr(&options.git_am_opt, " --signoff"); |
| 1208 | options.flags |= REBASE_FORCE; |
| 1209 | } |
| 1210 | |
Pratik Karki | b361bd7 | 2018-08-08 21:21:35 +0545 | [diff] [blame] | 1211 | if (options.type == REBASE_PRESERVE_MERGES) |
| 1212 | /* |
| 1213 | * Note: incompatibility with --signoff handled in signoff block above |
| 1214 | * Note: incompatibility with --interactive is just a strong warning; |
| 1215 | * git-rebase.txt caveats with "unless you know what you are doing" |
| 1216 | */ |
| 1217 | if (options.rebase_merges) |
| 1218 | die(_("error: cannot combine '--preserve_merges' with " |
| 1219 | "'--rebase-merges'")); |
| 1220 | |
| 1221 | if (options.rebase_merges) { |
| 1222 | if (strategy_options.nr) |
| 1223 | die(_("error: cannot combine '--rebase_merges' with " |
| 1224 | "'--strategy-option'")); |
| 1225 | if (options.strategy) |
| 1226 | die(_("error: cannot combine '--rebase_merges' with " |
| 1227 | "'--strategy'")); |
| 1228 | } |
| 1229 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1230 | if (!options.root) { |
Pratik Karki | 8f5986d | 2018-08-08 21:21:30 +0545 | [diff] [blame] | 1231 | if (argc < 1) { |
| 1232 | struct branch *branch; |
| 1233 | |
| 1234 | branch = branch_get(NULL); |
| 1235 | options.upstream_name = branch_get_upstream(branch, |
| 1236 | NULL); |
| 1237 | if (!options.upstream_name) |
| 1238 | error_on_missing_default_upstream(); |
| 1239 | if (fork_point < 0) |
| 1240 | fork_point = 1; |
| 1241 | } else { |
Pratik Karki | f28d40d | 2018-09-04 14:27:07 -0700 | [diff] [blame] | 1242 | options.upstream_name = argv[0]; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1243 | argc--; |
| 1244 | argv++; |
| 1245 | if (!strcmp(options.upstream_name, "-")) |
| 1246 | options.upstream_name = "@{-1}"; |
| 1247 | } |
| 1248 | options.upstream = peel_committish(options.upstream_name); |
| 1249 | if (!options.upstream) |
| 1250 | die(_("invalid upstream '%s'"), options.upstream_name); |
Pratik Karki | 06e4775 | 2018-09-04 14:27:10 -0700 | [diff] [blame] | 1251 | options.upstream_arg = options.upstream_name; |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 1252 | } else { |
| 1253 | if (!options.onto_name) { |
| 1254 | if (commit_tree("", 0, the_hash_algo->empty_tree, NULL, |
| 1255 | &squash_onto, NULL, NULL) < 0) |
| 1256 | die(_("Could not create new root commit")); |
| 1257 | options.squash_onto = &squash_onto; |
| 1258 | options.onto_name = squash_onto_name = |
| 1259 | xstrdup(oid_to_hex(&squash_onto)); |
| 1260 | } |
| 1261 | options.upstream_name = NULL; |
| 1262 | options.upstream = NULL; |
| 1263 | if (argc > 1) |
| 1264 | usage_with_options(builtin_rebase_usage, |
| 1265 | builtin_rebase_options); |
| 1266 | options.upstream_arg = "--root"; |
| 1267 | } |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1268 | |
| 1269 | /* Make sure the branch to rebase onto is valid. */ |
| 1270 | if (!options.onto_name) |
| 1271 | options.onto_name = options.upstream_name; |
| 1272 | if (strstr(options.onto_name, "...")) { |
Pratik Karki | 075bc85 | 2018-09-04 14:27:09 -0700 | [diff] [blame] | 1273 | if (get_oid_mb(options.onto_name, &merge_base) < 0) |
| 1274 | die(_("'%s': need exactly one merge base"), |
| 1275 | options.onto_name); |
| 1276 | options.onto = lookup_commit_or_die(&merge_base, |
| 1277 | options.onto_name); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1278 | } else { |
| 1279 | options.onto = peel_committish(options.onto_name); |
| 1280 | if (!options.onto) |
| 1281 | die(_("Does not point to a valid commit '%s'"), |
| 1282 | options.onto_name); |
| 1283 | } |
| 1284 | |
| 1285 | /* |
| 1286 | * If the branch to rebase is given, that is the branch we will rebase |
| 1287 | * branch_name -- branch/commit being rebased, or |
| 1288 | * HEAD (already detached) |
| 1289 | * orig_head -- commit object name of tip of the branch before rebasing |
Pratik Karki | d4c569f | 2018-09-04 14:27:20 -0700 | [diff] [blame] | 1290 | * head_name -- refs/heads/<that-branch> or NULL (detached HEAD) |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1291 | */ |
Pratik Karki | e65123a | 2018-09-04 14:27:21 -0700 | [diff] [blame] | 1292 | if (argc == 1) { |
| 1293 | /* Is it "rebase other branchname" or "rebase other commit"? */ |
| 1294 | branch_name = argv[0]; |
| 1295 | options.switch_to = argv[0]; |
| 1296 | |
| 1297 | /* Is it a local branch? */ |
| 1298 | strbuf_reset(&buf); |
| 1299 | strbuf_addf(&buf, "refs/heads/%s", branch_name); |
| 1300 | if (!read_ref(buf.buf, &options.orig_head)) |
| 1301 | options.head_name = xstrdup(buf.buf); |
| 1302 | /* If not is it a valid ref (branch or commit)? */ |
| 1303 | else if (!get_oid(branch_name, &options.orig_head)) |
| 1304 | options.head_name = NULL; |
| 1305 | else |
| 1306 | die(_("fatal: no such branch/commit '%s'"), |
| 1307 | branch_name); |
| 1308 | } else if (argc == 0) { |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1309 | /* Do not need to switch branches, we are already on it. */ |
| 1310 | options.head_name = |
| 1311 | xstrdup_or_null(resolve_ref_unsafe("HEAD", 0, NULL, |
| 1312 | &flags)); |
| 1313 | if (!options.head_name) |
| 1314 | die(_("No such ref: %s"), "HEAD"); |
| 1315 | if (flags & REF_ISSYMREF) { |
| 1316 | if (!skip_prefix(options.head_name, |
| 1317 | "refs/heads/", &branch_name)) |
| 1318 | branch_name = options.head_name; |
| 1319 | |
| 1320 | } else { |
Pratik Karki | d4c569f | 2018-09-04 14:27:20 -0700 | [diff] [blame] | 1321 | free(options.head_name); |
| 1322 | options.head_name = NULL; |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1323 | branch_name = "HEAD"; |
| 1324 | } |
| 1325 | if (get_oid("HEAD", &options.orig_head)) |
| 1326 | die(_("Could not resolve HEAD to a revision")); |
Pratik Karki | e65123a | 2018-09-04 14:27:21 -0700 | [diff] [blame] | 1327 | } else |
| 1328 | BUG("unexpected number of arguments left to parse"); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1329 | |
Pratik Karki | 92d0d74 | 2018-09-04 15:00:09 -0700 | [diff] [blame] | 1330 | if (fork_point > 0) { |
| 1331 | struct commit *head = |
| 1332 | lookup_commit_reference(the_repository, |
| 1333 | &options.orig_head); |
| 1334 | options.restrict_revision = |
| 1335 | get_fork_point(options.upstream_name, head); |
| 1336 | } |
| 1337 | |
Pratik Karki | e0333e5 | 2018-09-04 14:27:14 -0700 | [diff] [blame] | 1338 | if (read_index(the_repository->index) < 0) |
| 1339 | die(_("could not read index")); |
| 1340 | |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 1341 | if (options.autostash) { |
| 1342 | struct lock_file lock_file = LOCK_INIT; |
| 1343 | int fd; |
| 1344 | |
| 1345 | fd = hold_locked_index(&lock_file, 0); |
| 1346 | refresh_cache(REFRESH_QUIET); |
| 1347 | if (0 <= fd) |
| 1348 | update_index_if_able(&the_index, &lock_file); |
| 1349 | rollback_lock_file(&lock_file); |
| 1350 | |
| 1351 | if (has_unstaged_changes(0) || has_uncommitted_changes(0)) { |
| 1352 | const char *autostash = |
| 1353 | state_dir_path("autostash", &options); |
| 1354 | struct child_process stash = CHILD_PROCESS_INIT; |
| 1355 | struct object_id oid; |
| 1356 | struct commit *head = |
| 1357 | lookup_commit_reference(the_repository, |
| 1358 | &options.orig_head); |
| 1359 | |
| 1360 | argv_array_pushl(&stash.args, |
| 1361 | "stash", "create", "autostash", NULL); |
| 1362 | stash.git_cmd = 1; |
| 1363 | stash.no_stdin = 1; |
| 1364 | strbuf_reset(&buf); |
| 1365 | if (capture_command(&stash, &buf, GIT_MAX_HEXSZ)) |
| 1366 | die(_("Cannot autostash")); |
| 1367 | strbuf_trim_trailing_newline(&buf); |
| 1368 | if (get_oid(buf.buf, &oid)) |
| 1369 | die(_("Unexpected stash response: '%s'"), |
| 1370 | buf.buf); |
| 1371 | strbuf_reset(&buf); |
| 1372 | strbuf_add_unique_abbrev(&buf, &oid, DEFAULT_ABBREV); |
| 1373 | |
| 1374 | if (safe_create_leading_directories_const(autostash)) |
| 1375 | die(_("Could not create directory for '%s'"), |
| 1376 | options.state_dir); |
| 1377 | write_file(autostash, "%s", buf.buf); |
| 1378 | printf(_("Created autostash: %s\n"), buf.buf); |
| 1379 | if (reset_head(&head->object.oid, "reset --hard", |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 1380 | NULL, 0, NULL, NULL) < 0) |
Pratik Karki | 6defce2 | 2018-09-04 15:00:02 -0700 | [diff] [blame] | 1381 | die(_("could not reset --hard")); |
| 1382 | printf(_("HEAD is now at %s"), |
| 1383 | find_unique_abbrev(&head->object.oid, |
| 1384 | DEFAULT_ABBREV)); |
| 1385 | strbuf_reset(&buf); |
| 1386 | pp_commit_easy(CMIT_FMT_ONELINE, head, &buf); |
| 1387 | if (buf.len > 0) |
| 1388 | printf(" %s", buf.buf); |
| 1389 | putchar('\n'); |
| 1390 | |
| 1391 | if (discard_index(the_repository->index) < 0 || |
| 1392 | read_index(the_repository->index) < 0) |
| 1393 | die(_("could not read index")); |
| 1394 | } |
| 1395 | } |
| 1396 | |
Pratik Karki | e0333e5 | 2018-09-04 14:27:14 -0700 | [diff] [blame] | 1397 | if (require_clean_work_tree("rebase", |
| 1398 | _("Please commit or stash them."), 1, 1)) { |
| 1399 | ret = 1; |
| 1400 | goto cleanup; |
| 1401 | } |
| 1402 | |
Pratik Karki | 9a48a61 | 2018-09-04 14:27:16 -0700 | [diff] [blame] | 1403 | /* |
| 1404 | * Now we are rebasing commits upstream..orig_head (or with --root, |
| 1405 | * everything leading up to orig_head) on top of onto. |
| 1406 | */ |
| 1407 | |
| 1408 | /* |
| 1409 | * Check if we are already based on onto with linear history, |
| 1410 | * but this should be done only when upstream and onto are the same |
| 1411 | * and if this is not an interactive rebase. |
| 1412 | */ |
| 1413 | if (can_fast_forward(options.onto, &options.orig_head, &merge_base) && |
| 1414 | !is_interactive(&options) && !options.restrict_revision && |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 1415 | options.upstream && |
Pratik Karki | 9a48a61 | 2018-09-04 14:27:16 -0700 | [diff] [blame] | 1416 | !oidcmp(&options.upstream->object.oid, &options.onto->object.oid)) { |
| 1417 | int flag; |
| 1418 | |
Pratik Karki | 1ed9c14 | 2018-09-04 14:27:17 -0700 | [diff] [blame] | 1419 | if (!(options.flags & REBASE_FORCE)) { |
Pratik Karki | e65123a | 2018-09-04 14:27:21 -0700 | [diff] [blame] | 1420 | /* Lazily switch to the target branch if needed... */ |
| 1421 | if (options.switch_to) { |
| 1422 | struct object_id oid; |
| 1423 | |
| 1424 | if (get_oid(options.switch_to, &oid) < 0) { |
| 1425 | ret = !!error(_("could not parse '%s'"), |
| 1426 | options.switch_to); |
| 1427 | goto cleanup; |
| 1428 | } |
| 1429 | |
| 1430 | strbuf_reset(&buf); |
| 1431 | strbuf_addf(&buf, "rebase: checkout %s", |
| 1432 | options.switch_to); |
| 1433 | if (reset_head(&oid, "checkout", |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 1434 | options.head_name, 0, |
| 1435 | NULL, NULL) < 0) { |
Pratik Karki | e65123a | 2018-09-04 14:27:21 -0700 | [diff] [blame] | 1436 | ret = !!error(_("could not switch to " |
| 1437 | "%s"), |
| 1438 | options.switch_to); |
| 1439 | goto cleanup; |
| 1440 | } |
| 1441 | } |
| 1442 | |
Pratik Karki | 1ed9c14 | 2018-09-04 14:27:17 -0700 | [diff] [blame] | 1443 | if (!(options.flags & REBASE_NO_QUIET)) |
| 1444 | ; /* be quiet */ |
| 1445 | else if (!strcmp(branch_name, "HEAD") && |
| 1446 | resolve_ref_unsafe("HEAD", 0, NULL, &flag)) |
| 1447 | puts(_("HEAD is up to date.")); |
| 1448 | else |
| 1449 | printf(_("Current branch %s is up to date.\n"), |
| 1450 | branch_name); |
| 1451 | ret = !!finish_rebase(&options); |
| 1452 | goto cleanup; |
| 1453 | } else if (!(options.flags & REBASE_NO_QUIET)) |
Pratik Karki | 9a48a61 | 2018-09-04 14:27:16 -0700 | [diff] [blame] | 1454 | ; /* be quiet */ |
| 1455 | else if (!strcmp(branch_name, "HEAD") && |
| 1456 | resolve_ref_unsafe("HEAD", 0, NULL, &flag)) |
| 1457 | puts(_("HEAD is up to date, rebase forced.")); |
| 1458 | else |
| 1459 | printf(_("Current branch %s is up to date, rebase " |
| 1460 | "forced.\n"), branch_name); |
| 1461 | } |
| 1462 | |
Pratik Karki | 06e4775 | 2018-09-04 14:27:10 -0700 | [diff] [blame] | 1463 | /* If a hook exists, give it a chance to interrupt*/ |
| 1464 | if (!ok_to_skip_pre_rebase && |
| 1465 | run_hook_le(NULL, "pre-rebase", options.upstream_arg, |
| 1466 | argc ? argv[0] : NULL, NULL)) |
| 1467 | die(_("The pre-rebase hook refused to rebase.")); |
| 1468 | |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 1469 | if (options.flags & REBASE_DIFFSTAT) { |
| 1470 | struct diff_options opts; |
| 1471 | |
| 1472 | if (options.flags & REBASE_VERBOSE) |
| 1473 | printf(_("Changes from %s to %s:\n"), |
| 1474 | oid_to_hex(&merge_base), |
| 1475 | oid_to_hex(&options.onto->object.oid)); |
| 1476 | |
| 1477 | /* We want color (if set), but no pager */ |
| 1478 | diff_setup(&opts); |
| 1479 | opts.stat_width = -1; /* use full terminal width */ |
| 1480 | opts.stat_graph_width = -1; /* respect statGraphWidth config */ |
| 1481 | opts.output_format |= |
| 1482 | DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; |
| 1483 | opts.detect_rename = DIFF_DETECT_RENAME; |
| 1484 | diff_setup_done(&opts); |
| 1485 | diff_tree_oid(&merge_base, &options.onto->object.oid, |
| 1486 | "", &opts); |
| 1487 | diffcore_std(&opts); |
| 1488 | diff_flush(&opts); |
| 1489 | } |
| 1490 | |
Pratik Karki | 361badd | 2018-09-04 14:59:49 -0700 | [diff] [blame] | 1491 | if (is_interactive(&options)) |
| 1492 | goto run_rebase; |
| 1493 | |
Pratik Karki | bff014d | 2018-09-04 14:27:13 -0700 | [diff] [blame] | 1494 | /* Detach HEAD and reset the tree */ |
| 1495 | if (options.flags & REBASE_NO_QUIET) |
| 1496 | printf(_("First, rewinding head to replay your work on top of " |
| 1497 | "it...\n")); |
| 1498 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1499 | strbuf_addf(&msg, "rebase: checkout %s", options.onto_name); |
Pratik Karki | fa443d4 | 2018-08-08 21:21:31 +0545 | [diff] [blame] | 1500 | if (reset_head(&options.onto->object.oid, "checkout", NULL, 1, |
| 1501 | NULL, msg.buf)) |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1502 | die(_("Could not detach HEAD")); |
| 1503 | strbuf_release(&msg); |
| 1504 | |
Pratik Karki | 7eecfa5 | 2018-08-08 21:21:32 +0545 | [diff] [blame] | 1505 | /* |
| 1506 | * If the onto is a proper descendant of the tip of the branch, then |
| 1507 | * we just fast-forwarded. |
| 1508 | */ |
| 1509 | strbuf_reset(&msg); |
| 1510 | if (!oidcmp(&merge_base, &options.orig_head)) { |
| 1511 | printf(_("Fast-forwarded %s to %s. \n"), |
| 1512 | branch_name, options.onto_name); |
| 1513 | strbuf_addf(&msg, "rebase finished: %s onto %s", |
| 1514 | options.head_name ? options.head_name : "detached HEAD", |
| 1515 | oid_to_hex(&options.onto->object.oid)); |
| 1516 | reset_head(NULL, "Fast-forwarded", options.head_name, 0, |
| 1517 | "HEAD", msg.buf); |
| 1518 | strbuf_release(&msg); |
| 1519 | ret = !!finish_rebase(&options); |
| 1520 | goto cleanup; |
| 1521 | } |
| 1522 | |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1523 | strbuf_addf(&revisions, "%s..%s", |
| 1524 | options.root ? oid_to_hex(&options.onto->object.oid) : |
| 1525 | (options.restrict_revision ? |
| 1526 | oid_to_hex(&options.restrict_revision->object.oid) : |
| 1527 | oid_to_hex(&options.upstream->object.oid)), |
| 1528 | oid_to_hex(&options.orig_head)); |
| 1529 | |
| 1530 | options.revisions = revisions.buf; |
| 1531 | |
Pratik Karki | f957362 | 2018-08-08 20:51:16 +0545 | [diff] [blame] | 1532 | run_rebase: |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1533 | ret = !!run_specific_rebase(&options); |
| 1534 | |
Pratik Karki | e0333e5 | 2018-09-04 14:27:14 -0700 | [diff] [blame] | 1535 | cleanup: |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1536 | strbuf_release(&revisions); |
| 1537 | free(options.head_name); |
Pratik Karki | 12026a4 | 2018-09-04 15:00:00 -0700 | [diff] [blame] | 1538 | free(options.gpg_sign_opt); |
Pratik Karki | 68e46d7 | 2018-09-04 15:00:04 -0700 | [diff] [blame] | 1539 | free(options.cmd); |
Pratik Karki | 9dba809 | 2018-09-04 15:00:12 -0700 | [diff] [blame] | 1540 | free(squash_onto_name); |
Pratik Karki | ac7f467 | 2018-08-07 01:16:11 +0545 | [diff] [blame] | 1541 | return ret; |
Pratik Karki | 55071ea | 2018-08-07 01:16:09 +0545 | [diff] [blame] | 1542 | } |