commit - ed611b60fe058e4f6bd245b9bc55cd450763c6ad
commit + 070c80a59d5048ca05990df52d7993f3015c2ee4
blob - 9ca39428e1178142919dfd78df6b0381cda7f8b6
blob + fdb4ef70a58be2c0ebaee1bc320ee9ba9a5c82fe
--- got/got.1
+++ got/got.1
.Tg he
.It Xo
.Cm histedit
-.Op Fl aceflmX
+.Op Fl acdeflmX
.Op Fl F Ar histedit-script
.Op Ar branch
.Xc
If this option is used, no other command-line arguments are allowed.
.It Fl c
Continue an interrupted histedit operation.
+If this option is used, no other command-line arguments are allowed.
+.It Fl d
+Drop all commits.
+This option is a quick equivalent to a histedit script which drops all
+commits.
+The
+.Fl d
+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 e
Interrupt the histedit operation for editing after merging each commit.
blob - abb9d74080d4e2fa0d17b4bc6d3c69691b3fdb2f
blob + 26f94faab531e5b6bfa3c5e7cf0f1d547a900326
--- got/got.c
+++ got/got.c
__dead static void
usage_histedit(void)
{
- fprintf(stderr, "usage: %s histedit [-aceflmX] [-F histedit-script] "
+ fprintf(stderr, "usage: %s histedit [-acdeflmX] [-F histedit-script] "
"[branch]\n", getprogname());
exit(1);
}
static const struct got_error *
histedit_write_commit_list(struct got_object_id_queue *commits,
- FILE *f, int edit_logmsg_only, int fold_only, int edit_only,
- struct got_repository *repo)
+ FILE *f, int edit_logmsg_only, int fold_only, int drop_only,
+ int edit_only, struct got_repository *repo)
{
const struct got_error *err = NULL;
struct got_object_qid *qid;
STAILQ_FOREACH(qid, commits, entry) {
histedit_cmd = got_histedit_cmds[0].name;
- if (edit_only)
+ if (drop_only)
+ histedit_cmd = "drop";
+ else if (edit_only)
histedit_cmd = "edit";
else if (fold_only && STAILQ_NEXT(qid, entry) != NULL)
histedit_cmd = "fold";
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, int edit_only,
+ int edit_logmsg_only, int fold_only, int drop_only, int edit_only,
struct got_repository *repo)
{
const struct got_error *err;
goto done;
err = histedit_write_commit_list(commits, f, edit_logmsg_only,
- fold_only, edit_only, repo);
+ fold_only, drop_only, edit_only, repo);
if (err)
goto done;
- if (edit_logmsg_only || fold_only || edit_only) {
+ if (drop_only || edit_logmsg_only || fold_only || edit_only) {
rewind(f);
err = histedit_parse_list(histedit_cmds, f, repo);
} else {
} else if (resp == 'r') {
histedit_free_list(histedit_cmds);
err = histedit_edit_script(histedit_cmds,
- commits, branch_name, 0, 0, 0, repo);
+ commits, branch_name, 0, 0, 0, 0, repo);
if (err) {
if (err->code != GOT_ERR_HISTEDIT_SYNTAX &&
err->code != GOT_ERR_HISTEDIT_CMD)
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, edit_only = 0;
+ int drop_only = 0, 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;
TAILQ_INIT(&merged_paths);
memset(&upa, 0, sizeof(upa));
- while ((ch = getopt(argc, argv, "aceF:flmX")) != -1) {
+ while ((ch = getopt(argc, argv, "acdeF:flmX")) != -1) {
switch (ch) {
case 'a':
abort_edit = 1;
break;
case 'c':
continue_edit = 1;
+ break;
+ case 'd':
+ drop_only = 1;
break;
case 'e':
edit_only = 1;
option_conflict('e', 'm');
if (edit_script_path && edit_only)
option_conflict('F', 'e');
+ if (drop_only && abort_edit)
+ option_conflict('d', 'a');
+ if (drop_only && continue_edit)
+ option_conflict('d', 'c');
+ if (drop_only && edit_logmsg_only)
+ option_conflict('d', 'm');
+ if (drop_only && edit_only)
+ option_conflict('d', 'e');
+ if (drop_only && edit_script_path)
+ option_conflict('d', 'F');
+ if (drop_only && fold_only)
+ option_conflict('d', 'f');
if (list_backups) {
if (abort_edit)
option_conflict('l', 'a');
option_conflict('l', 'F');
if (edit_logmsg_only)
option_conflict('l', 'm');
+ if (drop_only)
+ option_conflict('l', 'd');
if (fold_only)
option_conflict('l', 'f');
if (edit_only)
option_conflict('X', 'a');
if (continue_edit)
option_conflict('X', 'c');
+ if (drop_only)
+ option_conflict('X', 'd');
if (edit_script_path)
option_conflict('X', 'F');
if (edit_logmsg_only)
"histedit operation is in progress in this "
"work tree and must be continued or aborted "
"before the -m option can be used");
+ goto done;
+ }
+ if (edit_in_progress && drop_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 -d option can be used");
goto done;
}
if (edit_in_progress && fold_only) {
branch_name += 11;
error = histedit_edit_script(&histedit_cmds, &commits,
branch_name, edit_logmsg_only, fold_only,
- edit_only, repo);
+ drop_only, edit_only, repo);
if (error) {
got_worktree_histedit_abort(worktree, fileindex,
repo, branch, base_commit_id,
blob - 0df4c2aa44205dec456271bfe781335ed70669e9
blob + a2f15eebb25a5cb8f1f524fcda7e9545a66598bf
--- regress/cmdline/histedit.sh
+++ regress/cmdline/histedit.sh
test_done "$testroot" "$ret"
}
+
+test_histedit_drop_only() {
+ local testroot=`test_init histedit_drop_only`
+
+ local orig_commit=`git_show_head $testroot/repo`
+ local drop="-> drop commit:"
+ local dropmsg="commit changes to drop"
+
+ 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 "$dropmsg 1"
+ local drop_commit1=`git_show_head $testroot/repo`
+
+ echo "modified zeta on master" > $testroot/repo/epsilon/zeta
+
+ git_commit $testroot/repo -m "$dropmsg 2"
+ local drop_commit2=`git_show_head $testroot/repo`
+
+ echo "modified delta on master" > $testroot/repo/gamma/delta
+
+ git_commit $testroot/repo -m "$dropmsg 3"
+ local drop_commit3=`git_show_head $testroot/repo`
+
+ got checkout -c $orig_commit $testroot/repo $testroot/wt > /dev/null
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ (cd $testroot/wt && got histedit -d > $testroot/stdout)
+ local new_commit1=`git_show_head $testroot/repo`
+
+ local short_commit1=`trim_obj_id 28 $drop_commit1`
+ local short_commit2=`trim_obj_id 28 $drop_commit2`
+ local short_commit3=`trim_obj_id 28 $drop_commit3`
+
+ echo "$short_commit1 $drop $dropmsg 1" > $testroot/stdout.expected
+ echo "$short_commit2 $drop $dropmsg 2" >> $testroot/stdout.expected
+ echo "$short_commit3 $drop $dropmsg 3" >> $testroot/stdout.expected
+ echo "Switching work tree to refs/heads/master" \
+ >> $testroot/stdout.expected
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "alpha" > $testroot/content.expected
+ cat $testroot/wt/alpha > $testroot/content
+ cmp -s $testroot/content.expected $testroot/content
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/content.expected $testroot/content
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "zeta" > $testroot/content.expected
+ cat $testroot/wt/epsilon/zeta > $testroot/content
+ cmp -s $testroot/content.expected $testroot/content
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/content.expected $testroot/content
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ echo "delta" > $testroot/content.expected
+ cat $testroot/wt/gamma/delta > $testroot/content
+ cmp -s $testroot/content.expected $testroot/content
+ ret=$?
+ if [ $ret -ne 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 should be restored" >&2
+ test_done "$testroot" "1"
+ return 1
+ fi
+
+ if [ -e $testroot/wt/new ]; then
+ echo "new file should no longer exist" >&2
+ 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 -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ (cd $testroot/wt && got log | grep ^commit > $testroot/stdout)
+ echo "commit $orig_commit (master)" > $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
test_parseargs "$@"
run_test test_histedit_no_op
run_test test_histedit_swap
run_test test_histedit_resets_committer
run_test test_histedit_umask
run_test test_histedit_mesg_filemode_change
+run_test test_histedit_drop_only