commit c50a74557db04e5ab02a1b0c53cb4fbdd64088ac from: Stefan Sperling via: Thomas Adam date: Mon Oct 04 07:53:31 2021 UTC add histedit -e option which runs the 'edit' script command for every commit ok jrick commit - 839511b2e2ef1858aa18758d757677b5b8af7269 commit + c50a74557db04e5ab02a1b0c53cb4fbdd64088ac blob - 237c161ab95271094fff0f6ca83316e7b1d60e7d blob + 450e4baab5541257e9c371762a5fe893fa1c19bb --- got/got.1 +++ got/got.1 @@ -1863,7 +1863,7 @@ None of the other options can be used together with .It Cm rb Short alias for .Cm rebase . -.It Cm histedit Oo Fl a Oc Oo Fl c Oc Oo Fl f Oc Oo Fl F Ar histedit-script Oc Oo Fl m Oc Oo Fl l Oc Oo Fl X Oc Op Ar branch +.It Cm histedit Oo Fl a Oc Oo Fl c Oc Oo Fl e Oc Oo Fl f Oc Oo Fl F Ar histedit-script Oc Oo Fl m Oc Oo Fl l Oc Oo Fl X Oc Op Ar branch Edit commit history between the work tree's current base commit and the tip commit of the work tree's current branch. .Pp @@ -2011,6 +2011,15 @@ If this option is used, no other command-line argument .It Fl c Continue an interrupted histedit operation. If this option is used, no other command-line arguments are allowed. +.It Fl e +Interrupt the histedit operation for editing after merging each commit. +This option is a quick equivalent to a histedit script which uses the +.Cm edit +command for all commits. +The +.Fl e +option can only be used when starting a new histedit operation. +If this option is used, no other command-line arguments are allowed. .It Fl f Fold all commits into a single commit. This option is a quick equivalent to a histedit script which folds all blob - a7a3f56bbcdf1e56c782beb4100d8d513f2ec999 blob + b375b79361d8973852cd690a8972093ca55267d0 --- got/got.c +++ got/got.c @@ -9162,7 +9162,7 @@ done: __dead static void usage_histedit(void) { - fprintf(stderr, "usage: %s histedit [-a] [-c] [-f] " + fprintf(stderr, "usage: %s histedit [-a] [-c] [-e] [-f] " "[-F histedit-script] [-m] [-l] [-X] [branch]\n", getprogname()); exit(1); @@ -9230,7 +9230,8 @@ done: static const struct got_error * histedit_write_commit_list(struct got_object_id_queue *commits, - FILE *f, int edit_logmsg_only, int fold_only, struct got_repository *repo) + FILE *f, int edit_logmsg_only, int fold_only, int edit_only, + struct got_repository *repo) { const struct got_error *err = NULL; struct got_object_qid *qid; @@ -9241,7 +9242,9 @@ histedit_write_commit_list(struct got_object_id_queue STAILQ_FOREACH(qid, commits, entry) { histedit_cmd = got_histedit_cmds[0].name; - if (fold_only && STAILQ_NEXT(qid, entry) != NULL) + if (edit_only) + histedit_cmd = "edit"; + else if (fold_only && STAILQ_NEXT(qid, entry) != NULL) histedit_cmd = "fold"; err = histedit_write_commit(qid->id, histedit_cmd, f, repo); if (err) @@ -9655,7 +9658,8 @@ histedit_edit_list_retry(struct got_histedit_list *, c static const struct got_error * histedit_edit_script(struct got_histedit_list *histedit_cmds, struct got_object_id_queue *commits, const char *branch_name, - int edit_logmsg_only, int fold_only, struct got_repository *repo) + int edit_logmsg_only, int fold_only, int edit_only, + struct got_repository *repo) { const struct got_error *err; FILE *f = NULL; @@ -9670,11 +9674,11 @@ histedit_edit_script(struct got_histedit_list *histedi goto done; err = histedit_write_commit_list(commits, f, edit_logmsg_only, - fold_only, repo); + fold_only, edit_only, repo); if (err) goto done; - if (edit_logmsg_only || fold_only) { + if (edit_logmsg_only || fold_only || edit_only) { rewind(f); err = histedit_parse_list(histedit_cmds, f, repo); } else { @@ -9805,7 +9809,7 @@ histedit_edit_list_retry(struct got_histedit_list *his } else if (resp == 'r') { histedit_free_list(histedit_cmds); err = histedit_edit_script(histedit_cmds, - commits, branch_name, 0, 0, repo); + commits, branch_name, 0, 0, 0, repo); if (err) { if (err->code != GOT_ERR_HISTEDIT_SYNTAX && err->code != GOT_ERR_HISTEDIT_CMD) @@ -9997,7 +10001,7 @@ cmd_histedit(int argc, char *argv[]) int ch, rebase_in_progress = 0, merge_in_progress = 0; struct got_update_progress_arg upa; int edit_in_progress = 0, abort_edit = 0, continue_edit = 0; - int edit_logmsg_only = 0, fold_only = 0; + int edit_logmsg_only = 0, fold_only = 0, edit_only = 0; int list_backups = 0, delete_backups = 0; const char *edit_script_path = NULL; struct got_object_id_queue commits; @@ -10012,7 +10016,7 @@ cmd_histedit(int argc, char *argv[]) TAILQ_INIT(&merged_paths); memset(&upa, 0, sizeof(upa)); - while ((ch = getopt(argc, argv, "acfF:mlX")) != -1) { + while ((ch = getopt(argc, argv, "acefF:mlX")) != -1) { switch (ch) { case 'a': abort_edit = 1; @@ -10020,6 +10024,9 @@ cmd_histedit(int argc, char *argv[]) case 'c': continue_edit = 1; break; + case 'e': + edit_only = 1; + break; case 'f': fold_only = 1; break; @@ -10065,6 +10072,14 @@ cmd_histedit(int argc, char *argv[]) option_conflict('f', 'm'); if (edit_script_path && fold_only) option_conflict('F', 'f'); + if (abort_edit && edit_only) + option_conflict('a', 'e'); + if (continue_edit && edit_only) + option_conflict('c', 'e'); + if (edit_only && edit_logmsg_only) + option_conflict('e', 'm'); + if (edit_script_path && edit_only) + option_conflict('F', 'e'); if (list_backups) { if (abort_edit) option_conflict('l', 'a'); @@ -10076,6 +10091,8 @@ cmd_histedit(int argc, char *argv[]) option_conflict('l', 'm'); if (fold_only) option_conflict('l', 'f'); + if (edit_only) + option_conflict('l', 'e'); if (delete_backups) option_conflict('l', 'X'); if (argc != 0 && argc != 1) @@ -10091,6 +10108,8 @@ cmd_histedit(int argc, char *argv[]) option_conflict('X', 'm'); if (fold_only) option_conflict('X', 'f'); + if (edit_only) + option_conflict('X', 'e'); if (list_backups) option_conflict('X', 'l'); if (argc != 0 && argc != 1) @@ -10181,6 +10200,13 @@ cmd_histedit(int argc, char *argv[]) "before the -f option can be used"); goto done; } + if (edit_in_progress && edit_only) { + error = got_error_msg(GOT_ERR_HISTEDIT_BUSY, + "histedit operation is in progress in this " + "work tree and must be continued or aborted " + "before the -e option can be used"); + goto done; + } if (edit_in_progress && abort_edit) { error = got_worktree_histedit_continue(&resume_commit_id, @@ -10316,7 +10342,8 @@ cmd_histedit(int argc, char *argv[]) if (strncmp(branch_name, "refs/heads/", 11) == 0) branch_name += 11; error = histedit_edit_script(&histedit_cmds, &commits, - branch_name, edit_logmsg_only, fold_only, repo); + branch_name, edit_logmsg_only, fold_only, + edit_only, repo); if (error) { got_worktree_histedit_abort(worktree, fileindex, repo, branch, base_commit_id, blob - 24ae6d99cf14c28bd331ff1aebba74a90761a951 blob + ec9e48a654c56cc96e8bb36e57a8690cc98c76c0 --- regress/cmdline/histedit.sh +++ regress/cmdline/histedit.sh @@ -1757,6 +1757,153 @@ EOF (cd $testroot/wt && got log | grep ^commit > $testroot/stdout) echo "commit $new_commit1 (master)" > $testroot/stdout.expected + echo "commit $orig_commit" >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + fi + test_done "$testroot" "$ret" +} + +test_histedit_edit_only() { + local testroot=`test_init histedit_edit_only` + + local orig_commit=`git_show_head $testroot/repo` + + echo "modified alpha on master" > $testroot/repo/alpha + (cd $testroot/repo && git rm -q beta) + echo "new file on master" > $testroot/repo/epsilon/new + (cd $testroot/repo && git add epsilon/new) + git_commit $testroot/repo -m "committing changes" + local old_commit1=`git_show_head $testroot/repo` + + echo "modified zeta on master" > $testroot/repo/epsilon/zeta + git_commit $testroot/repo -m "committing to zeta on master" + local old_commit2=`git_show_head $testroot/repo` + + got checkout -c $orig_commit $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && got histedit -e > $testroot/stdout) + + local short_old_commit1=`trim_obj_id 28 $old_commit1` + local short_old_commit2=`trim_obj_id 28 $old_commit2` + + echo "G alpha" > $testroot/stdout.expected + echo "D beta" >> $testroot/stdout.expected + echo "A epsilon/new" >> $testroot/stdout.expected + echo "Stopping histedit for amending commit $old_commit1" \ + >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "edited modified alpha on master" > $testroot/wt/alpha + + cat > $testroot/editor.sh < $testroot/stdout) + + local new_commit1=$(cd $testroot/wt && got info | \ + grep '^work tree base commit: ' | cut -d: -f2 | tr -d ' ') + local short_new_commit1=`trim_obj_id 28 $new_commit1` + + echo -n "$short_old_commit1 -> $short_new_commit1: " \ + > $testroot/stdout.expected + echo "committing edited changes 1" >> $testroot/stdout.expected + echo "G epsilon/zeta" >> $testroot/stdout.expected + echo "Stopping histedit for amending commit $old_commit2" \ + >> $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "edited zeta on master" > $testroot/wt/epsilon/zeta + + cat > $testroot/editor.sh < $testroot/stdout) + + local new_commit2=`git_show_head $testroot/repo` + local short_new_commit2=`trim_obj_id 28 $new_commit2` + + echo -n "$short_old_commit2 -> $short_new_commit2: " \ + > $testroot/stdout.expected + echo "committing edited changes 2" >> $testroot/stdout.expected + echo "Switching work tree to refs/heads/master" \ + >> $testroot/stdout.expected + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "edited modified alpha on master" > $testroot/content.expected + cat $testroot/wt/alpha > $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + if [ -e $testroot/wt/beta ]; then + echo "removed file beta still exists on disk" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo "new file on master" > $testroot/content.expected + cat $testroot/wt/epsilon/new > $testroot/content + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && got status > $testroot/stdout) + + echo -n > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + (cd $testroot/wt && got log -l3 | grep ^commit > $testroot/stdout) + echo "commit $new_commit2 (master)" > $testroot/stdout.expected + echo "commit $new_commit1" >> $testroot/stdout.expected echo "commit $orig_commit" >> $testroot/stdout.expected cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" @@ -1784,3 +1931,4 @@ run_test test_histedit_duplicate_commit_in_script run_test test_histedit_fold_add_delete run_test test_histedit_fold_only run_test test_histedit_fold_only_empty_logmsg +run_test test_histedit_edit_only