Skip to content

Commit

Permalink
checkout: simplify untracked detection
Browse files Browse the repository at this point in the history
We can simplify the untracked file detection in a folder by simply
digging into the iterator.

In the original code (the code with the faulty assumption), we look to
see if there's an index entry beneath the directory that we want to
remove.   Eg, it looks to see if we have a workdir entry foo and an
index entry foo/bar.txt. If this is not the case, then the working
directory must have precious files in that directory. This part is okay.
The part that's not okay is if there is an index entry foo/bar.txt. It
just blows away the whole damned directory.

That's not cool.

Instead, by simply pushing the directory itself onto the stack and
iterating each entry, we will deal with the files one by one - whether
they're in the index (and can be force removed) or not (and are
precious).

The original code was a bad optimization, assuming that we didn't need
to git_iterator_advance_into if there was any index entry in the folder.
That's wrong - we could have optimized this iff all folder entries are
in the index.

Instead, we need to simply dig into the directory and analyze its
entries.
  • Loading branch information
ethomson committed Jun 8, 2017
1 parent f2d5ded commit a46e619
Showing 1 changed file with 2 additions and 50 deletions.
52 changes: 2 additions & 50 deletions src/checkout.c
Expand Up @@ -331,44 +331,6 @@ static int checkout_queue_remove(checkout_data *data, const char *path)
return git_vector_insert(&data->removes, copy);
}

static int contains_unversioned(int *unversioned, git_index *index, const char *dir)
{
git_vector entries = GIT_VECTOR_INIT;
git_buf path = GIT_BUF_INIT;
const char *workdir, *entry;
int error = 0;
size_t i;

if ((workdir = git_repository_workdir(index->rc.owner)) == NULL) {
error = -1;
goto out;
}

if ((error = git_buf_joinpath(&path, workdir, dir)) < 0)
goto out;

if ((error = git_path_dirload(&entries, path.ptr, strlen(workdir), 0)) < 0)
goto out;

*unversioned = 0;

git_vector_foreach(&entries, i, entry) {
const git_index_entry *ientry =
git_index_get_bypath(index, entry, 0);

if (ientry == NULL) {
*unversioned = 1;
break;
}
}

out:
git_vector_free_deep(&entries);
git_buf_free(&path);

return error;
}

/* note that this advances the iterator over the wd item */
static int checkout_action_wd_only(
checkout_data *data,
Expand Down Expand Up @@ -408,18 +370,8 @@ static int checkout_action_wd_only(
*/
const git_index_entry *e = git_index_get_byindex(data->index, pos);

if (e != NULL && data->diff->pfxcomp(e->path, wd->path) == 0) {
int unversioned;
if ((error = !contains_unversioned(
&unversioned, data->index, wd->path)) < 0)
return error;

if (unversioned)
return git_iterator_advance_into(wditem, workdir);

notify = GIT_CHECKOUT_NOTIFY_DIRTY;
remove = ((data->strategy & GIT_CHECKOUT_FORCE) != 0);
}
if (e != NULL && data->diff->pfxcomp(e->path, wd->path) == 0)
return git_iterator_advance_into(wditem, workdir);
}
}

Expand Down

0 comments on commit a46e619

Please sign in to comment.