mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
Merge branch 'sg/rebase-progress' into maint
Use "Erase in Line" CSI sequence that is already used in the editor support to clear cruft in the progress output. * sg/rebase-progress: progress: use term_clear_line() rebase: fix garbled progress display with '-x' pager: add a helper function to clear the last line in the terminal t3404: make the 'rebase.missingCommitsCheck=ignore' test more focused t3404: modernize here doc style
This commit is contained in:
commit
3e06e74e4c
1
cache.h
1
cache.h
@ -1759,6 +1759,7 @@ void setup_pager(void);
|
||||
int pager_in_use(void);
|
||||
extern int pager_use_color;
|
||||
int term_columns(void);
|
||||
void term_clear_line(void);
|
||||
int decimal_width(uintmax_t);
|
||||
int check_pager_config(const char *cmd);
|
||||
void prepare_pager_args(struct child_process *, const char *pager);
|
||||
|
6
editor.c
6
editor.c
@ -96,10 +96,10 @@ static int launch_specified_editor(const char *editor, const char *path,
|
||||
|
||||
if (print_waiting_for_editor && !is_terminal_dumb())
|
||||
/*
|
||||
* Go back to the beginning and erase the entire line to
|
||||
* avoid wasting the vertical space.
|
||||
* Erase the entire line to avoid wasting the
|
||||
* vertical space.
|
||||
*/
|
||||
fputs("\r\033[K", stderr);
|
||||
term_clear_line();
|
||||
}
|
||||
|
||||
if (!buffer)
|
||||
|
20
pager.c
20
pager.c
@ -177,6 +177,26 @@ int term_columns(void)
|
||||
return term_columns_at_startup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the entire line, leave cursor in first column.
|
||||
*/
|
||||
void term_clear_line(void)
|
||||
{
|
||||
if (is_terminal_dumb())
|
||||
/*
|
||||
* Fall back to print a terminal width worth of space
|
||||
* characters (hoping that the terminal is still as wide
|
||||
* as it was upon the first call to term_columns()).
|
||||
*/
|
||||
fprintf(stderr, "\r%*s\r", term_columns(), "");
|
||||
else
|
||||
/*
|
||||
* On non-dumb terminals use an escape sequence to clear
|
||||
* the whole line, no matter how wide the terminal.
|
||||
*/
|
||||
fputs("\r\033[K", stderr);
|
||||
}
|
||||
|
||||
/*
|
||||
* How many columns do we need to show this number in decimal?
|
||||
*/
|
||||
|
28
progress.c
28
progress.c
@ -88,7 +88,6 @@ static void display(struct progress *progress, uint64_t n, const char *done)
|
||||
const char *tp;
|
||||
struct strbuf *counters_sb = &progress->counters_sb;
|
||||
int show_update = 0;
|
||||
int last_count_len = counters_sb->len;
|
||||
|
||||
if (progress->delay && (!progress_update || --progress->delay))
|
||||
return;
|
||||
@ -116,26 +115,21 @@ static void display(struct progress *progress, uint64_t n, const char *done)
|
||||
if (show_update) {
|
||||
if (is_foreground_fd(fileno(stderr)) || done) {
|
||||
const char *eol = done ? done : "\r";
|
||||
size_t clear_len = counters_sb->len < last_count_len ?
|
||||
last_count_len - counters_sb->len + 1 :
|
||||
0;
|
||||
size_t progress_line_len = progress->title_len +
|
||||
counters_sb->len + 2;
|
||||
int cols = term_columns();
|
||||
|
||||
term_clear_line();
|
||||
if (progress->split) {
|
||||
fprintf(stderr, " %s%*s", counters_sb->buf,
|
||||
(int) clear_len, eol);
|
||||
} else if (!done && cols < progress_line_len) {
|
||||
clear_len = progress->title_len + 1 < cols ?
|
||||
cols - progress->title_len - 1 : 0;
|
||||
fprintf(stderr, "%s:%*s\n %s%s",
|
||||
progress->title, (int) clear_len, "",
|
||||
counters_sb->buf, eol);
|
||||
fprintf(stderr, " %s%s", counters_sb->buf,
|
||||
eol);
|
||||
} else if (!done &&
|
||||
/* The "+ 2" accounts for the ": ". */
|
||||
term_columns() < progress->title_len +
|
||||
counters_sb->len + 2) {
|
||||
fprintf(stderr, "%s:\n %s%s",
|
||||
progress->title, counters_sb->buf, eol);
|
||||
progress->split = 1;
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s%*s", progress->title,
|
||||
counters_sb->buf, (int) clear_len, eol);
|
||||
fprintf(stderr, "%s: %s%s", progress->title,
|
||||
counters_sb->buf, eol);
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
|
17
sequencer.c
17
sequencer.c
@ -3731,8 +3731,11 @@ static int pick_commits(struct repository *r,
|
||||
unlink(git_path_merge_head(the_repository));
|
||||
delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
|
||||
|
||||
if (item->command == TODO_BREAK)
|
||||
if (item->command == TODO_BREAK) {
|
||||
if (!opts->verbose)
|
||||
term_clear_line();
|
||||
return stopped_at_head(r);
|
||||
}
|
||||
}
|
||||
if (item->command <= TODO_SQUASH) {
|
||||
if (is_rebase_i(opts))
|
||||
@ -3754,11 +3757,14 @@ static int pick_commits(struct repository *r,
|
||||
}
|
||||
if (item->command == TODO_EDIT) {
|
||||
struct commit *commit = item->commit;
|
||||
if (!res)
|
||||
if (!res) {
|
||||
if (!opts->verbose)
|
||||
term_clear_line();
|
||||
fprintf(stderr,
|
||||
_("Stopped at %s... %.*s\n"),
|
||||
short_commit_name(commit),
|
||||
item->arg_len, arg);
|
||||
}
|
||||
return error_with_patch(r, commit,
|
||||
arg, item->arg_len, opts, res, !res);
|
||||
}
|
||||
@ -3796,6 +3802,8 @@ static int pick_commits(struct repository *r,
|
||||
int saved = *end_of_arg;
|
||||
struct stat st;
|
||||
|
||||
if (!opts->verbose)
|
||||
term_clear_line();
|
||||
*end_of_arg = '\0';
|
||||
res = do_exec(r, arg);
|
||||
*end_of_arg = saved;
|
||||
@ -3954,10 +3962,13 @@ cleanup_head_ref:
|
||||
}
|
||||
apply_autostash(opts);
|
||||
|
||||
if (!opts->quiet)
|
||||
if (!opts->quiet) {
|
||||
if (!opts->verbose)
|
||||
term_clear_line();
|
||||
fprintf(stderr,
|
||||
"Successfully rebased and updated %s.\n",
|
||||
head_ref.buf);
|
||||
}
|
||||
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&head_ref);
|
||||
|
@ -75,11 +75,10 @@ test_expect_success 'rebase --keep-empty' '
|
||||
test_line_count = 6 actual
|
||||
'
|
||||
|
||||
cat > expect <<EOF
|
||||
error: nothing to do
|
||||
EOF
|
||||
|
||||
test_expect_success 'rebase -i with empty HEAD' '
|
||||
cat >expect <<-\EOF &&
|
||||
error: nothing to do
|
||||
EOF
|
||||
set_fake_editor &&
|
||||
test_must_fail env FAKE_LINES="1 exec_true" git rebase -i HEAD^ >actual 2>&1 &&
|
||||
test_i18ncmp expect actual
|
||||
@ -237,25 +236,23 @@ test_expect_success 'exchange two commits' '
|
||||
test G = $(git cat-file commit HEAD | sed -ne \$p)
|
||||
'
|
||||
|
||||
cat > expect << EOF
|
||||
diff --git a/file1 b/file1
|
||||
index f70f10e..fd79235 100644
|
||||
--- a/file1
|
||||
+++ b/file1
|
||||
@@ -1 +1 @@
|
||||
-A
|
||||
+G
|
||||
EOF
|
||||
|
||||
cat > expect2 << EOF
|
||||
<<<<<<< HEAD
|
||||
D
|
||||
=======
|
||||
G
|
||||
>>>>>>> 5d18e54... G
|
||||
EOF
|
||||
|
||||
test_expect_success 'stop on conflicting pick' '
|
||||
cat >expect <<-\EOF &&
|
||||
diff --git a/file1 b/file1
|
||||
index f70f10e..fd79235 100644
|
||||
--- a/file1
|
||||
+++ b/file1
|
||||
@@ -1 +1 @@
|
||||
-A
|
||||
+G
|
||||
EOF
|
||||
cat >expect2 <<-\EOF &&
|
||||
<<<<<<< HEAD
|
||||
D
|
||||
=======
|
||||
G
|
||||
>>>>>>> 5d18e54... G
|
||||
EOF
|
||||
git tag new-branch1 &&
|
||||
set_fake_editor &&
|
||||
test_must_fail git rebase -i master &&
|
||||
@ -495,15 +492,14 @@ test_expect_success 'commit message retained after conflict' '
|
||||
git branch -D conflict-squash
|
||||
'
|
||||
|
||||
cat > expect-squash-fixup << EOF
|
||||
B
|
||||
|
||||
D
|
||||
|
||||
ONCE
|
||||
EOF
|
||||
|
||||
test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messages' '
|
||||
cat >expect-squash-fixup <<-\EOF &&
|
||||
B
|
||||
|
||||
D
|
||||
|
||||
ONCE
|
||||
EOF
|
||||
git checkout -b squash-fixup E &&
|
||||
base=$(git rev-parse HEAD~4) &&
|
||||
set_fake_editor &&
|
||||
@ -799,13 +795,12 @@ test_expect_success 'rebase -i can copy notes' '
|
||||
test "a note" = "$(git notes show HEAD)"
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
an earlier note
|
||||
|
||||
a note
|
||||
EOF
|
||||
|
||||
test_expect_success 'rebase -i can copy notes over a fixup' '
|
||||
cat >expect <<-\EOF &&
|
||||
an earlier note
|
||||
|
||||
a note
|
||||
EOF
|
||||
git reset --hard n3 &&
|
||||
git notes add -m"an earlier note" n2 &&
|
||||
set_fake_editor &&
|
||||
@ -1304,52 +1299,37 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' '
|
||||
actual
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
Warning: some commits may have been dropped accidentally.
|
||||
Dropped commits (newer to older):
|
||||
- $(git rev-list --pretty=oneline --abbrev-commit -1 master)
|
||||
To avoid this message, use "drop" to explicitly remove a commit.
|
||||
|
||||
Use 'git config rebase.missingCommitsCheck' to change the level of warnings.
|
||||
The possible behaviours are: ignore, warn, error.
|
||||
|
||||
Rebasing (1/4)
|
||||
Rebasing (2/4)
|
||||
Rebasing (3/4)
|
||||
Rebasing (4/4)
|
||||
Successfully rebased and updated refs/heads/missing-commit.
|
||||
EOF
|
||||
|
||||
cr_to_nl () {
|
||||
tr '\015' '\012'
|
||||
}
|
||||
|
||||
test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' '
|
||||
cat >expect <<-EOF &&
|
||||
Warning: some commits may have been dropped accidentally.
|
||||
Dropped commits (newer to older):
|
||||
- $(git rev-list --pretty=oneline --abbrev-commit -1 master)
|
||||
To avoid this message, use "drop" to explicitly remove a commit.
|
||||
EOF
|
||||
test_config rebase.missingCommitsCheck warn &&
|
||||
rebase_setup_and_clean missing-commit &&
|
||||
set_fake_editor &&
|
||||
FAKE_LINES="1 2 3 4" \
|
||||
git rebase -i --root 2>actual.2 &&
|
||||
cr_to_nl <actual.2 >actual &&
|
||||
head -n4 actual.2 >actual &&
|
||||
test_i18ncmp expect actual &&
|
||||
test D = $(git cat-file commit HEAD | sed -ne \$p)
|
||||
'
|
||||
|
||||
cat >expect <<EOF
|
||||
Warning: some commits may have been dropped accidentally.
|
||||
Dropped commits (newer to older):
|
||||
- $(git rev-list --pretty=oneline --abbrev-commit -1 master)
|
||||
- $(git rev-list --pretty=oneline --abbrev-commit -1 master~2)
|
||||
To avoid this message, use "drop" to explicitly remove a commit.
|
||||
|
||||
Use 'git config rebase.missingCommitsCheck' to change the level of warnings.
|
||||
The possible behaviours are: ignore, warn, error.
|
||||
|
||||
You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
|
||||
Or you can abort the rebase with 'git rebase --abort'.
|
||||
EOF
|
||||
|
||||
test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
|
||||
cat >expect <<-EOF &&
|
||||
Warning: some commits may have been dropped accidentally.
|
||||
Dropped commits (newer to older):
|
||||
- $(git rev-list --pretty=oneline --abbrev-commit -1 master)
|
||||
- $(git rev-list --pretty=oneline --abbrev-commit -1 master~2)
|
||||
To avoid this message, use "drop" to explicitly remove a commit.
|
||||
|
||||
Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings.
|
||||
The possible behaviours are: ignore, warn, error.
|
||||
|
||||
You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''.
|
||||
Or you can abort the rebase with '\''git rebase --abort'\''.
|
||||
EOF
|
||||
test_config rebase.missingCommitsCheck error &&
|
||||
rebase_setup_and_clean missing-commit &&
|
||||
set_fake_editor &&
|
||||
|
@ -49,7 +49,7 @@ create_expected_success_interactive () {
|
||||
$(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
|
||||
HEAD is now at $(git rev-parse --short feature-branch) third commit
|
||||
Rebasing (1/2)QRebasing (2/2)QApplied autostash.
|
||||
Successfully rebased and updated refs/heads/rebased-feature-branch.
|
||||
Q QSuccessfully rebased and updated refs/heads/rebased-feature-branch.
|
||||
EOF
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ create_expected_failure_interactive () {
|
||||
Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts.
|
||||
Your changes are safe in the stash.
|
||||
You can run "git stash pop" or "git stash drop" at any time.
|
||||
Successfully rebased and updated refs/heads/rebased-feature-branch.
|
||||
Q QSuccessfully rebased and updated refs/heads/rebased-feature-branch.
|
||||
EOF
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,7 @@ test_expect_success TTY 'push shows progress when stderr is a tty' '
|
||||
cd "$ROOT_PATH"/test_repo_clone &&
|
||||
test_commit noisy &&
|
||||
test_terminal git push >output 2>&1 &&
|
||||
test_i18ngrep "^Writing objects" output
|
||||
test_i18ngrep "Writing objects" output
|
||||
'
|
||||
|
||||
test_expect_success TTY 'push --quiet silences status and progress' '
|
||||
@ -277,7 +277,7 @@ test_expect_success TTY 'push --no-progress silences progress but not status' '
|
||||
test_commit no-progress &&
|
||||
test_terminal git push --no-progress >output 2>&1 &&
|
||||
test_i18ngrep "^To http" output &&
|
||||
test_i18ngrep ! "^Writing objects" output
|
||||
test_i18ngrep ! "Writing objects" output
|
||||
'
|
||||
|
||||
test_expect_success 'push --progress shows progress to non-tty' '
|
||||
@ -285,7 +285,7 @@ test_expect_success 'push --progress shows progress to non-tty' '
|
||||
test_commit progress &&
|
||||
git push --progress >output 2>&1 &&
|
||||
test_i18ngrep "^To http" output &&
|
||||
test_i18ngrep "^Writing objects" output
|
||||
test_i18ngrep "Writing objects" output
|
||||
'
|
||||
|
||||
test_expect_success 'http push gives sane defaults to reflog' '
|
||||
|
Loading…
Reference in New Issue
Block a user