Commit 702b23d7 by Edward Thomson

checkout: provide internal func to compute target path

Many code paths in checkout need the final, full on-disk path of the
file they're writing.  (No surprise).  However, they all munge the
`data->path` buffer themselves to get there.  Provide a nice helper
method for them.

Plus, drop the use `git_iterator_current_workdir_path` which does the
same thing but different.  Checkout is the only caller of this silly
function, which lets us remove it.
parent be30387e
...@@ -66,8 +66,8 @@ typedef struct { ...@@ -66,8 +66,8 @@ typedef struct {
git_vector update_conflicts; git_vector update_conflicts;
git_vector *update_reuc; git_vector *update_reuc;
git_vector *update_names; git_vector *update_names;
git_buf path; git_buf target_path;
size_t workdir_len; size_t target_len;
git_buf tmp; git_buf tmp;
unsigned int strategy; unsigned int strategy;
int can_symlink; int can_symlink;
...@@ -294,14 +294,30 @@ static int checkout_action_no_wd( ...@@ -294,14 +294,30 @@ static int checkout_action_no_wd(
return checkout_action_common(action, data, delta, NULL); return checkout_action_common(action, data, delta, NULL);
} }
static bool wd_item_is_removable(git_iterator *iter, const git_index_entry *wd) static int checkout_target_fullpath(
git_buf **out, checkout_data *data, const char *path)
{ {
git_buf *full = NULL; git_buf_truncate(&data->target_path, data->target_len);
if (path && git_buf_puts(&data->target_path, path) < 0)
return -1;
*out = &data->target_path;
return 0;
}
static bool wd_item_is_removable(
checkout_data *data, const git_index_entry *wd)
{
git_buf *full;
if (wd->mode != GIT_FILEMODE_TREE) if (wd->mode != GIT_FILEMODE_TREE)
return true; return true;
if (git_iterator_current_workdir_path(&full, iter) < 0)
return true; if (checkout_target_fullpath(&full, data, wd->path) < 0)
return false;
return !full || !git_path_contains(full, DOT_GIT); return !full || !git_path_contains(full, DOT_GIT);
} }
...@@ -363,14 +379,14 @@ static int checkout_action_wd_only( ...@@ -363,14 +379,14 @@ static int checkout_action_wd_only(
if ((error = checkout_notify(data, notify, NULL, wd)) != 0) if ((error = checkout_notify(data, notify, NULL, wd)) != 0)
return error; return error;
if (remove && wd_item_is_removable(workdir, wd)) if (remove && wd_item_is_removable(data, wd))
error = checkout_queue_remove(data, wd->path); error = checkout_queue_remove(data, wd->path);
if (!error) if (!error)
error = git_iterator_advance(wditem, workdir); error = git_iterator_advance(wditem, workdir);
} else { } else {
/* untracked or ignored - can't know which until we advance through */ /* untracked or ignored - can't know which until we advance through */
bool over = false, removable = wd_item_is_removable(workdir, wd); bool over = false, removable = wd_item_is_removable(data, wd);
git_iterator_status_t untracked_state; git_iterator_status_t untracked_state;
/* copy the entry for issuing notification callback later */ /* copy the entry for issuing notification callback later */
...@@ -428,10 +444,12 @@ static bool submodule_is_config_only( ...@@ -428,10 +444,12 @@ static bool submodule_is_config_only(
static bool checkout_is_empty_dir(checkout_data *data, const char *path) static bool checkout_is_empty_dir(checkout_data *data, const char *path)
{ {
git_buf_truncate(&data->path, data->workdir_len); git_buf *fullpath;
if (git_buf_puts(&data->path, path) < 0)
if (checkout_target_fullpath(&fullpath, data, path) < 0)
return false; return false;
return git_path_is_empty_dir(data->path.ptr);
return git_path_is_empty_dir(fullpath->ptr);
} }
static int checkout_action_with_wd( static int checkout_action_with_wd(
...@@ -1582,18 +1600,18 @@ static int checkout_submodule_update_index( ...@@ -1582,18 +1600,18 @@ static int checkout_submodule_update_index(
checkout_data *data, checkout_data *data,
const git_diff_file *file) const git_diff_file *file)
{ {
git_buf *fullpath;
struct stat st; struct stat st;
/* update the index unless prevented */ /* update the index unless prevented */
if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) != 0) if ((data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) != 0)
return 0; return 0;
git_buf_truncate(&data->path, data->workdir_len); if (checkout_target_fullpath(&fullpath, data, file->path) < 0)
if (git_buf_puts(&data->path, file->path) < 0)
return -1; return -1;
data->perfdata.stat_calls++; data->perfdata.stat_calls++;
if (p_stat(git_buf_cstr(&data->path), &st) < 0) { if (p_stat(fullpath->ptr, &st) < 0) {
giterr_set( giterr_set(
GITERR_CHECKOUT, "Could not stat submodule %s\n", file->path); GITERR_CHECKOUT, "Could not stat submodule %s\n", file->path);
return GIT_ENOTFOUND; return GIT_ENOTFOUND;
...@@ -1718,22 +1736,23 @@ static int checkout_blob( ...@@ -1718,22 +1736,23 @@ static int checkout_blob(
checkout_data *data, checkout_data *data,
const git_diff_file *file) const git_diff_file *file)
{ {
int error = 0; git_buf *fullpath;
struct stat st; struct stat st;
int error = 0;
git_buf_truncate(&data->path, data->workdir_len); if (checkout_target_fullpath(&fullpath, data, file->path) < 0)
if (git_buf_puts(&data->path, file->path) < 0)
return -1; return -1;
if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) { if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) {
int rval = checkout_safe_for_update_only( int rval = checkout_safe_for_update_only(
data, git_buf_cstr(&data->path), file->mode); data, fullpath->ptr, file->mode);
if (rval <= 0) if (rval <= 0)
return rval; return rval;
} }
error = checkout_write_content( error = checkout_write_content(
data, &file->id, git_buf_cstr(&data->path), NULL, file->mode, &st); data, &file->id, fullpath->ptr, NULL, file->mode, &st);
/* update the index unless prevented */ /* update the index unless prevented */
if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0) if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0)
...@@ -1754,18 +1773,21 @@ static int checkout_remove_the_old( ...@@ -1754,18 +1773,21 @@ static int checkout_remove_the_old(
git_diff_delta *delta; git_diff_delta *delta;
const char *str; const char *str;
size_t i; size_t i;
const char *workdir = git_buf_cstr(&data->path); git_buf *fullpath;
uint32_t flg = GIT_RMDIR_EMPTY_PARENTS | uint32_t flg = GIT_RMDIR_EMPTY_PARENTS |
GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS; GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS;
if (data->opts.checkout_strategy & GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES) if (data->opts.checkout_strategy & GIT_CHECKOUT_SKIP_LOCKED_DIRECTORIES)
flg |= GIT_RMDIR_SKIP_NONEMPTY; flg |= GIT_RMDIR_SKIP_NONEMPTY;
git_buf_truncate(&data->path, data->workdir_len); if (checkout_target_fullpath(&fullpath, data, NULL) < 0)
return -1;
git_vector_foreach(&data->diff->deltas, i, delta) { git_vector_foreach(&data->diff->deltas, i, delta) {
if (actions[i] & CHECKOUT_ACTION__REMOVE) { if (actions[i] & CHECKOUT_ACTION__REMOVE) {
error = git_futils_rmdir_r(delta->old_file.path, workdir, flg); error = git_futils_rmdir_r(
delta->old_file.path, fullpath->ptr, flg);
if (error < 0) if (error < 0)
return error; return error;
...@@ -1782,7 +1804,7 @@ static int checkout_remove_the_old( ...@@ -1782,7 +1804,7 @@ static int checkout_remove_the_old(
} }
git_vector_foreach(&data->removes, i, str) { git_vector_foreach(&data->removes, i, str) {
error = git_futils_rmdir_r(str, workdir, flg); error = git_futils_rmdir_r(str, fullpath->ptr, flg);
if (error < 0) if (error < 0)
return error; return error;
...@@ -1949,13 +1971,13 @@ static int checkout_write_entry( ...@@ -1949,13 +1971,13 @@ static int checkout_write_entry(
const git_index_entry *side) const git_index_entry *side)
{ {
const char *hint_path = NULL, *suffix; const char *hint_path = NULL, *suffix;
git_buf *fullpath;
struct stat st; struct stat st;
int error; int error;
assert (side == conflict->ours || side == conflict->theirs); assert (side == conflict->ours || side == conflict->theirs);
git_buf_truncate(&data->path, data->workdir_len); if (checkout_target_fullpath(&fullpath, data, side->path) < 0)
if (git_buf_puts(&data->path, side->path) < 0)
return -1; return -1;
if ((conflict->name_collision || conflict->directoryfile) && if ((conflict->name_collision || conflict->directoryfile) &&
...@@ -1969,18 +1991,18 @@ static int checkout_write_entry( ...@@ -1969,18 +1991,18 @@ static int checkout_write_entry(
suffix = data->opts.their_label ? data->opts.their_label : suffix = data->opts.their_label ? data->opts.their_label :
"theirs"; "theirs";
if (checkout_path_suffixed(&data->path, suffix) < 0) if (checkout_path_suffixed(fullpath, suffix) < 0)
return -1; return -1;
hint_path = side->path; hint_path = side->path;
} }
if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 && if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0 &&
(error = checkout_safe_for_update_only(data, git_buf_cstr(&data->path), side->mode)) <= 0) (error = checkout_safe_for_update_only(data, fullpath->ptr, side->mode)) <= 0)
return error; return error;
return checkout_write_content(data, return checkout_write_content(data,
&side->id, git_buf_cstr(&data->path), hint_path, side->mode, &st); &side->id, fullpath->ptr, hint_path, side->mode, &st);
} }
static int checkout_write_entries( static int checkout_write_entries(
...@@ -2293,7 +2315,7 @@ static void checkout_data_clear(checkout_data *data) ...@@ -2293,7 +2315,7 @@ static void checkout_data_clear(checkout_data *data)
git_strmap_free(data->mkdir_map); git_strmap_free(data->mkdir_map);
git_buf_free(&data->path); git_buf_free(&data->target_path);
git_buf_free(&data->tmp); git_buf_free(&data->tmp);
git_index_free(data->index); git_index_free(data->index);
...@@ -2447,12 +2469,12 @@ static int checkout_data_init( ...@@ -2447,12 +2469,12 @@ static int checkout_data_init(
if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 || if ((error = git_vector_init(&data->removes, 0, git__strcmp_cb)) < 0 ||
(error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 || (error = git_vector_init(&data->remove_conflicts, 0, NULL)) < 0 ||
(error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 || (error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 ||
(error = git_buf_puts(&data->path, data->opts.target_directory)) < 0 || (error = git_buf_puts(&data->target_path, data->opts.target_directory)) < 0 ||
(error = git_path_to_dir(&data->path)) < 0 || (error = git_path_to_dir(&data->target_path)) < 0 ||
(error = git_strmap_alloc(&data->mkdir_map)) < 0) (error = git_strmap_alloc(&data->mkdir_map)) < 0)
goto cleanup; goto cleanup;
data->workdir_len = git_buf_len(&data->path); data->target_len = git_buf_len(&data->target_path);
git_attr_session__init(&data->attr_session, data->repo); git_attr_session__init(&data->attr_session, data->repo);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment