23
#include "hashmap.h"
24
#include "notes-utils.h"
25
#include "sigchain.h"
26
+#include "unpack-trees.h"
27
+#include "worktree.h"
28
29
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
30
122
static GIT_PATH_FUNC(rebase_path_rewritten_list, "rebase-merge/rewritten-list")
123
static GIT_PATH_FUNC(rebase_path_rewritten_pending,
124
"rebase-merge/rewritten-pending")
125
+
126
+/*
127
+ * The path of the file listing refs that need to be deleted after the rebase
128
+ * finishes. This is used by the `label` command to record the need for cleanup.
129
+ */
130
+static GIT_PATH_FUNC(rebase_path_refs_to_delete, "rebase-merge/refs-to-delete")
131
+
132
/*
133
* The following files are written by git-rebase just after parsing the
134
* command-line (and are only consumed, not modified, by the sequencer).
254
255
int sequencer_remove_state(struct replay_opts *opts)
256
{
248
- struct strbuf dir = STRBUF_INIT;
257
+ struct strbuf buf = STRBUF_INIT;
258
int i;
259
260
+ if (is_rebase_i(opts) &&
261
+ strbuf_read_file(&buf, rebase_path_refs_to_delete(), 0) > 0) {
262
+ char *p = buf.buf;
263
+ while (*p) {
264
+ char *eol = strchr(p, '\n');
265
+ if (eol)
266
+ *eol = '\0';
267
+ if (delete_ref("(rebase -i) cleanup", p, NULL, 0) < 0)
268
+ warning(_("could not delete '%s'"), p);
269
+ if (!eol)
270
+ break;
271
+ p = eol + 1;
272
+ }
273
+ }
274
+
275
free(opts->gpg_sign);
276
free(opts->strategy);
277
for (i = 0; i < opts->xopts_nr; i++)
278
free(opts->xopts[i]);
279
free(opts->xopts);
280
257
- strbuf_addstr(&dir, get_dir(opts));
258
- remove_dir_recursively(&dir, 0);
259
- strbuf_release(&dir);
281
+ strbuf_reset(&buf);
282
+ strbuf_addstr(&buf, get_dir(opts));
283
+ remove_dir_recursively(&buf, 0);
284
+ strbuf_release(&buf);
285
286
return 0;
287
}
1305
TODO_SQUASH,
1306
/* commands that do something else than handling a single commit */
1307
TODO_EXEC,
1308
+ TODO_LABEL,
1309
+ TODO_RESET,
1310
/* commands that do nothing but are counted for reporting progress */
1311
TODO_NOOP,
1312
TODO_DROP,
1325
{ 'f', "fixup" },
1326
{ 's', "squash" },
1327
{ 'x', "exec" },
1328
+ { 'l', "label" },
1329
+ { 't', "reset" },
1330
{ 0, "noop" },
1331
{ 'd', "drop" },
1332
{ 0, NULL }
1832
return error(_("missing arguments for %s"),
1833
command_to_string(item->command));
1834
1806
- if (item->command == TODO_EXEC) {
1835
+ if (item->command == TODO_EXEC || item->command == TODO_LABEL ||
1836
+ item->command == TODO_RESET) {
1837
item->commit = NULL;
1838
item->arg = bol;
1839
item->arg_len = (int)(eol - bol);
2501
return status;
2502
}
2503
2504
+static int safe_append(const char *filename, const char *fmt, ...)
2505
+{
2506
+ va_list ap;
2507
+ struct lock_file lock = LOCK_INIT;
2508
+ int fd = hold_lock_file_for_update(&lock, filename,
2509
+ LOCK_REPORT_ON_ERROR);
2510
+ struct strbuf buf = STRBUF_INIT;
2511
+
2512
+ if (fd < 0)
2513
+ return -1;
2514
+
2515
+ if (strbuf_read_file(&buf, filename, 0) < 0 && errno != ENOENT) {
2516
+ error_errno(_("could not read '%s'"), filename);
2517
+ rollback_lock_file(&lock);
2518
+ return -1;
2519
+ }
2520
+ strbuf_complete(&buf, '\n');
2521
+ va_start(ap, fmt);
2522
+ strbuf_vaddf(&buf, fmt, ap);
2523
+ va_end(ap);
2524
+
2525
+ if (write_in_full(fd, buf.buf, buf.len) < 0) {
2526
+ error_errno(_("could not write to '%s'"), filename);
2527
+ strbuf_release(&buf);
2528
+ rollback_lock_file(&lock);
2529
+ return -1;
2530
+ }
2531
+ if (commit_lock_file(&lock) < 0) {
2532
+ strbuf_release(&buf);
2533
+ rollback_lock_file(&lock);
2534
+ return error(_("failed to finalize '%s'"), filename);
2535
+ }
2536
+
2537
+ strbuf_release(&buf);
2538
+ return 0;
2539
+}
2540
+
2541
+static int do_label(const char *name, int len)
2542
+{
2543
+ struct ref_store *refs = get_main_ref_store();
2544
+ struct ref_transaction *transaction;
2545
+ struct strbuf ref_name = STRBUF_INIT, err = STRBUF_INIT;
2546
+ struct strbuf msg = STRBUF_INIT;
2547
+ int ret = 0;
2548
+ struct object_id head_oid;
2549
+
2550
+ if (len == 1 && *name == '#')
2551
+ return error("Illegal label name: '%.*s'", len, name);
2552
+
2553
+ strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
2554
+ strbuf_addf(&msg, "rebase -i (label) '%.*s'", len, name);
2555
+
2556
+ transaction = ref_store_transaction_begin(refs, &err);
2557
+ if (!transaction) {
2558
+ error("%s", err.buf);
2559
+ ret = -1;
2560
+ } else if (get_oid("HEAD", &head_oid)) {
2561
+ error(_("could not read HEAD"));
2562
+ ret = -1;
2563
+ } else if (ref_transaction_update(transaction, ref_name.buf, &head_oid,
2564
+ NULL, 0, msg.buf, &err) < 0 ||
2565
+ ref_transaction_commit(transaction, &err)) {
2566
+ error("%s", err.buf);
2567
+ ret = -1;
2568
+ }
2569
+ ref_transaction_free(transaction);
2570
+ strbuf_release(&err);
2571
+ strbuf_release(&msg);
2572
+
2573
+ if (!ret)
2574
+ ret = safe_append(rebase_path_refs_to_delete(),
2575
+ "%s\n", ref_name.buf);
2576
+ strbuf_release(&ref_name);
2577
+
2578
+ return ret;
2579
+}
2580
+
2581
+static const char *reflog_message(struct replay_opts *opts,
2582
+ const char *sub_action, const char *fmt, ...);
2583
+
2584
+static int do_reset(const char *name, int len, struct replay_opts *opts)
2585
+{
2586
+ struct strbuf ref_name = STRBUF_INIT;
2587
+ struct object_id oid;
2588
+ struct lock_file lock = LOCK_INIT;
2589
+ struct tree_desc desc;
2590
+ struct tree *tree;
2591
+ struct unpack_trees_options unpack_tree_opts;
2592
+ int ret = 0, i;
2593
+
2594
+ if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0)
2595
+ return -1;
2596
+
2597
+ /* Determine the length of the label */
2598
+ for (i = 0; i < len; i++)
2599
+ if (isspace(name[i]))
2600
+ len = i;
2601
+
2602
+ strbuf_addf(&ref_name, "refs/rewritten/%.*s", len, name);
2603
+ if (get_oid(ref_name.buf, &oid) &&
2604
+ get_oid(ref_name.buf + strlen("refs/rewritten/"), &oid)) {
2605
+ error(_("could not read '%s'"), ref_name.buf);
2606
+ rollback_lock_file(&lock);
2607
+ strbuf_release(&ref_name);
2608
+ return -1;
2609
+ }
2610
+
2611
+ memset(&unpack_tree_opts, 0, sizeof(unpack_tree_opts));
2612
+ setup_unpack_trees_porcelain(&unpack_tree_opts, "reset");
2613
+ unpack_tree_opts.head_idx = 1;
2614
+ unpack_tree_opts.src_index = &the_index;
2615
+ unpack_tree_opts.dst_index = &the_index;
2616
+ unpack_tree_opts.fn = oneway_merge;
2617
+ unpack_tree_opts.merge = 1;
2618
+ unpack_tree_opts.update = 1;
2619
+
2620
+ if (read_cache_unmerged()) {
2621
+ rollback_lock_file(&lock);
2622
+ strbuf_release(&ref_name);
2623
+ return error_resolve_conflict(_(action_name(opts)));
2624
+ }
2625
+
2626
+ if (!fill_tree_descriptor(&desc, &oid)) {
2627
+ error(_("failed to find tree of %s"), oid_to_hex(&oid));
2628
+ rollback_lock_file(&lock);
2629
+ free((void *)desc.buffer);
2630
+ strbuf_release(&ref_name);
2631
+ return -1;
2632
+ }
2633
+
2634
+ if (unpack_trees(1, &desc, &unpack_tree_opts)) {
2635
+ rollback_lock_file(&lock);
2636
+ free((void *)desc.buffer);
2637
+ strbuf_release(&ref_name);
2638
+ return -1;
2639
+ }
2640
+
2641
+ tree = parse_tree_indirect(&oid);
2642
+ prime_cache_tree(&the_index, tree);
2643
+
2644
+ if (write_locked_index(&the_index, &lock, COMMIT_LOCK) < 0)
2645
+ ret = error(_("could not write index"));
2646
+ free((void *)desc.buffer);
2647
+
2648
+ if (!ret)
2649
+ ret = update_ref(reflog_message(opts, "reset", "'%.*s'",
2650
+ len, name), "HEAD", &oid,
2651
+ NULL, 0, UPDATE_REFS_MSG_ON_ERR);
2652
+
2653
+ strbuf_release(&ref_name);
2654
+ return ret;
2655
+}
2656
+
2657
static int is_final_fixup(struct todo_list *todo_list)
2658
{
2659
int i = todo_list->current;
2757
2758
static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
2759
{
2577
- int res = 0;
2760
+ int res = 0, reschedule = 0;
2761
2762
setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
2763
if (opts->allow_ff)
2828
intend_to_amend();
2829
return error_failed_squash(item->commit, opts,
2830
item->arg_len, item->arg);
2648
- } else if (res && is_rebase_i(opts))
2831
+ } else if (res && is_rebase_i(opts) && item->commit)
2832
return res | error_with_patch(item->commit,
2833
item->arg, item->arg_len, opts, res,
2834
item->command == TODO_REWORD);
2854
/* `current` will be incremented below */
2855
todo_list->current = -1;
2856
}
2857
+ } else if (item->command == TODO_LABEL) {
2858
+ if ((res = do_label(item->arg, item->arg_len)))
2859
+ reschedule = 1;
2860
+ } else if (item->command == TODO_RESET) {
2861
+ if ((res = do_reset(item->arg, item->arg_len, opts)))
2862
+ reschedule = 1;
2863
} else if (!is_noop(item->command))
2864
return error(_("unknown command %d"), item->command);
2865
2866
+ if (reschedule) {
2867
+ advise(_(rescheduled_advice),
2868
+ get_item_line_length(todo_list,
2869
+ todo_list->current),
2870
+ get_item_line(todo_list, todo_list->current));
2871
+ todo_list->current--;
2872
+ if (save_todo(todo_list, opts))
2873
+ return -1;
2874
+ }
2875
+
2876
todo_list->current++;
2877
if (res)
2878
return res;