D5851: scmutil: introduce a new backuppath() to replace origpath()

martinvonz (Martin von Zweigbergk) phabricator at mercurial-scm.org
Tue Feb 5 12:53:10 EST 2019

martinvonz created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

  Unlike most functions in our codebase, origpath() takes a path that is
  relative to cwd. This commit introduces a replacement for
  origpath(). The new function takes a path that is relative to the repo
  root. There is a lot of duplication between the two, but I intend to
  remove origpath() within the next few commits, so it won't be a
  maintenance burden.
  origpath() is also a little weird in that it returns either a a
  cwd-relative path or an absolute path. It needs to be able to return a
  path outside the repo, so it makes sense that it can return an
  absolute path. However, it would be simpler to always return an
  absolute path. At first I attempted to change that too in the new
  function. That wasn't trivial since the returned path often gets
  displayed to the user (things like "moving file dir/file to
  dir/file.orig") and we don't want to always display absolute paths
  there. It should probably be the caller's responsibility to convert
  back to repo-relative, or cwd-relative, path if desirable. However, we
  can safely do that as a follow-up later, since the caller has to call
  repo.wjoin() on the result anyway.

  rHG Mercurial




diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -838,6 +838,43 @@
         return None
     return vfs.vfs(repo.wvfs.join(origbackuppath))
+def backuppath(ui, repo, filepath):
+    '''customize where working copy backup files (.orig files) are created
+    Fetch user defined path from config file: [ui] origbackuppath = <path>
+    Fall back to default (filepath with .orig suffix) if not specified
+    filepath is repo-relative
+    Returns a repo-relative path *or* an absolute path. The caller is thus
+    expected to call repo.wjoin() on the result before passing it to e.g.
+    util.rename().
+    '''
+    origvfs = getorigvfs(ui, repo)
+    if origvfs is None:
+        return filepath + ".orig"
+    origbackupdir = origvfs.dirname(filepath)
+    if not origvfs.isdir(origbackupdir) or origvfs.islink(origbackupdir):
+        ui.note(_('creating directory: %s\n') % origvfs.join(origbackupdir))
+        # Remove any files that conflict with the backup file's path
+        for f in reversed(list(util.finddirs(filepath))):
+            if origvfs.isfileorlink(f):
+                ui.note(_('removing conflicting file: %s\n')
+                        % origvfs.join(f))
+                origvfs.unlink(f)
+                break
+        origvfs.makedirs(origbackupdir)
+    if origvfs.isdir(filepath) and not origvfs.islink(filepath):
+        ui.note(_('removing conflicting directory: %s\n')
+                % origvfs.join(filepath))
+        origvfs.rmtree(filepath, forcibly=True)
+    return origvfs.join(filepath)
 def origpath(ui, repo, filepath):
     '''customize where .orig files are created

To: martinvonz, #hg-reviewers
Cc: mercurial-devel

More information about the Mercurial-devel mailing list