Re: [PATCH v2] repack.c: Use move_temp_to_file() instead of rename()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Torsten Bögershausen <tboegi@xxxxxx> writes:

> In a1bbc6c0 a shell command "mv -f" was replaced with the rename() function.
>
> Use move_temp_to_file() from sha1_file.c instead of rename().
> This is in line with the handling of other Git internal tmp files,
> and calls adjust_shared_perm()

>
> Signed-off-by: Torsten Bögershausen <tboegi@xxxxxx>
> ---
> Thanks for all comments.
> I haven't been able to reproduce the problem here.
> Tips and information how to reproduce it are wellcome.
>
> I think this patch makes sense to support core.sharedRepository(),
> but I haven't made a test case for the pack/idx files.
>
> Jochen, doess this patch fix your problem, or do we need
> another patch on top of this?

Turning the call to rename(2) in the last hunk in your patch to
move_temp_to_file() may be an improvement, but the other changes are
wrong, I think.

There are two big differences between the rename(2) used here and
move_temp_to_file().  You need to understand what move_temp_to_file()
is from its name.

 - It is meant to move a temporary file we create ourselves, and the
   most important characteristic of such a file is that we do not
   create it read-only.  The function uses platform's rename(2) and
   returns a failure if the platform's rename(2) fails, but that is
   not a problem even on Windows because of this.

 - When returning a failure, it unlinks the temporary file.  This
   unlinking is necessary to clean up after our half-done mess.

The other two calls to rename(2) you changed in the patch are *not*
about turning a newly created temporary file into the final one.
They are about moving existing packfiles away just in case we fail
in the later phases of the command so that they can be moved back to
their original name to restore the state before we started, and
actually moving them back to their original name.  We do not want to
remove these files.  The platform's rename(2) must do the right
thing in these two calls and there is no guarantee these existing
packfiles are read-write.

Earlier, I said that turning the call to rename(2) in the last hunk
in your patch to move_temp_to_file() may be an improvement, because
I thought that it is a good thing that the latter makes a call to
adjust_shared_perm().

But after a closer inspection, I no longer think that hunk is an
improvement.  These new packfiles were created by pack-objects,
which finishes each packfile it produces by calling
finish_tmp_packfile(), and that is where adjust_shared_perm()
happens already.  As far as "pack-objects" that was called from
"repack" is concerned, these new packfiles are not "temporary"; they
are finished product.  It may be OK to remove them as part of
"rewind back to the original state, as a later phase of repack
failed" if we saw a failure (but note that the original
"git-repack.sh" didn't), but a plain vanilla rename(2) without any
frills is what we want to happen to them.

>  builtin/repack.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/builtin/repack.c b/builtin/repack.c
> index ba66c6e..4b6d663 100644
> --- a/builtin/repack.c
> +++ b/builtin/repack.c
> @@ -271,7 +271,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>  				if (unlink(fname_old))
>  					failed = 1;
>  
> -			if (!failed && rename(fname, fname_old)) {
> +			if (!failed && move_temp_to_file(fname, fname_old)) {
>  				free(fname);
>  				failed = 1;
>  				break;
> @@ -288,7 +288,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>  			char *fname, *fname_old;
>  			fname = mkpathdup("%s/%s", packdir, item->string);
>  			fname_old = mkpath("%s/old-%s", packdir, item->string);
> -			if (rename(fname_old, fname))
> +			if (move_temp_to_file(fname_old, fname))
>  				string_list_append(&rollback_failure, fname);
>  			free(fname);
>  		}
> @@ -324,7 +324,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
>  				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
>  				chmod(fname_old, statbuffer.st_mode);
>  			}
> -			if (rename(fname_old, fname))
> +			if (move_temp_to_file(fname_old, fname))
>  				die_errno(_("renaming '%s' failed"), fname_old);
>  			free(fname);
>  			free(fname_old);
> -- 
> 1.8.5.2
>
> -- 
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]