Patchwork D9677: upgrade: use copy+delete instead of rename while creating backup

login
register
mail settings
Submitter phabricator
Date Dec. 31, 2020, 4:43 p.m.
Message ID <differential-rev-PHID-DREV-jovvc5gtf6svsdc3bql5-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47988/
State New
Headers show

Comments

phabricator - Dec. 31, 2020, 4:43 p.m.
pulkit created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  A lot of times, we do an upgrade operation which does not touches all the parts
  of the stores. But right not, we have a blind logic which processes everything.
  To selectively upgrade parts of repository, we need to persist existing data
  which is untouched.
  
  However while creating current repository backup, we rename the whole store
  leaving no option to persist untouched files.
  
  We switch to copy+delete so that we can only delete data files which are changed
  by the operation and leave rest untouched.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9677

AFFECTED FILES
  mercurial/upgrade_utils/engine.py
  tests/test-upgrade-repo.t

CHANGE DETAILS




To: pulkit, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-upgrade-repo.t b/tests/test-upgrade-repo.t
--- a/tests/test-upgrade-repo.t
+++ b/tests/test-upgrade-repo.t
@@ -615,10 +615,6 @@ 
   data
   fncache
   phaseroots
-  undo
-  undo.backup.fncache
-  undo.backupfiles
-  undo.phaseroots
 
 unless --no-backup is passed
 
diff --git a/mercurial/upgrade_utils/engine.py b/mercurial/upgrade_utils/engine.py
--- a/mercurial/upgrade_utils/engine.py
+++ b/mercurial/upgrade_utils/engine.py
@@ -414,7 +414,35 @@ 
     """
     # TODO: don't blindly rename everything in store
     # There can be upgrades where store is not touched at all
-    util.rename(currentrepo.spath, backupvfs.join(b'store'))
+    backupstorevfs = vfsmod.vfs(backupvfs.join(b'store'))
+    util.makedirs(backupstorevfs.base)
+    for path, kind, st in sorted(currentrepo.store.vfs.readdir(b'', stat=True)):
+        # Skip transaction related files.
+        if path.startswith(b'undo'):
+            continue
+        # Only copy regular files.
+        if kind != stat.S_IFREG:
+            continue
+        # Skip other skipped files.
+        if path in (b'lock',):
+            continue
+        src = currentrepo.store.rawvfs.join(path)
+        dst = backupstorevfs.join(path)
+        util.copyfile(src, dst, copystat=True)
+    if currentrepo.svfs.exists(b'data'):
+        util.copyfiles(
+            currentrepo.svfs.join(b'data'),
+            backupstorevfs.join(b'data'),
+            hardlink=False,
+        )
+    if currentrepo.svfs.exists(b'meta'):
+        util.copyfiles(
+            currentrepo.svfs.join(b'meta'),
+            backupstorevfs.join(b'meta'),
+            hardlink=False,
+        )
+
+    currentrepo.vfs.rmtree(b'store', forcibly=True)
     util.rename(upgradedrepo.spath, currentrepo.spath)
 
 
@@ -514,10 +542,4 @@ 
     )
     scmutil.writereporequirements(srcrepo, upgrade_op.new_requirements)
 
-    # The lock file from the old store won't be removed because nothing has a
-    # reference to its new location. So clean it up manually. Alternatively, we
-    # could update srcrepo.svfs and other variables to point to the new
-    # location. This is simpler.
-    backupvfs.unlink(b'store/lock')
-
     return backuppath