status: better advices when splitting a commit (during rebase -i)

Add new informative help messages at the output of 'git status' when the user is splitting a commit. The code figures this state by comparing the contents of the following files in the .git/ directory: - HEAD - ORIG_HEAD - rebase-merge/amend - rebase-merge/orig-head Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr> Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr> Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr> Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr> Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr> Signed-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Lucien Kong committed Jun 10, 2012 at 13:17 UTC 2d1ccebae41541946ddd7e32f291f3c8983feea9
2 files changed +329
t/t7512-status-help.sh
+277
@@ -196,6 +196,283 @@ test_expect_success 'status when rebasing -i in edit mode' '
196 '
197
198
199 +test_expect_success 'status when splitting a commit' '
200 + git reset --hard master &&
201 + git checkout -b split_commit &&
202 + test_commit one_split main.txt one &&
203 + test_commit two_split main.txt two &&
204 + test_commit three_split main.txt three &&
205 + test_commit four_split main.txt four &&
206 + FAKE_LINES="1 edit 2 3" &&
207 + export FAKE_LINES &&
208 + test_when_finished "git rebase --abort" &&
209 + git rebase -i HEAD~3 &&
210 + git reset HEAD^ &&
211 + cat >expected <<-\EOF &&
212 + # Not currently on any branch.
213 + # You are currently splitting a commit during a rebase.
214 + # (Once your working directory is clean, run "git rebase --continue")
215 + #
216 + # Changes not staged for commit:
217 + # (use "git add <file>..." to update what will be committed)
218 + # (use "git checkout -- <file>..." to discard changes in working directory)
219 + #
220 + # modified: main.txt
221 + #
222 + no changes added to commit (use "git add" and/or "git commit -a")
223 + EOF
224 + git status --untracked-files=no >actual &&
225 + test_i18ncmp expected actual
226 +'
227 +
228 +
229 +test_expect_success 'status after editing the last commit with --amend during a rebase -i' '
230 + git reset --hard master &&
231 + git checkout -b amend_last &&
232 + test_commit one_amend main.txt one &&
233 + test_commit two_amend main.txt two &&
234 + test_commit three_amend main.txt three &&
235 + test_commit four_amend main.txt four &&
236 + FAKE_LINES="1 2 edit 3" &&
237 + export FAKE_LINES &&
238 + test_when_finished "git rebase --abort" &&
239 + git rebase -i HEAD~3 &&
240 + git commit --amend -m "foo" &&
241 + cat >expected <<-\EOF &&
242 + # Not currently on any branch.
243 + # You are currently editing a commit during a rebase.
244 + # (use "git commit --amend" to amend the current commit)
245 + # (use "git rebase --continue" once you are satisfied with your changes)
246 + #
247 + nothing to commit (use -u to show untracked files)
248 + EOF
249 + git status --untracked-files=no >actual &&
250 + test_i18ncmp expected actual
251 +'
252 +
253 +
254 +test_expect_success 'prepare for several edits' '
255 + git reset --hard master &&
256 + git checkout -b several_edits &&
257 + test_commit one_edits main.txt one &&
258 + test_commit two_edits main.txt two &&
259 + test_commit three_edits main.txt three &&
260 + test_commit four_edits main.txt four
261 +'
262 +
263 +
264 +test_expect_success 'status: (continue first edit) second edit' '
265 + FAKE_LINES="edit 1 edit 2 3" &&
266 + export FAKE_LINES &&
267 + test_when_finished "git rebase --abort" &&
268 + git rebase -i HEAD~3 &&
269 + git rebase --continue &&
270 + cat >expected <<-\EOF &&
271 + # Not currently on any branch.
272 + # You are currently editing a commit during a rebase.
273 + # (use "git commit --amend" to amend the current commit)
274 + # (use "git rebase --continue" once you are satisfied with your changes)
275 + #
276 + nothing to commit (use -u to show untracked files)
277 + EOF
278 + git status --untracked-files=no >actual &&
279 + test_i18ncmp expected actual
280 +'
281 +
282 +
283 +test_expect_success 'status: (continue first edit) second edit and split' '
284 + git reset --hard several_edits &&
285 + FAKE_LINES="edit 1 edit 2 3" &&
286 + export FAKE_LINES &&
287 + test_when_finished "git rebase --abort" &&
288 + git rebase -i HEAD~3 &&
289 + git rebase --continue &&
290 + git reset HEAD^ &&
291 + cat >expected <<-\EOF &&
292 + # Not currently on any branch.
293 + # You are currently splitting a commit during a rebase.
294 + # (Once your working directory is clean, run "git rebase --continue")
295 + #
296 + # Changes not staged for commit:
297 + # (use "git add <file>..." to update what will be committed)
298 + # (use "git checkout -- <file>..." to discard changes in working directory)
299 + #
300 + # modified: main.txt
301 + #
302 + no changes added to commit (use "git add" and/or "git commit -a")
303 + EOF
304 + git status --untracked-files=no >actual &&
305 + test_i18ncmp expected actual
306 +'
307 +
308 +
309 +test_expect_success 'status: (continue first edit) second edit and amend' '
310 + git reset --hard several_edits &&
311 + FAKE_LINES="edit 1 edit 2 3" &&
312 + export FAKE_LINES &&
313 + test_when_finished "git rebase --abort" &&
314 + git rebase -i HEAD~3 &&
315 + git rebase --continue &&
316 + git commit --amend -m "foo" &&
317 + cat >expected <<-\EOF &&
318 + # Not currently on any branch.
319 + # You are currently editing a commit during a rebase.
320 + # (use "git commit --amend" to amend the current commit)
321 + # (use "git rebase --continue" once you are satisfied with your changes)
322 + #
323 + nothing to commit (use -u to show untracked files)
324 + EOF
325 + git status --untracked-files=no >actual &&
326 + test_i18ncmp expected actual
327 +'
328 +
329 +
330 +test_expect_success 'status: (amend first edit) second edit' '
331 + git reset --hard several_edits &&
332 + FAKE_LINES="edit 1 edit 2 3" &&
333 + export FAKE_LINES &&
334 + test_when_finished "git rebase --abort" &&
335 + git rebase -i HEAD~3 &&
336 + git commit --amend -m "a" &&
337 + git rebase --continue &&
338 + cat >expected <<-\EOF &&
339 + # Not currently on any branch.
340 + # You are currently editing a commit during a rebase.
341 + # (use "git commit --amend" to amend the current commit)
342 + # (use "git rebase --continue" once you are satisfied with your changes)
343 + #
344 + nothing to commit (use -u to show untracked files)
345 + EOF
346 + git status --untracked-files=no >actual &&
347 + test_i18ncmp expected actual
348 +'
349 +
350 +
351 +test_expect_success 'status: (amend first edit) second edit and split' '
352 + git reset --hard several_edits &&
353 + FAKE_LINES="edit 1 edit 2 3" &&
354 + export FAKE_LINES &&
355 + test_when_finished "git rebase --abort" &&
356 + git rebase -i HEAD~3 &&
357 + git commit --amend -m "b" &&
358 + git rebase --continue &&
359 + git reset HEAD^ &&
360 + cat >expected <<-\EOF &&
361 + # Not currently on any branch.
362 + # You are currently splitting a commit during a rebase.
363 + # (Once your working directory is clean, run "git rebase --continue")
364 + #
365 + # Changes not staged for commit:
366 + # (use "git add <file>..." to update what will be committed)
367 + # (use "git checkout -- <file>..." to discard changes in working directory)
368 + #
369 + # modified: main.txt
370 + #
371 + no changes added to commit (use "git add" and/or "git commit -a")
372 + EOF
373 + git status --untracked-files=no >actual &&
374 + test_i18ncmp expected actual
375 +'
376 +
377 +
378 +test_expect_success 'status: (amend first edit) second edit and amend' '
379 + git reset --hard several_edits &&
380 + FAKE_LINES="edit 1 edit 2 3" &&
381 + export FAKE_LINES &&
382 + test_when_finished "git rebase --abort" &&
383 + git rebase -i HEAD~3 &&
384 + git commit --amend -m "c" &&
385 + git rebase --continue &&
386 + git commit --amend -m "d" &&
387 + cat >expected <<-\EOF &&
388 + # Not currently on any branch.
389 + # You are currently editing a commit during a rebase.
390 + # (use "git commit --amend" to amend the current commit)
391 + # (use "git rebase --continue" once you are satisfied with your changes)
392 + #
393 + nothing to commit (use -u to show untracked files)
394 + EOF
395 + git status --untracked-files=no >actual &&
396 + test_i18ncmp expected actual
397 +'
398 +
399 +
400 +test_expect_success 'status: (split first edit) second edit' '
401 + git reset --hard several_edits &&
402 + FAKE_LINES="edit 1 edit 2 3" &&
403 + export FAKE_LINES &&
404 + test_when_finished "git rebase --abort" &&
405 + git rebase -i HEAD~3 &&
406 + git reset HEAD^ &&
407 + git add main.txt &&
408 + git commit -m "e" &&
409 + git rebase --continue &&
410 + cat >expected <<-\EOF &&
411 + # Not currently on any branch.
412 + # You are currently editing a commit during a rebase.
413 + # (use "git commit --amend" to amend the current commit)
414 + # (use "git rebase --continue" once you are satisfied with your changes)
415 + #
416 + nothing to commit (use -u to show untracked files)
417 + EOF
418 + git status --untracked-files=no >actual &&
419 + test_i18ncmp expected actual
420 +'
421 +
422 +
423 +test_expect_success 'status: (split first edit) second edit and split' '
424 + git reset --hard several_edits &&
425 + FAKE_LINES="edit 1 edit 2 3" &&
426 + export FAKE_LINES &&
427 + test_when_finished "git rebase --abort" &&
428 + git rebase -i HEAD~3 &&
429 + git reset HEAD^ &&
430 + git add main.txt &&
431 + git commit --amend -m "f" &&
432 + git rebase --continue &&
433 + git reset HEAD^ &&
434 + cat >expected <<-\EOF &&
435 + # Not currently on any branch.
436 + # You are currently splitting a commit during a rebase.
437 + # (Once your working directory is clean, run "git rebase --continue")
438 + #
439 + # Changes not staged for commit:
440 + # (use "git add <file>..." to update what will be committed)
441 + # (use "git checkout -- <file>..." to discard changes in working directory)
442 + #
443 + # modified: main.txt
444 + #
445 + no changes added to commit (use "git add" and/or "git commit -a")
446 + EOF
447 + git status --untracked-files=no >actual &&
448 + test_i18ncmp expected actual
449 +'
450 +
451 +
452 +test_expect_success 'status: (split first edit) second edit and amend' '
453 + git reset --hard several_edits &&
454 + FAKE_LINES="edit 1 edit 2 3" &&
455 + export FAKE_LINES &&
456 + test_when_finished "git rebase --abort" &&
457 + git rebase -i HEAD~3 &&
458 + git reset HEAD^ &&
459 + git add main.txt &&
460 + git commit --amend -m "g" &&
461 + git rebase --continue &&
462 + git commit --amend -m "h" &&
463 + cat >expected <<-\EOF &&
464 + # Not currently on any branch.
465 + # You are currently editing a commit during a rebase.
466 + # (use "git commit --amend" to amend the current commit)
467 + # (use "git rebase --continue" once you are satisfied with your changes)
468 + #
469 + nothing to commit (use -u to show untracked files)
470 + EOF
471 + git status --untracked-files=no >actual &&
472 + test_i18ncmp expected actual
473 +'
474 +
475 +
476 test_expect_success 'prepare am_session' '
477 git reset --hard master &&
478 git checkout -b am_session &&
wt-status.c
+52
@@ -12,6 +12,7 @@
12 #include "refs.h"
13 #include "submodule.h"
14 #include "column.h"
15 +#include "strbuf.h"
16
17 static char default_wt_status_colors[][COLOR_MAXLEN] = {
18 GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */
@@ -817,6 +818,52 @@ static void show_am_in_progress(struct wt_status *s,
818 wt_status_print_trailer(s);
819 }
820
821 +static char *read_line_from_git_path(const char *filename)
822 +{
823 + struct strbuf buf = STRBUF_INIT;
824 + FILE *fp = fopen(git_path("%s", filename), "r");
825 + if (!fp) {
826 + strbuf_release(&buf);
827 + return NULL;
828 + }
829 + strbuf_getline(&buf, fp, '\n');
830 + if (!fclose(fp)) {
831 + return strbuf_detach(&buf, NULL);
832 + } else {
833 + strbuf_release(&buf);
834 + return NULL;
835 + }
836 +}
837 +
838 +static int split_commit_in_progress(struct wt_status *s)
839 +{
840 + int split_in_progress = 0;
841 + char *head = read_line_from_git_path("HEAD");
842 + char *orig_head = read_line_from_git_path("ORIG_HEAD");
843 + char *rebase_amend = read_line_from_git_path("rebase-merge/amend");
844 + char *rebase_orig_head = read_line_from_git_path("rebase-merge/orig-head");
845 +
846 + if (!head || !orig_head || !rebase_amend || !rebase_orig_head ||
847 + !s->branch || strcmp(s->branch, "HEAD"))
848 + return split_in_progress;
849 +
850 + if (!strcmp(rebase_amend, rebase_orig_head)) {
851 + if (strcmp(head, rebase_amend))
852 + split_in_progress = 1;
853 + } else if (strcmp(orig_head, rebase_orig_head)) {
854 + split_in_progress = 1;
855 + }
856 +
857 + if (!s->amend && !s->nowarn && !s->workdir_dirty)
858 + split_in_progress = 0;
859 +
860 + free(head);
861 + free(orig_head);
862 + free(rebase_amend);
863 + free(rebase_orig_head);
864 + return split_in_progress;
865 +}
866 +
867 static void show_rebase_in_progress(struct wt_status *s,
868 struct wt_status_state *state,
869 const char *color)
@@ -838,6 +885,11 @@ static void show_rebase_in_progress(struct wt_status *s,
885 if (advice_status_hints)
886 status_printf_ln(s, color,
887 _(" (all conflicts fixed: run \"git rebase --continue\")"));
888 + } else if (split_commit_in_progress(s)) {
889 + status_printf_ln(s, color, _("You are currently splitting a commit during a rebase."));
890 + if (advice_status_hints)
891 + status_printf_ln(s, color,
892 + _(" (Once your working directory is clean, run \"git rebase --continue\")"));
893 } else {
894 status_printf_ln(s, color, _("You are currently editing a commit during a rebase."));
895 if (advice_status_hints && !s->amend) {