All of lore.kernel.org
 help / color / mirror / Atom feed
From: Elijah Newren <newren@gmail.com>
To: Jonathan Tan <jonathantanmy@google.com>
Cc: "Git Mailing List" <git@vger.kernel.org>,
	"Junio C Hamano" <gitster@pobox.com>,
	"SZEDER Gábor" <szeder.dev@gmail.com>
Subject: Re: [PATCH v2] merge-recursive: symlink's descendants not in way
Date: Wed, 18 Sep 2019 14:54:32 -0700	[thread overview]
Message-ID: <CABPp-BGN9x5HAdfm1Pn14uswCBomczSYNHeqkNmuUhWnuQD++Q@mail.gmail.com> (raw)
In-Reply-To: <20190918202738.57273-1-jonathantanmy@google.com>

On Wed, Sep 18, 2019 at 1:27 PM Jonathan Tan <jonathantanmy@google.com> wrote:
>
> When the working tree has:
>  - bar (directory)
>  - bar/file (file)
>  - foo (symlink to .)
>
> (note that lstat() for "foo/bar" would tell us that it is a directory)
>
> and the user merges a commit that deletes the foo symlink and instead
> contains:
>  - bar (directory, as above)
>  - bar/file (file, as above)
>  - foo (directory)
>  - foo/bar (file)
>
> the merge should happen without requiring user intervention. However,
> this does not happen.
>
> This is because dir_in_way(), when checking the working tree, thinks
> that "foo/bar" is a directory. But a symlink should be treated much the
> same as a file: since dir_in_way() is only checking to see if there is a
> directory in the way, we don't want symlinks in leading paths to
> sometimes cause dir_in_way() to return true.
>
> Teach dir_in_way() to also check for symlinks in leading paths before
> reporting whether a directory is in the way.
>
> Helped-by: Elijah Newren <newren@gmail.com>
> Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
> ---
> Changes from v1:
>
> - Used has_symlink_leading_path(). This drastically shortens the diff.
> - Updated commit message following suggestions from Junio, Szeder Gábor,
>   and Elijah Newren.
> - Updated test to add prereq and verification that the working tree
>   contains what we want.
> ---
>  merge-recursive.c          |  3 ++-
>  t/t3030-merge-recursive.sh | 28 ++++++++++++++++++++++++++++
>  2 files changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/merge-recursive.c b/merge-recursive.c
> index 6b812d67e3..22a12cfeba 100644
> --- a/merge-recursive.c
> +++ b/merge-recursive.c
> @@ -764,7 +764,8 @@ static int dir_in_way(struct index_state *istate, const char *path,
>
>         strbuf_release(&dirpath);
>         return check_working_copy && !lstat(path, &st) && S_ISDIR(st.st_mode) &&
> -               !(empty_ok && is_empty_dir(path));
> +               !(empty_ok && is_empty_dir(path)) &&
> +               !has_symlink_leading_path(path, strlen(path));
>  }
>
>  /*
> diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
> index ff641b348a..faa8892741 100755
> --- a/t/t3030-merge-recursive.sh
> +++ b/t/t3030-merge-recursive.sh
> @@ -452,6 +452,34 @@ test_expect_success 'merge-recursive d/f conflict result' '
>
>  '
>
> +test_expect_success SYMLINKS 'dir in working tree with symlink ancestor does not produce d/f conflict' '
> +       git init sym &&
> +       (
> +               cd sym &&
> +               ln -s . foo &&
> +               mkdir bar &&
> +               >bar/file &&
> +               git add foo bar/file &&
> +               git commit -m "foo symlink" &&
> +
> +               git checkout -b branch1 &&
> +               git commit --allow-empty -m "empty commit" &&
> +
> +               git checkout master &&
> +               git rm foo &&
> +               mkdir foo &&
> +               >foo/bar &&
> +               git add foo/bar &&
> +               git commit -m "replace foo symlink with real foo dir and foo/bar file" &&
> +
> +               git checkout branch1 &&
> +
> +               git cherry-pick master &&
> +               test_path_is_dir foo &&
> +               test_path_is_file foo/bar
> +       )
> +'
> +
>  test_expect_success 'reset and 3-way merge' '
>
>         git reset --hard "$c2" &&
> --

Looks good to me; nice how much it has simplified.  Thanks for working on this.

> 2.23.0.237.gc6a4ce50a0-goog

A total tangent, but what do you use the "-goog" suffix for?

  reply	other threads:[~2019-09-18 21:54 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <https://public-inbox.org/git/20190917215040.132503-1-jonathantanmy@google.com/>
2019-09-18 20:27 ` [PATCH v2] merge-recursive: symlink's descendants not in way Jonathan Tan
2019-09-18 21:54   ` Elijah Newren [this message]
2019-09-20 17:15   ` Junio C Hamano
2019-09-20 20:25     ` Jonathan Tan
2019-09-20 20:38       ` Junio C Hamano
2019-09-20 20:50         ` Jonathan Tan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CABPp-BGN9x5HAdfm1Pn14uswCBomczSYNHeqkNmuUhWnuQD++Q@mail.gmail.com \
    --to=newren@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jonathantanmy@google.com \
    --cc=szeder.dev@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.