diff -r 153e4e05e9b3 -r 6fad8059a970 mercurial/scmutil.py --- a/mercurial/scmutil.py Sun Oct 01 12:21:50 2017 +0100 +++ b/mercurial/scmutil.py Mon Oct 02 14:05:30 2017 -0700 @@ -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"""