[PATCH] update: do not remove cwd

Durham Goode durham at fb.com
Tue Aug 30 12:45:48 EDT 2016



On 8/29/16 11:50 AM, Stanislau Hlebik wrote:
> # HG changeset patch
> # User Stanislau Hlebik <stash at fb.com>
> # Date 1472496038 25200
> #      Mon Aug 29 11:40:38 2016 -0700
> # Node ID e1962781ce84040746ef79c0084b8fd70cfcd4b4
> # Parent  318e2b600b80e4ed3c6f37df46ec7544f60d4c0b
> update: do not remove cwd
>
> During update directories are deleted as soon as they have no entries.
> But current working directory shouldn't be deleted because it
> causes problems for users after hg finishes. Also it makes complex commands
> like 'hg split' fail.
Won't this cause update to fail if the parent directory is to be deleted 
and replaced with a file?  I'd almost err towards just printing a 
warning message when the current working directory is deleted (and 
recommending they cd to the root of their repo).
>
> diff --git a/mercurial/merge.py b/mercurial/merge.py
> --- a/mercurial/merge.py
> +++ b/mercurial/merge.py
> @@ -1043,7 +1043,7 @@
>               repo.ui.note(_("removing %s\n") % f)
>           audit(f)
>           try:
> -            unlink(wjoin(f), ignoremissing=True)
> +            unlink(wjoin(f), ignoremissing=True, donotremovecwd=True)
>           except OSError as inst:
>               repo.ui.warn(_("update failed to remove %s: %s!\n") %
>                            (f, inst.strerror))
> diff --git a/mercurial/posix.py b/mercurial/posix.py
> --- a/mercurial/posix.py
> +++ b/mercurial/posix.py
> @@ -23,6 +23,7 @@
>   from .i18n import _
>   from . import (
>       encoding,
> +    osutil,
>   )
>   
>   posixfile = open
> @@ -496,7 +497,31 @@
>   def makedir(path, notindexed):
>       os.mkdir(path)
>   
> -def unlinkpath(f, ignoremissing=False):
> +def removedirs(name, donotremovecwd=False):
> +    """special version of os.removedirs that does not remove symlinked
This mentions symlinks are also affected.  That seems unrelated to the 
purpose of this patch though, and I think we do want to allow symlinks 
to be deleted if their target contains files.
> +    directories or junction points if they actually contain files"""
> +    if not donotremovecwd:
> +        return os.removedirs(name)
> +
> +    cwd = os.getcwd()
> +    if cwd == name:
> +        return
> +    if osutil.listdir(name):
> +        return
> +    os.rmdir(name)
> +    head, tail = os.path.split(name)
> +    if not tail:
> +        head, tail = os.path.split(head)
> +    while head and tail:
> +        try:
> +            if osutil.listdir(head) or cwd == head:
> +                return
> +            os.rmdir(head)
> +        except (ValueError, OSError):
> +            break
> +        head, tail = os.path.split(head)
> +
> +def unlinkpath(f, ignoremissing=False, donotremovecwd=False):
>       """unlink and remove the directory if it is empty"""
>       try:
>           os.unlink(f)
> @@ -505,7 +530,7 @@
>               raise
>       # try removing directories that might now be empty
>       try:
> -        os.removedirs(os.path.dirname(f))
> +        removedirs(os.path.dirname(f), donotremovecwd)
>       except OSError:
>           pass
>   
> diff --git a/mercurial/windows.py b/mercurial/windows.py
> --- a/mercurial/windows.py
> +++ b/mercurial/windows.py
> @@ -369,11 +369,14 @@
>       If gid is None, return the name of the current group."""
>       return None
>   
> -def removedirs(name):
> +def removedirs(name, donotremovecwd=False):
>       """special version of os.removedirs that does not remove symlinked
>       directories or junction points if they actually contain files"""
>       if osutil.listdir(name):
>           return
> +    cwd = os.getcwd()
> +    if donotremovecwd and cwd == name:
> +        return
>       os.rmdir(name)
>       head, tail = os.path.split(name)
>       if not tail:
> @@ -382,12 +385,14 @@
>           try:
>               if osutil.listdir(head):
>                   return
> +            if donotremovecwd and cwd == head:
> +                return
>               os.rmdir(head)
>           except (ValueError, OSError):
>               break
>           head, tail = os.path.split(head)
>   
> -def unlinkpath(f, ignoremissing=False):
> +def unlinkpath(f, ignoremissing=False, donotremovecwd=False):
>       """unlink and remove the directory if it is empty"""
>       try:
>           unlink(f)
> @@ -396,7 +401,7 @@
>               raise
>       # try removing directories that might now be empty
>       try:
> -        removedirs(os.path.dirname(f))
> +        removedirs(os.path.dirname(f), donotremovecwd)
>       except OSError:
>           pass
>   
> diff --git a/tests/test-update-names.t b/tests/test-update-names.t
> --- a/tests/test-update-names.t
> +++ b/tests/test-update-names.t
> @@ -72,3 +72,13 @@
>     $ cd ..
>   
>   #endif
> +
> +Test that cwd is not deleted during update
> +  $ hg init r4 && cd r4
> +  $ mkdir dir
> +  $ cd dir
> +  $ echo a > a
> +  $ hg add a
> +  $ hg ci -m "file and dir"
> +  $ hg up -q null
> +  $ cd .



More information about the Mercurial-devel mailing list