git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Nieder <jrnieder@gmail.com>
To: Michael Haggerty <mhagger@alum.mit.edu>
Cc: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: Re: [PATCH 3/5] safe_create_leading_directories(): add "slash" pointer
Date: Thu, 26 Dec 2013 14:34:44 -0800	[thread overview]
Message-ID: <20131226223444.GY20443@google.com> (raw)
In-Reply-To: <1387696451-32224-4-git-send-email-mhagger@alum.mit.edu>

Michael Haggerty wrote:

> [Subject: safe_create_leading_directories(): add "slash" pointer]

Is this a cleanup or improving the (internal) functionality of the
function somehow?  The above one-liner doesn't sum up for me in an
obvious way why this is a good change.

> Keep track of the position of the slash character separately, and

Separately from what?

> restore the slash character at a single place, at the end of the while
> loop.  This makes the next change easier to implement.
>
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>

Ah, do I understand correctly that this is about cleaning up
after the code that scribbles over 'path' in one place, to make
it harder to forget to do that cleanup as new code paths are
introduced?

It's too bad there's no variant of 'stat' and 'mkdir' that takes
a (buf, len) pair which would avoid the scribbling altogether.

> ---
>  sha1_file.c | 36 ++++++++++++++++++------------------
>  1 file changed, 18 insertions(+), 18 deletions(-)
>
> diff --git a/sha1_file.c b/sha1_file.c
> index cc9957e..dcfd35a 100644
> --- a/sha1_file.c
> +++ b/sha1_file.c
> @@ -107,40 +107,40 @@ int mkdir_in_gitdir(const char *path)
>  
>  int safe_create_leading_directories(char *path)
>  {
> -	char *pos = path + offset_1st_component(path);
> +	char *next_component = path + offset_1st_component(path);

This name change is probably worth also mentioning in the commit
message (or lifting into a separate patch) so the reader doesn't get
distracted.

> +	int retval = 0;
>  
> -	while (pos) {
> +	while (!retval && next_component) {

A more usual style would be

	int ... = 0;

	while (pos) {
		...
		if (!stat(path, &st)) {
			/* path exists */
			if (!S_ISDIR(st.st_mode)) {
				... = -3;
				goto out;
			}
		} else if (...) {
			...
		}
		...
	}
 out:
	*slash = '/';
	return ...;
 }

which makes it more explicit that the slash needs to be written back.
In this example, that would look like:

	char *slash = NULL;
	int ret;

	while (pos) {
		...
		if (!slash)
			break;

		...
		if (!*pos)
			break;

		*slash = '\0';
		if (!stat(path, &st)) {
			if (!S_ISDIR(st.st_mode)) {
				ret = -3;
				goto out;
			}
		} else if (mkdir(...)) {
			if (errno == EEXIST && ...) {
				; /* ok */
			} else {
				ret = -1;
				goto out;
			}
		} else if (adjust_shared_perm(...)) {
			ret = -2;
			goto out;
		}
		*slash = '/';
	}
	ret = 0;
 out:
 	if (slash)
		*slash = '/';
	return ret;

Using retval for control flow instead makes it eight lines more
concise, which is probably worth it.

[...]
> 			if (!S_ISDIR(st.st_mode)) {
> -				*pos = '/';
> -				return -3;
> +				retval = -3;
> 			}

Now the 'if' body is one line, so we can drop the braces and save
another line. :)

One more nit: elsewhere in this file, a variable keeping track of the
return value is named 'ret', so it probably makes sense to also use
that name here.

That would mean the following changes to be potentially squashed in
(keeping 'pos' name to make the patch easier to read, s/retval/ret/,
removing unnecessary braces).  None of these tweaks are particularly
important.  Feel free to skip them --- the only comment I've made that
matters is about the commit message.

Thanks for a nice cleanup,
Jonathan

diff --git i/sha1_file.c w/sha1_file.c
index dcfd35a..18cb50a 100644
--- i/sha1_file.c
+++ w/sha1_file.c
@@ -107,40 +107,38 @@ int mkdir_in_gitdir(const char *path)
 
 int safe_create_leading_directories(char *path)
 {
-	char *next_component = path + offset_1st_component(path);
-	int retval = 0;
+	char *pos = path + offset_1st_component(path);
+	int ret = 0;
 
-	while (!retval && next_component) {
+	while (!ret && pos) {
 		struct stat st;
-		char *slash = strchr(next_component, '/');
+		char *slash = strchr(pos, '/');
 
 		if (!slash)
 			return 0;
 		while (*(slash + 1) == '/')
 			slash++;
-		next_component = slash + 1;
-		if (!*next_component)
+		pos = slash + 1;
+		if (!*pos)
 			return 0;
 
 		*slash = '\0';
 		if (!stat(path, &st)) {
 			/* path exists */
-			if (!S_ISDIR(st.st_mode)) {
-				retval = -3;
-			}
+			if (!S_ISDIR(st.st_mode))
+				ret = -3;
 		} else if (mkdir(path, 0777)) {
 			if (errno == EEXIST &&
-			    !stat(path, &st) && S_ISDIR(st.st_mode)) {
+			    !stat(path, &st) && S_ISDIR(st.st_mode))
 				; /* somebody created it since we checked */
-			} else {
-				retval = -1;
-			}
+			else
+				ret = -1;
 		} else if (adjust_shared_perm(path)) {
-			retval = -2;
+			ret = -2;
 		}
 		*slash = '/';
 	}
-	return retval;
+	return ret;
 }
 
 int safe_create_leading_directories_const(const char *path)

  reply	other threads:[~2013-12-26 22:35 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-22  7:14 [PATCH 0/5] Fix two mkdir/rmdir races Michael Haggerty
2013-12-22  7:14 ` [PATCH 1/5] safe_create_leading_directories(): modernize format of "if" chaining Michael Haggerty
2013-12-26 21:52   ` Jonathan Nieder
2013-12-22  7:14 ` [PATCH 2/5] safe_create_leading_directories(): reduce scope of local variable Michael Haggerty
2013-12-26 21:55   ` Jonathan Nieder
2014-01-01 12:39     ` Michael Haggerty
2013-12-22  7:14 ` [PATCH 3/5] safe_create_leading_directories(): add "slash" pointer Michael Haggerty
2013-12-26 22:34   ` Jonathan Nieder [this message]
2014-01-01 21:10     ` Michael Haggerty
2013-12-22  7:14 ` [PATCH 4/5] safe_create_leading_directories(): fix a mkdir/rmdir race Michael Haggerty
2013-12-22 22:42   ` Ramsay Jones
2013-12-26 23:02   ` Jonathan Nieder
2014-01-02  0:53     ` Michael Haggerty
2013-12-22  7:14 ` [PATCH 5/5] rename_ref(): fix a mkdir()/rmdir() race Michael Haggerty
2013-12-26 23:20   ` Jonathan Nieder

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=20131226223444.GY20443@google.com \
    --to=jrnieder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=mhagger@alum.mit.edu \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).