changeset 50366:a445194f0a4d stable

backup: fix issue when the backup end up in a different directory Because of store encoding, we might end up with the backup in a different directory than the initial copy (for example if the backup path make it cross the 120 char limit). This can create crash, especially since 6.4 where backup are used during revlog split. Making sure the directory exists fixes these crash We added a test covering this case. Strictly speaking, this has always been broken, however the new code in 6.4 triggers it more easily.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 03 May 2023 00:16:38 +0200
parents d1d458fb96a5
children fc445f8abcf9
files mercurial/transaction.py tests/test-transaction-rollback-on-revlog-split.t
diffstat 2 files changed, 13 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/transaction.py	Wed May 03 00:12:34 2023 +0200
+++ b/mercurial/transaction.py	Wed May 03 00:16:38 2023 +0200
@@ -414,6 +414,11 @@
         if vfs.exists(file):
             filepath = vfs.join(file)
             backuppath = vfs.join(backupfile)
+            # store encoding may result in different directory here.
+            # so we have to ensure the destination directory exist
+            final_dir_name = os.path.dirname(backuppath)
+            util.makedirs(final_dir_name, mode=vfs.createmode, notindexed=True)
+            # then we can copy the backup
             util.copyfile(filepath, backuppath, hardlink=hardlink)
         else:
             backupfile = b''
--- a/tests/test-transaction-rollback-on-revlog-split.t	Wed May 03 00:12:34 2023 +0200
+++ b/tests/test-transaction-rollback-on-revlog-split.t	Wed May 03 00:16:38 2023 +0200
@@ -1,6 +1,9 @@
 Test correctness of revlog inline -> non-inline transition
 ----------------------------------------------------------
 
+We test various file length and naming pattern as this created issue in the
+past.
+
 Helper extension to intercept renames and kill process
 
   $ cat > $TESTTMP/intercept_before_rename.py << EOF
@@ -80,6 +83,7 @@
   > file
   > Directory_With,Special%Char/Complex_File.babar
   > foo/bar/babar_celeste/foo
+  > 1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/f
   > "
   $ for f in $files; do
   >     mkdir -p `dirname $f`
@@ -179,7 +183,7 @@
   $ f -s .hg/store/data/file*
   .hg/store/data/file.i: size=1174
   $ hg tip
-  changeset:   1:272bd31be9b8
+  changeset:   1:cc8dfb126534
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
@@ -249,7 +253,7 @@
   $ f -s .hg/store/data/file*
   .hg/store/data/file.i: size=1174
   $ hg tip
-  changeset:   1:272bd31be9b8
+  changeset:   1:cc8dfb126534
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
@@ -313,7 +317,7 @@
   $ f -s .hg/store/data/file*
   .hg/store/data/file.i: size=1174
   $ hg tip
-  changeset:   1:272bd31be9b8
+  changeset:   1:cc8dfb126534
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
@@ -353,7 +357,7 @@
 
 
   $ hg tip
-  changeset:   1:272bd31be9b8
+  changeset:   1:cc8dfb126534
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000