All of lore.kernel.org
 help / color / mirror / Atom feed
From: "SZEDER Gábor" <szeder.dev@gmail.com>
To: Miriam Rubio <mirucam@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [Outreachy][PATCH] abspath: reconcile `dir_exists()` and `is_directory()`
Date: Thu, 24 Oct 2019 13:41:48 +0200	[thread overview]
Message-ID: <20191024114148.GK4348@szeder.dev> (raw)
In-Reply-To: <20191024092745.97035-1-mirucam@gmail.com>

On Thu, Oct 24, 2019 at 11:27:45AM +0200, Miriam Rubio wrote:
> The dir_exists() function in builtin/clone.c is marked as static, so
> nobody can use it outside builtin/clone.c.
> 
> There is also is_directory() which obviously tries to do the very same, but it uses a name that few developers will think of when they see file_exists() and look for the equivalent function to see whether a given directory exists.
> 
> Let's reconcile these functions by renaming is_directory() to dir_exists() and using it also in builtin/clone.c.

Please wrap the proposed log message at about 70 characters width;
that way it will look much better in 'git log' in a standard 80 char
wide terminal.

I think this is a cleanup worth doing, but...

> diff --git a/abspath.c b/abspath.c
> index 9857985329..13bd92eca5 100644
> --- a/abspath.c
> +++ b/abspath.c
> @@ -5,7 +5,7 @@
>   * symlink to a directory, we do not want to say it is a directory when
>   * dealing with tracked content in the working tree.
>   */
> -int is_directory(const char *path)
> +int dir_exists(const char *path)
>  {
>  	struct stat st;
>  	return (!stat(path, &st) && S_ISDIR(st.st_mode));

Note the '&& S_ISDIR(st.st_mode)', making sure that the given path is
in fact a directory.  Good.

> diff --git a/builtin/clone.c b/builtin/clone.c
> index c46ee29f0a..f89938bf94 100644
> --- a/builtin/clone.c
> +++ b/builtin/clone.c
> @@ -899,12 +899,6 @@ static void dissociate_from_references(void)
>  	free(alternates);
>  }
>  
> -static int dir_exists(const char *path)
> -{
> -	struct stat sb;
> -	return !stat(path, &sb);

But look at this, it only checks that the given path exists, but it
could be a regular file or any other kind of path other than a
directory as well!

So this function clearly doesn't do what it's name suggests.  That's
bad.

Unfortunately, it gets worse: some of its callsites in
'builtin/clone.c' do expect it to check the existence of _any_ path,
not just a directory.

The first callsite is:

    dest_exists = dir_exists(dir);
    if (dest_exists && !is_empty_dir(dir))
            die(_("destination path '%s' already exists and is not "
                    "an empty directory."), dir);

I think this actually means path_exists(): if a file, or any other
kind of path with the given name were to exist, then we should die()
showing this error message, but after changing dir_exists() to make
sure that the path is indeed a directory we won't:

  # create a 'git' _file_
  $ >git
  # current git master:
  $ git clone https://github.com/git/git
  fatal: destination path 'git' already exists and is not an empty directory.
  # with this patch:
  $ ~/src/git/git clone https://github.com/git/git
  fatal: could not create work tree dir 'git': File exists

So the command still fails, which is good, but with a different error
message.  The test suite doesn't catch this, because the test case
looking at this scenario ('clone to an existing path' in
'./t5601-clone.sh') only checks that 'git clone' fails, but it doesn't
check whether it failed with the right error message.

Now, that other error message comes after a failed mkdir() call later
on which should have created the work tree.  So it begs the question
what would happen when a file is in the way of a bare clone:

  $ >git.git
  $ git clone --bare https://github.com/git/git
  fatal: destination path 'git.git' already exists and is not an empty directory.
  $ ~/src/git/git clone --bare https://github.com/git/git
  Cloning into bare repository 'git.git'...
  fatal: invalid gitfile format: /home/szeder/src/git/tmp/git.git

Then the next callsite looks like it meant path_exists() as well, but
I didn't try to make it fail or show different behavior:

    work_tree = getenv("GIT_WORK_TREE");
    if (work_tree && dir_exists(work_tree))
            die(_("working tree '%s' already exists."), work_tree);

And there is a third callsite, but I'm not sure what it is about, and,
consequently, what is really meant with dir_exists() here:

    if (real_git_dir) {
            if (dir_exists(real_git_dir))
                    junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;



  reply	other threads:[~2019-10-24 11:41 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-24  9:27 [Outreachy][PATCH] abspath: reconcile `dir_exists()` and `is_directory()` Miriam Rubio
2019-10-24 11:41 ` SZEDER Gábor [this message]
2019-10-24 18:13   ` Jeff King
2019-10-24 20:45     ` Emily Shaffer
2019-10-24 20:51       ` Jeff King
2019-10-25  2:40         ` Junio C Hamano
2019-10-24 20:57   ` Miriam R.
2019-10-25  2:45   ` Junio C Hamano
2019-10-25  8:59     ` Miriam R.
2019-10-25  9:43       ` Junio C Hamano
2019-10-25 14:47         ` Christian Couder
2019-10-25 15:23           ` Miriam R.
2019-10-26 15:30             ` Miriam R.
2019-10-26 18:05               ` Christian Couder
2019-10-26 18:42                 ` Miriam R.

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=20191024114148.GK4348@szeder.dev \
    --to=szeder.dev@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=mirucam@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.