threads / patch / 9244

patchuse lockfile.c routines in git_commit_set_multivar()

Subject: [PATCH] use lockfile.c routines in git_commit_set_multivar()

## tl;dr

7 messages between Jul 26, 2007 and Jul 27, 2007. Diffs are folded; open one to read it.

replies: 6people: 3as markdown or json

Bradford C. Smith· Jul 26, 2007, 16:55 UTC · lore

Changed git_commit_set_multivar() to use the routines provided by lockfile.c to reduce code duplication and ensure consistent behavior.

Signed-off-by: Bradford C. Smith <bradford.carl.smith@gmail.com>
---

I am resubmitting this patch to be considered separately from the symlink resolution change. It differs from the first time I submitted it only in that I have corrected the multi-line comment formatting I used.

I ran the full test suite (make test) on this patch without failures.
 config.c |   30 ++++++++++++++++++------------
 1 files changed, 18 insertions(+), 12 deletions(-)
Show changes to config.c +18 −12
diff --git a/config.c b/config.c
index f89a611..dd2de6e 100644
--- a/config.c
+++ b/config.c
@@ -715,7 +715,7 @@ int git_config_set_multivar(const char* key, const char* value,
 	int fd = -1, in_fd;
 	int ret;
 	char* config_filename;
-	char* lock_file;
+	struct lock_file *lock = NULL;
 	const char* last_dot = strrchr(key, '.');
 
 	config_filename = getenv(CONFIG_ENVIRONMENT);
@@ -725,7 +725,6 @@ int git_config_set_multivar(const char* key, const char* value,
 			config_filename  = git_path("config");
 	}
 	config_filename = xstrdup(config_filename);
-	lock_file = xstrdup(mkpath("%s.lock", config_filename));
 
 	/*
 	 * Since "key" actually contains the section name and the real
@@ -770,11 +769,12 @@ int git_config_set_multivar(const char* key, const char* value,
 	store.key[i] = 0;
 
 	/*
-	 * The lock_file serves a purpose in addition to locking: the new
+	 * The lock serves a purpose in addition to locking: the new
 	 * contents of .git/config will be written into it.
 	 */
-	fd = open(lock_file, O_WRONLY | O_CREAT | O_EXCL, 0666);
-	if (fd < 0 || adjust_shared_perm(lock_file)) {
+	lock = xcalloc(sizeof(struct lock_file), 1);
+	fd = hold_lock_file_for_update(lock, config_filename, 0);
+	if (fd < 0) {
 		fprintf(stderr, "could not lock config file\n");
 		free(store.key);
 		ret = -1;
@@ -914,25 +914,31 @@ int git_config_set_multivar(const char* key, const char* value,
 				goto write_err_out;
 
 		munmap(contents, contents_sz);
-		unlink(config_filename);
 	}
 
-	if (rename(lock_file, config_filename) < 0) {
-		fprintf(stderr, "Could not rename the lock file?\n");
+	if (close(fd) || commit_lock_file(lock) < 0) {
+		fprintf(stderr, "Cannot commit config file!\n");
 		ret = 4;
 		goto out_free;
 	}
 
+	/* fd is closed, so don't try to close it below. */
+	fd = -1;
+	/*
+	 * lock is committed, so don't try to roll it back below.
+	 * NOTE: Since lockfile.c keeps a linked list of all created
+	 * lock_file structures, it isn't safe to free(lock).  It's
+	 * better to just leave it hanging around.
+	 */
+	lock = NULL;
 	ret = 0;
 
 out_free:
 	if (0 <= fd)
 		close(fd);
+	if (lock)
+		rollback_lock_file(lock);
 	free(config_filename);
-	if (lock_file) {
-		unlink(lock_file);
-		free(lock_file);
-	}
 	return ret;
 
 write_err_out:
-- 
1.5.3.rc3.9.g1b487
Johannes Schindelin· Jul 26, 2007, 18:31 UTC · re: Bradford C. Smith · lore

Re: [PATCH] use lockfile.c routines in git_commit_set_multivar()

Hi,
I like the general idea.  Thanks.
On Thu, 26 Jul 2007, Bradford C. Smith wrote:
Show 16 quoted lines
> +	/* fd is closed, so don't try to close it below. */
> +	fd = -1;
> +	/*
> +	 * lock is committed, so don't try to roll it back below.
> +	 * NOTE: Since lockfile.c keeps a linked list of all created
> +	 * lock_file structures, it isn't safe to free(lock).  It's
> +	 * better to just leave it hanging around.
> +	 */
> +	lock = NULL;
>  	ret = 0;
>  
>  out_free:
>  	if (0 <= fd)
>  		close(fd);
> +	if (lock)
> +		rollback_lock_file(lock);

Wouldn't it be better to put the rollback_lock_file() into the if clause when commit failed?

Besides, I think you can safely call rollback_lock_file(lock) on a committed lock_file, since the name will be set to "" by the latter, which is checked by the former.

But I am fine with the patch as is (have not tested it, though).

Ciao, Dscho

Bradford Smith· Jul 26, 2007, 18:48 UTC · re: Johannes Schindelin · lore

Re: [PATCH] use lockfile.c routines in git_commit_set_multivar()

On 7/26/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 21 quoted lines
> On Thu, 26 Jul 2007, Bradford C. Smith wrote:
>
> > +     /* fd is closed, so don't try to close it below. */
> > +     fd = -1;
> > +     /*
> > +      * lock is committed, so don't try to roll it back below.
> > +      * NOTE: Since lockfile.c keeps a linked list of all created
> > +      * lock_file structures, it isn't safe to free(lock).  It's
> > +      * better to just leave it hanging around.
> > +      */
> > +     lock = NULL;
> >       ret = 0;
> >
> >  out_free:
> >       if (0 <= fd)
> >               close(fd);
> > +     if (lock)
> > +             rollback_lock_file(lock);
>
> Wouldn't it be better to put the rollback_lock_file() into the if clause
> when commit failed?

Actually no. There are multiple goto statements that lead to out_free. It isn't even needed at the point that the commit failed, because commit_lock_file() sets the lock file name to "" even when it fails.

> Besides, I think you can safely call rollback_lock_file(lock) on a
> committed lock_file, since the name will be set to "" by the latter, which
> is checked by the former.

Quite right. I really just put in the comment and 'lock= NULL' line to increase readability. I wanted to make it very clear to the reader that the commit wouldn't be undone by the rollback.

> But I am fine with the patch as is (have not tested it, though).
Thanks!

FWIW, I have successfully run 'make test' and also verified that it behaves as I expect with my ~/.gitconfig symlink (in conjunction with the my other patch for resolving symlinks).

Best Regards,
Bradford
Junio C Hamano· Jul 27, 2007, 04:30 UTC · re: Bradford Smith · lore

Re: [PATCH] use lockfile.c routines in git_commit_set_multivar()

"Bradford Smith" <bradford.carl.smith@gmail.com> writes:
> FWIW, I have successfully run 'make test' and also verified that it
> behaves as I expect with my ~/.gitconfig symlink (in conjunction with
> the my other patch for resolving symlinks).

Existing "make test" testsuite is not an appropriate thing to say this patch is safe, as we do not have much symlinking in the test git repository there. Care to add a new test or two?

Junio C Hamano· Jul 27, 2007, 04:53 UTC · re: Junio C Hamano · lore

Re: [PATCH] use lockfile.c routines in git_commit_set_multivar()

Junio C Hamano <gitster@pobox.com> writes:
Show 9 quoted lines
> "Bradford Smith" <bradford.carl.smith@gmail.com> writes:
>
>> FWIW, I have successfully run 'make test' and also verified that it
>> behaves as I expect with my ~/.gitconfig symlink (in conjunction with
>> the my other patch for resolving symlinks).
>
> Existing "make test" testsuite is not an appropriate thing to
> say this patch is safe, as we do not have much symlinking in the
> test git repository there.  Care to add a new test or two?

How about this? On top of your "lockfile to keep symlink" and "set-multivar to use lockfile protocol" patches.

---
 t/t1300-repo-config.sh |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
Show changes to t/t1300-repo-config.sh +15 −0
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 1c43cc3..187ca2d 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -595,4 +595,19 @@ echo >>result
 
 test_expect_success '--null --get-regexp' 'cmp result expect'
 
+test_expect_success 'symlinked configuration' '
+
+	ln -s notyet myconfig &&
+	GIT_CONFIG=myconfig git config test.frotz nitfol &&
+	test -h myconfig &&
+	test -f notyet &&
+	test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol &&
+	GIT_CONFIG=myconfig git config test.xyzzy rezrov &&
+	test -h myconfig &&
+	test -f notyet &&
+	test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol &&
+	test "z$(GIT_CONFIG=notyet git config test.xyzzy)" = zrezrov
+
+'
+
 test_done
Johannes Schindelin· Jul 27, 2007, 09:05 UTC · re: Junio C Hamano · lore

Re: [PATCH] use lockfile.c routines in git_commit_set_multivar()

Hi,
On Thu, 26 Jul 2007, Junio C Hamano wrote:
> How about this?  On top of your "lockfile to keep symlink" and
> "set-multivar to use lockfile protocol" patches.
Looks very good to me!

Ciao, Dscho

Bradford Smith· Jul 27, 2007, 18:24 UTC · re: Junio C Hamano · lore

Re: [PATCH] use lockfile.c routines in git_commit_set_multivar()

That's great!

I've added this patch to my local branch and confirmed that all tests, including the new ones, run successfully.

Thanks!
Bradford
On 7/27/07, Junio C Hamano <gitster@pobox.com> wrote:
Show 46 quoted lines
> Junio C Hamano <gitster@pobox.com> writes:
>
> > "Bradford Smith" <bradford.carl.smith@gmail.com> writes:
> >
> >> FWIW, I have successfully run 'make test' and also verified that it
> >> behaves as I expect with my ~/.gitconfig symlink (in conjunction with
> >> the my other patch for resolving symlinks).
> >
> > Existing "make test" testsuite is not an appropriate thing to
> > say this patch is safe, as we do not have much symlinking in the
> > test git repository there.  Care to add a new test or two?
>
> How about this?  On top of your "lockfile to keep symlink" and
> "set-multivar to use lockfile protocol" patches.
>
> ---
>
>  t/t1300-repo-config.sh |   15 +++++++++++++++
>  1 files changed, 15 insertions(+), 0 deletions(-)
>
> diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
> index 1c43cc3..187ca2d 100755
> --- a/t/t1300-repo-config.sh
> +++ b/t/t1300-repo-config.sh
> @@ -595,4 +595,19 @@ echo >>result
>
>  test_expect_success '--null --get-regexp' 'cmp result expect'
>
> +test_expect_success 'symlinked configuration' '
> +
> +       ln -s notyet myconfig &&
> +       GIT_CONFIG=myconfig git config test.frotz nitfol &&
> +       test -h myconfig &&
> +       test -f notyet &&
> +       test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol &&
> +       GIT_CONFIG=myconfig git config test.xyzzy rezrov &&
> +       test -h myconfig &&
> +       test -f notyet &&
> +       test "z$(GIT_CONFIG=notyet git config test.frotz)" = znitfol &&
> +       test "z$(GIT_CONFIG=notyet git config test.xyzzy)" = zrezrov
> +
> +'
> +
>  test_done
>
>

← back to recent threads