On Mon, Jul 30, 2018 at 8:27 AM, Nguyễn Thái Ngọc Duy <pclo...@gmail.com> wrote:
> Paths that only differ in case work fine in a case-sensitive
> filesystems, but if those repos are cloned in a case-insensitive one,
> you'll get problems. The first thing to notice is "git status" will
> never be clean with no indication what's exactly is "dirty".

"what" rather than "what's"?

> This patch helps the situation a bit by pointing out the problem at
> clone time. I have not suggested any way to work around or fix this
> problem. But I guess we could probably have a section in
> Documentation/ dedicated to this problem and point there instead of
> a long advice in this warning.
>
> Another thing we probably should do is catch in "git checkout" too,
> not just "git clone" since your linux/unix colleage colleague may

drop "colleage", keep "colleague"?

> accidentally add some files that your mac/windows machine is not very
> happy with. But then there's another problem, once the problem is
> known, we probably should stop spamming this warning at every
> checkout, but how?

Good questions.  I have no answers.

>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
> ---
>  builtin/clone.c | 41 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>
> diff --git a/builtin/clone.c b/builtin/clone.c
> index 5c439f1394..32738c2737 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -711,6 +711,33 @@ static void update_head(const struct ref *our, const 
> struct ref *remote,
>         }
>  }
>
> +static void find_duplicate_icase_entries(struct index_state *istate,
> +                                        struct string_list *dup)
> +{
> +       struct string_list list = STRING_LIST_INIT_NODUP;
> +       int i;
> +
> +       for (i = 0; i < istate->cache_nr; i++)
> +               string_list_append(&list, istate->cache[i]->name);
> +
> +       list.cmp = fspathcmp;
> +       string_list_sort(&list);

So, you sort the list by fspathcmp to get the entries that differ in
case only next to each other.  Makes sense...

> +
> +       for (i = 1; i < list.nr; i++) {
> +               const char *cur = list.items[i].string;
> +               const char *prev = list.items[i - 1].string;
> +
> +               if (dup->nr &&
> +                   !fspathcmp(cur, dup->items[dup->nr - 1].string)) {
> +                       string_list_append(dup, cur);

If we have at least one duplicate in dup (and currently we'd have to
have at least two), and we now hit yet another (i.e. a third or
fourth...) way of spelling the same path, then we add it.

> +               } else if (!fspathcmp(cur, prev)) {
> +                       string_list_append(dup, prev);
> +                       string_list_append(dup, cur);
> +               }

...otherwise, if we find a duplicate, we add both spellings to the dup list.

> +       }
> +       string_list_clear(&list, 0);
> +}
> +
>  static int checkout(int submodule_progress)
>  {
>         struct object_id oid;
> @@ -761,6 +788,20 @@ static int checkout(int submodule_progress)
>         if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
>                 die(_("unable to write new index file"));
>
> +       if (ignore_case) {
> +               struct string_list dup = STRING_LIST_INIT_DUP;
> +               int i;
> +
> +               find_duplicate_icase_entries(&the_index, &dup);
> +               if (dup.nr) {
> +                       warning(_("the following paths in this repository 
> only differ in case and will\n"

Perhaps I'm being excessively pedantic, but what if there are multiple
pairs of paths differing in case?  E.g. if someone has readme.txt,
README.txt, foo.txt, and FOO.txt, you'll list all four files but
readme.txt and foo.txt do not only differ in case.

Maybe something like "...only differ in case from another path and
will... " or is that too verbose and annoying?

> +                                 "cause problems because you have cloned it 
> on an case-insensitive filesytem:\n"));
> +                       for (i = 0; i < dup.nr; i++)
> +                               fprintf(stderr, "\t%s\n", 
> dup.items[i].string);
> +               }
> +               string_list_clear(&dup, 0);
> +       }
> +
>         err |= run_hook_le(NULL, "post-checkout", sha1_to_hex(null_sha1),
>                            oid_to_hex(&oid), "1", NULL);

Is it worth attempting to also warn about paths that only differ in
UTF-normalization on relevant MacOS systems?

Reply via email to