wt-status.c: handle worktree renames
Before 425a28e0a4
(diff-lib: allow ita entries treated as "not yet exist
in index" - 2016-10-24) there are never "new files" in the index, which
essentially disables rename detection because we only detect renames
when a new file appears in a diff pair.
After that commit, an i-t-a entry can appear as a new file in "git
diff-files". But the diff callback function in wt-status.c does not
handle this case and produces incorrect status output.
PS. The reader may notice that this patch adds a new xstrdup() but not
a free(). Yes we leak memory (the same for head_path). But wt_status
so far has been short lived, this leak should not matter in
practice.
Noticed-by: Alex Vandiver <alexmv@dropbox.com>
Helped-by: Igor Djordjevic <igor.d.djordjevic@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
5134ccde64
commit
176ea74793
22
wt-status.c
22
wt-status.c
@ -361,8 +361,6 @@ static void wt_longstatus_print_change_data(struct wt_status *s,
|
||||
switch (change_type) {
|
||||
case WT_STATUS_UPDATED:
|
||||
status = d->index_status;
|
||||
if (d->rename_source)
|
||||
one_name = d->rename_source;
|
||||
break;
|
||||
case WT_STATUS_CHANGED:
|
||||
if (d->new_submodule_commits || d->dirty_submodule) {
|
||||
@ -383,6 +381,14 @@ static void wt_longstatus_print_change_data(struct wt_status *s,
|
||||
change_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only pick up the rename it's relevant. If the rename is for
|
||||
* the changed section and we're printing the updated section,
|
||||
* ignore it.
|
||||
*/
|
||||
if (d->rename_status == status)
|
||||
one_name = d->rename_source;
|
||||
|
||||
one = quote_path(one_name, s->prefix, &onebuf);
|
||||
two = quote_path(two_name, s->prefix, &twobuf);
|
||||
|
||||
@ -434,7 +440,7 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
|
||||
struct wt_status_change_data *d;
|
||||
|
||||
p = q->queue[i];
|
||||
it = string_list_insert(&s->change, p->one->path);
|
||||
it = string_list_insert(&s->change, p->two->path);
|
||||
d = it->util;
|
||||
if (!d) {
|
||||
d = xcalloc(1, sizeof(*d));
|
||||
@ -461,6 +467,14 @@ static void wt_status_collect_changed_cb(struct diff_queue_struct *q,
|
||||
/* mode_worktree is zero for a delete. */
|
||||
break;
|
||||
|
||||
case DIFF_STATUS_COPIED:
|
||||
case DIFF_STATUS_RENAMED:
|
||||
if (d->rename_status)
|
||||
die("BUG: multiple renames on the same target? how?");
|
||||
d->rename_source = xstrdup(p->one->path);
|
||||
d->rename_score = p->score * 100 / MAX_SCORE;
|
||||
d->rename_status = p->status;
|
||||
/* fallthru */
|
||||
case DIFF_STATUS_MODIFIED:
|
||||
case DIFF_STATUS_TYPE_CHANGED:
|
||||
case DIFF_STATUS_UNMERGED:
|
||||
@ -532,6 +546,8 @@ static void wt_status_collect_updated_cb(struct diff_queue_struct *q,
|
||||
|
||||
case DIFF_STATUS_COPIED:
|
||||
case DIFF_STATUS_RENAMED:
|
||||
if (d->rename_status)
|
||||
die("BUG: multiple renames on the same target? how?");
|
||||
d->rename_source = xstrdup(p->one->path);
|
||||
d->rename_score = p->score * 100 / MAX_SCORE;
|
||||
d->rename_status = p->status;
|
||||
|
Reference in New Issue
Block a user