D680: scmutil: handle conflicting files and dirs in origbackuppath
mbthomas (Mark Thomas)
phabricator at mercurial-scm.org
Tue Oct 10 01:26:18 UTC 2017
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGe68deea20e9a: scmutil: handle conflicting files and dirs in origbackuppath (authored by mbthomas, committed by ).
CHANGED PRIOR TO COMMIT
https://phab.mercurial-scm.org/D680?vs=2350&id=2543#toc
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D680?vs=2350&id=2543
REVISION DETAIL
https://phab.mercurial-scm.org/D680
AFFECTED FILES
mercurial/scmutil.py
tests/test-origbackup-conflict.t
CHANGE DETAILS
diff --git a/tests/test-origbackup-conflict.t b/tests/test-origbackup-conflict.t
new file mode 100644
--- /dev/null
+++ b/tests/test-origbackup-conflict.t
@@ -0,0 +1,118 @@
+Set up repo
+
+ $ cat << EOF >> $HGRCPATH
+ > [ui]
+ > origbackuppath=.hg/origbackups
+ > [merge]
+ > checkunknown=warn
+ > EOF
+ $ hg init repo
+ $ cd repo
+ $ echo base > base
+ $ hg add base
+ $ hg commit -m "base"
+
+Make a dir named b that contains a file
+
+ $ mkdir -p b
+ $ echo c1 > b/c
+ $ hg add b/c
+ $ hg commit -m "c1"
+ $ hg bookmark c1
+
+Peform an update that causes b/c to be backed up
+
+ $ hg up -q 0
+ $ mkdir -p b
+ $ echo c2 > b/c
+ $ hg up --verbose c1
+ resolving manifests
+ b/c: replacing untracked file
+ getting b/c
+ creating directory: $TESTTMP/repo/.hg/origbackups/b
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (activating bookmark c1)
+ $ test -f .hg/origbackups/b/c
+
+Make a file named b
+
+ $ hg up -q 0
+ $ echo b1 > b
+ $ hg add b
+ $ hg commit -m b1
+ created new head
+ $ hg bookmark b1
+
+Perform an update that causes b to be backed up - it should replace the backup b dir
+
+ $ hg up -q 0
+ $ echo b2 > b
+ $ hg up --verbose b1
+ resolving manifests
+ b: replacing untracked file
+ getting b
+ removing conflicting directory: $TESTTMP/repo/.hg/origbackups/b
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (activating bookmark b1)
+ $ test -f .hg/origbackups/b
+
+Perform an update the causes b/c to be backed up again - it should replace the backup b file
+
+ $ hg up -q 0
+ $ mkdir b
+ $ echo c3 > b/c
+ $ hg up --verbose c1
+ resolving manifests
+ b/c: replacing untracked file
+ getting b/c
+ creating directory: $TESTTMP/repo/.hg/origbackups/b
+ removing conflicting file: $TESTTMP/repo/.hg/origbackups/b
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (activating bookmark c1)
+ $ test -d .hg/origbackups/b
+
+Cause a symlink to be backed up that points to a valid location from the backup dir
+
+ $ hg up -q 0
+ $ mkdir ../sym-link-target
+ $ ln -s ../../../sym-link-target b
+ $ hg up b1
+ b: replacing untracked file
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (activating bookmark b1)
+ $ readlink .hg/origbackups/b
+ ../../../sym-link-target
+
+Perform an update that causes b/c to be backed up again - it should not go into the target dir
+
+ $ hg up -q 0
+ $ mkdir b
+ $ echo c4 > b/c
+ $ hg up --verbose c1
+ resolving manifests
+ b/c: replacing untracked file
+ getting b/c
+ creating directory: $TESTTMP/repo/.hg/origbackups/b
+ removing conflicting file: $TESTTMP/repo/.hg/origbackups/b
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (activating bookmark c1)
+ $ cat .hg/origbackups/b/c
+ c4
+ $ ls ../sym-link-target
+
+Incorrectly configure origbackuppath to be under a file
+
+ $ echo data > .hg/badorigbackups
+ $ hg up -q 0
+ $ mkdir b
+ $ echo c5 > b/c
+ $ hg up --verbose c1 --config ui.origbackuppath=.hg/badorigbackups
+ resolving manifests
+ b/c: replacing untracked file
+ getting b/c
+ creating directory: $TESTTMP/repo/.hg/badorigbackups/b
+ abort: Not a directory: '$TESTTMP/repo/.hg/badorigbackups/b'
+ [255]
+ $ cat .hg/badorigbackups
+ data
+
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -38,6 +38,7 @@
similar,
url,
util,
+ vfs,
)
if pycompat.osname == 'nt':
@@ -573,18 +574,34 @@
Fall back to default (filepath with .orig suffix) if not specified
'''
origbackuppath = ui.config('ui', 'origbackuppath')
- if origbackuppath is None:
+ if not origbackuppath:
return filepath + ".orig"
- filepathfromroot = os.path.relpath(filepath, start=repo.root)
- fullorigpath = repo.wjoin(origbackuppath, filepathfromroot)
+ # Convert filepath from an absolute path into a path inside the repo.
+ filepathfromroot = util.normpath(os.path.relpath(filepath,
+ start=repo.root))
+
+ origvfs = vfs.vfs(repo.wjoin(origbackuppath))
+ origbackupdir = origvfs.dirname(filepathfromroot)
+ if not origvfs.isdir(origbackupdir) or origvfs.islink(origbackupdir):
+ ui.note(_('creating directory: %s\n') % origvfs.join(origbackupdir))
- origbackupdir = repo.vfs.dirname(fullorigpath)
- if not repo.vfs.exists(origbackupdir):
- ui.note(_('creating directory: %s\n') % origbackupdir)
- util.makedirs(origbackupdir)
+ # Remove any files that conflict with the backup file's path
+ for f in reversed(list(util.finddirs(filepathfromroot))):
+ if origvfs.isfileorlink(f):
+ ui.note(_('removing conflicting file: %s\n')
+ % origvfs.join(f))
+ origvfs.unlink(f)
+ break
- return fullorigpath
+ origvfs.makedirs(origbackupdir)
+
+ if origvfs.isdir(filepathfromroot):
+ ui.note(_('removing conflicting directory: %s\n')
+ % origvfs.join(filepathfromroot))
+ origvfs.rmtree(filepathfromroot, forcibly=True)
+
+ return origvfs.join(filepathfromroot)
class _containsnode(object):
"""proxy __contains__(node) to container.__contains__ which accepts revs"""
To: mbthomas, ryanmce, #hg-reviewers, durham, yuja, ikostia
Cc: kiilerix, quark, ikostia, yuja, durham, mercurial-devel
More information about the Mercurial-devel
mailing list