[PATCH V2] update: fix edge-case with update.atomic-file and read-only files

Yuya Nishihara yuya at tcha.org
Sun Jan 13 21:20:50 EST 2019


On Sun, 13 Jan 2019 10:38:37 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld <boris.feld at octobus.net>
> # Date 1547128621 -3600
> #      Thu Jan 10 14:57:01 2019 +0100
> # Node ID d46392ed9a76773561c74c8df2063aaad4c3c952
> # Parent  963462786f6e028563bcedc9008622e0f3b59c86
> # EXP-Topic atomic-update-read-only
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r d46392ed9a76
> update: fix edge-case with update.atomic-file and read-only files
> 
> We used to create the tempfile with the original file mode. That means
> creating a read-only tempfile when the original file is read-only, which crash
> if we need to write on the tempfile.
> 
> The file in the working directory ends up being writable with and without the
> atomic update config, so the behavior is the same.
> 
> diff --git a/mercurial/util.py b/mercurial/util.py
> --- a/mercurial/util.py
> +++ b/mercurial/util.py
> @@ -2045,7 +2045,7 @@ def splitpath(path):
>      function if need.'''
>      return path.split(pycompat.ossep)
>  
> -def mktempcopy(name, emptyok=False, createmode=None):
> +def mktempcopy(name, emptyok=False, createmode=None, enforcewritable=False):
>      """Create a temporary file with the same contents from name
>  
>      The permission bits are copied from the original file.
> @@ -2062,6 +2062,15 @@ def mktempcopy(name, emptyok=False, crea
>      # what we want.  If the original file already exists, just copy
>      # its mode.  Otherwise, manually obey umask.
>      copymode(name, temp, createmode)
> +
> +    # If the resulting temporary file needs to be writable enforce it now.
> +    # createmode argument of copy mode is not used when the original file
> +    # already exists so we need to do it outside of it
> +    if enforcewritable:
> +        oldstat = filestat.frompath(temp)
> +        newstat = oldstat.stat.st_mode | stat.S_IWUSR
> +        os.chmod(temp, newstat)

I meant it would be better handled in copymode() where the chmod() business
is handled.

  os.chmod(dst, st_mode | addmode)


More information about the Mercurial-devel mailing list