[PATCH 2 of 4 shelve-ext v2] shelve: make shelvestate use simplekeyvaluefile

Kostia Balytskyi ikostia at fb.com
Mon Apr 10 12:04:50 EDT 2017


# HG changeset patch
# User Kostia Balytskyi <ikostia at fb.com>
# Date 1491839190 25200
#      Mon Apr 10 08:46:30 2017 -0700
# Node ID 73c4ca5490a9b5202ffb00ea0bea76c171491e4a
# Parent  5dc11b1531f701844001b0723c4b8b97c2e55217
shelve: make shelvestate use simplekeyvaluefile

Currently shelvestate uses line ordering to differentiate fields. This
makes it hard for extensions to wrap shelve, since if two alternative
versions of code add a new line, correct merging is going to be problematic.
simplekeyvaluefile was introduced fot this purpose specifically.

After this patch:
- shelve will always write a simplekeyvaluefile, unless 'shelve.oldstatefile'
is on
- unshelve will check the first line of the file and if it has '=' sign,
will treat the file as a simplekeyvalue one. Otherwise, it will try to read
an old-style statefile.

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -166,6 +166,10 @@ class shelvedstate(object):
 
     Handles saving and restoring a shelved state. Ensures that different
     versions of a shelved state are possible and handles them appropriately.
+
+    By default, simplekeyvaluefile is used. The following config option
+    allows one to enforce the old position-based state file to be used:
+    shelve.oldstatefile
     """
     _version = 1
     _filename = 'shelvedstate'
@@ -175,17 +179,32 @@ class shelvedstate(object):
     _noactivebook = ':no-active-bookmark'
 
     @classmethod
+    def iskeyvaluebased(cls, repo):
+        """Determine whether state file is simple lines or simplekeyvaluefile"""
+        if repo.ui.configbool('shelve', 'oldstatefile', False):
+            return True
+        fp = repo.vfs(cls._filename)
+        try:
+            firstline = fp.readline()
+            return '=' in firstline
+        finally:
+            fp.close()
+
+    @classmethod
     def load(cls, repo):
         # order is important, please do not change
         keys = ['version', 'name', 'originalwctx', 'pendingctx', 'parents',
                 'nodestoprune', 'branchtorestore', 'keep', 'activebook']
         st = {}
-        fp = repo.vfs(cls._filename)
-        try:
-            for key in keys:
-                st[key] = fp.readline().strip()
-        finally:
-            fp.close()
+        if cls.iskeyvaluebased(repo):
+            st = scmutil.simplekeyvaluefile(repo.vfs, cls._filename).read()
+        else:
+            fp = repo.vfs(cls._filename)
+            try:
+                for key in keys:
+                    st[key] = fp.readline().strip()
+            finally:
+                fp.close()
 
         # some basic syntactic verification and transformation
         try:
@@ -222,6 +241,22 @@ class shelvedstate(object):
     @classmethod
     def save(cls, repo, name, originalwctx, pendingctx, nodestoprune,
              branchtorestore, keep=False, activebook=''):
+        if not repo.ui.configbool('shelve', 'oldstatefile', False):
+            info = {
+                "version": str(cls._version),
+                "name": name,
+                "originalwctx": nodemod.hex(originalwctx.node()),
+                "pendingctx": nodemod.hex(pendingctx.node()),
+                "parents": ' '.join([nodemod.hex(p)
+                                     for p in repo.dirstate.parents()]),
+                "nodestoprune": ' '.join([nodemod.hex(n)
+                                          for n in nodestoprune]),
+                "branchtorestore": branchtorestore,
+                "keep": cls._keep if keep else cls._nokeep,
+                "activebook": activebook or cls._noactivebook
+            }
+            scmutil.simplekeyvaluefile(repo.vfs, cls._filename).write(info)
+            return
         fp = repo.vfs(cls._filename, 'wb')
         fp.write('%i\n' % cls._version)
         fp.write('%s\n' % name)
diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -1578,7 +1578,7 @@ shelve on new branch, conflict with prev
   $ echo "ccc" >> a
   $ hg status
   M a
-  $ hg unshelve
+  $ hg unshelve --config shelve.oldstatefile=on
   unshelving change 'default'
   temporarily committing pending changes (restore with 'hg unshelve --abort')
   rebasing shelved changes


More information about the Mercurial-devel mailing list