Re: [WIP v1 2/4] mv: add check_dir_in_index() and solve general dir check issue
- From
Victoria Dye <vdye@github.com>
- Date
- Mar 31, 2022, 21:28 UTC
- Message-ID
- <52784078-c748-a4a0-68b4-db3c133dfa80@github.com>
- In-Reply-To
- <20220331091755.385961-3-shaoxuan.yuan02@gmail.com>
Shaoxuan Yuan wrote:
Show 8 quoted lines
> Originally, moving a <source> directory which is not on-disk due > to its existence outside of sparse-checkout cone, "giv mv" command > errors out with "bad source". > > Add a helper check_dir_in_index() function to see if a directory > name exists in the index. Also add a SPARSE_DIRECTORY bit to mark > such directories. >
Hmm, I think this patch would fit better in your eventual "sparse index integration" series than this "prerequisite fixes to sparse-checkout" series. Sparse directories *only* appear when you're using a sparse index so, theoretically, this shouldn't ever come up (and thus isn't testable) until you're using a sparse index.
Since it's here, though, I'm happy to review what you have (even if you eventually move it to a later series)!
Show 28 quoted lines
> Change the checking logic, so that such <source> directory makes
> "giv mv" command warns with "advise_on_updating_sparse_paths()"
> instead of "bad source"; also user now can supply a "--sparse" flag so
> this operation can be carried out successfully.
>
> Signed-off-by: Shaoxuan Yuan <shaoxuan.yuan02@gmail.com>
> ---
> Since I'm so new to C language (not an acquaintance until this patch),
> the "check_dir_in_index()" function I added might not be ideal (in terms of
> safety and correctness?). I have digging into the APIs provided in the codebase
> but I haven't found anything to do this very job: find out if a directory is
> in the index (am I missing something?).
> Probably because contents are stored in the index as blobs and
> they all represent regular files. So I came up with this dull solution...
>
> builtin/mv.c | 41 ++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/builtin/mv.c b/builtin/mv.c
> index 32ad4d5682..9da9205e01 100644
> --- a/builtin/mv.c
> +++ b/builtin/mv.c
> @@ -115,6 +115,25 @@ static int index_range_of_same_dir(const char *src, int length,
> return last - first;
> }
>
> +static int check_dir_in_index(const char *dir)
> +{This function can be made a lot simpler - you can use `cache_name_pos()` to find the index entry - if it's found, the directory exists as a sparse directory. And, because 'add_slash()' enforces the trailing slash later on, you don't need to worry about adjusting the name before you look for the entry.
Show 48 quoted lines
> + int ret = 0;
> + int length = sizeof(dir) + 1;
> + char *substr = malloc(length);
> +
> + for (int i = 0; i < the_index.cache_nr; i++) {
> + memcpy(substr, the_index.cache[i]->name, length);
> + memset(substr + length - 1, 0, 1);
> +
> + if (strcmp(dir, substr) == 0) {
> + ret = 1;
> + return ret;
> + }
> + }
> + free(substr);
> + return ret;
> +}
> +
> int cmd_mv(int argc, const char **argv, const char *prefix)
> {
> int i, flags, gitmodules_modified = 0;
> @@ -129,7 +148,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> OPT_END(),
> };
> const char **source, **destination, **dest_path, **submodule_gitfile;
> - enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX, SPARSE } *modes;
> + enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX, SPARSE,
> + SPARSE_DIRECTORY } *modes;
> struct stat st;
> struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
> struct lock_file lock_file = LOCK_INIT;
> @@ -197,6 +217,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> */
>
> int pos = cache_name_pos(src, length);
> + const char *src_w_slash = add_slash(src);
> +
> if (pos >= 0) {
> const struct cache_entry *ce = active_cache[pos];
>
> @@ -209,6 +231,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> else
> bad = _("bad source");
> }
> + else if (check_dir_in_index(src_w_slash) &&
> + !path_in_sparse_checkout(src_w_slash, &the_index)) {
> + modes[i] = SPARSE_DIRECTORY;
> + goto dir_check;
> + }In if-statements like this, you'll want to line up the statements in parentheses on subsequent lines, like:
else if (check_dir_in_index(src_w_slash) &&
!path_in_sparse_checkout(src_w_slash, &the_index)) {...where the second line is indented 1 (8-space-sized) tab + 1 space.
In general, if you're trying to align code (in this repository), align first with as many tabs as possible, then the "remainder" with spaces. Note that this isn't 100% consistent throughout the repository - older lines might not have been aligned properly - but you should go for this styling on any new lines that you add.
Show 40 quoted lines
> /* only error if existence is expected. */
> else if (modes[i] != SPARSE)
> bad = _("bad source");
> @@ -219,7 +246,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> && lstat(dst, &st) == 0)
> bad = _("cannot move directory over file");
> else if (src_is_dir) {
> - int first = cache_name_pos(src, length), last;
> + int first, last;
> +dir_check:
> + first = cache_name_pos(src, length);
>
> if (first >= 0)
> prepare_move_submodule(src, first,
> @@ -230,7 +259,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> else { /* last - first >= 1 */
> int j, dst_len, n;
>
> - modes[i] = WORKING_DIRECTORY;
> + if (!modes[i])
> + modes[i] = WORKING_DIRECTORY;
> n = argc + last - first;
> REALLOC_ARRAY(source, n);
> REALLOC_ARRAY(destination, n);
> @@ -332,7 +362,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> printf(_("Renaming %s to %s\n"), src, dst);
> if (show_only)
> continue;
> - if (mode != INDEX && mode != SPARSE && rename(src, dst) < 0) {
> + if (mode != INDEX && mode != SPARSE && mode != SPARSE_DIRECTORY &&
> + rename(src, dst) < 0) {
> if (ignore_errors)
> continue;
> die_errno(_("renaming '%s' failed"), src);
> @@ -346,7 +377,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
> 1);
> }
>
> - if (mode == WORKING_DIRECTORY)
> + if (mode == WORKING_DIRECTORY || mode == SPARSE_DIRECTORY)I'm a bit confused - doesn't this mean the sparse dir move will be skipped? In your commit description, you mention that this 'mv' succeeds with the '--sparse' option, but I don't see any place where the sparse directory would be moved.
> continue; > > pos = cache_name_pos(src, strlen(src));