git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[StGit PATCH 03/10] Upgrade older stacks to newest version

From
Karl Hasselström <kha@treskal.com>
Date
Nov 25, 2007, 20:51 UTC
Message-ID
<20071125205112.7823.54437.stgit@yoghurt>
In-Reply-To
<20071125203717.7823.70046.stgit@yoghurt>

This is of course needed by the new infrastructure as well. So break it out into its own file, where it can be used by both new and old infrastructure. This has the added benefit of making it easy to see that the upgrade code doesn't depend on anything it shouldn't.

Signed-off-by: Karl Hasselström <kha@treskal.com>
---
 stgit/lib/git.py          |    7 +++
 stgit/lib/stack.py        |    3 +
 stgit/lib/stackupgrade.py |   96 +++++++++++++++++++++++++++++++++++++++++++
 stgit/stack.py            |  100 +++------------------------------------------
 4 files changed, 112 insertions(+), 94 deletions(-)
 create mode 100644 stgit/lib/stackupgrade.py
diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index 120ea35..c4011f9 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -160,6 +160,13 @@ class Refs(object):
         if self.__refs == None:
             self.__cache_refs()
         return self.__repository.get_commit(self.__refs[ref])
+    def exists(self, ref):
+        try:
+            self.get(ref)
+        except KeyError:
+            return False
+        else:
+            return True
     def set(self, ref, commit, msg):
         if self.__refs == None:
             self.__cache_refs()
diff --git a/stgit/lib/stack.py b/stgit/lib/stack.py
index 5a34592..8fc8b08 100644
--- a/stgit/lib/stack.py
+++ b/stgit/lib/stack.py
@@ -1,6 +1,6 @@
 import os.path
 from stgit import exception, utils
-from stgit.lib import git
+from stgit.lib import git, stackupgrade
 
 class Patch(object):
     def __init__(self, stack, name):
@@ -128,6 +128,7 @@ class Stack(object):
             raise exception.StgException('%s: no such branch' % name)
         self.__patchorder = PatchOrder(self)
         self.__patches = Patches(self)
+        stackupgrade.update_to_current_format_version(repository, name)
     name = property(lambda self: self.__name)
     repository = property(lambda self: self.__repository)
     patchorder = property(lambda self: self.__patchorder)
diff --git a/stgit/lib/stackupgrade.py b/stgit/lib/stackupgrade.py
new file mode 100644
index 0000000..00bfdf0
--- /dev/null
+++ b/stgit/lib/stackupgrade.py
@@ -0,0 +1,96 @@
+import os.path
+from stgit import utils
+from stgit.out import out
+from stgit.config import config
+
+# The current StGit metadata format version.
+FORMAT_VERSION = 2
+
+def format_version_key(branch):
+    return 'branch.%s.stgit.stackformatversion' % branch
+
+def update_to_current_format_version(repository, branch):
+    """Update a potentially older StGit directory structure to the latest
+    version. Note: This function should depend as little as possible
+    on external functions that may change during a format version
+    bump, since it must remain able to process older formats."""
+
+    branch_dir = os.path.join(repository.directory, 'patches', branch)
+    key = format_version_key(branch)
+    old_key = 'branch.%s.stgitformatversion' % branch
+    def get_format_version():
+        """Return the integer format version number, or None if the
+        branch doesn't have any StGit metadata at all, of any version."""
+        fv = config.get(key)
+        ofv = config.get(old_key)
+        if fv:
+            # Great, there's an explicitly recorded format version
+            # number, which means that the branch is initialized and
+            # of that exact version.
+            return int(fv)
+        elif ofv:
+            # Old name for the version info: upgrade it.
+            config.set(key, ofv)
+            config.unset(old_key)
+            return int(ofv)
+        elif os.path.isdir(os.path.join(branch_dir, 'patches')):
+            # There's a .git/patches/<branch>/patches dirctory, which
+            # means this is an initialized version 1 branch.
+            return 1
+        elif os.path.isdir(branch_dir):
+            # There's a .git/patches/<branch> directory, which means
+            # this is an initialized version 0 branch.
+            return 0
+        else:
+            # The branch doesn't seem to be initialized at all.
+            return None
+    def set_format_version(v):
+        out.info('Upgraded branch %s to format version %d' % (branch, v))
+        config.set(key, '%d' % v)
+    def mkdir(d):
+        if not os.path.isdir(d):
+            os.makedirs(d)
+    def rm(f):
+        if os.path.exists(f):
+            os.remove(f)
+    def rm_ref(ref):
+        if repository.refs.exists(ref):
+            repository.refs.delete(ref)
+
+    # Update 0 -> 1.
+    if get_format_version() == 0:
+        mkdir(os.path.join(branch_dir, 'trash'))
+        patch_dir = os.path.join(branch_dir, 'patches')
+        mkdir(patch_dir)
+        refs_base = 'refs/patches/%s' % branch
+        for patch in (file(os.path.join(branch_dir, 'unapplied')).readlines()
+                      + file(os.path.join(branch_dir, 'applied')).readlines()):
+            patch = patch.strip()
+            os.rename(os.path.join(branch_dir, patch),
+                      os.path.join(patch_dir, patch))
+            topfield = os.path.join(patch_dir, patch, 'top')
+            if os.path.isfile(topfield):
+                top = utils.read_string(topfield, False)
+            else:
+                top = None
+            if top:
+                repository.refs.set(refs_base + '/' + patch,
+                                    repository.get_commit(top), 'StGit upgrade')
+        set_format_version(1)
+
+    # Update 1 -> 2.
+    if get_format_version() == 1:
+        desc_file = os.path.join(branch_dir, 'description')
+        if os.path.isfile(desc_file):
+            desc = utils.read_string(desc_file)
+            if desc:
+                config.set('branch.%s.description' % branch, desc)
+            rm(desc_file)
+        rm(os.path.join(branch_dir, 'current'))
+        rm_ref('refs/bases/%s' % branch)
+        set_format_version(2)
+
+    # Make sure we're at the latest version.
+    if not get_format_version() in [None, FORMAT_VERSION]:
+        raise StackException('Branch %s is at format version %d, expected %d'
+                             % (branch, get_format_version(), FORMAT_VERSION))
diff --git a/stgit/stack.py b/stgit/stack.py
index f93d842..29e92c9 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -28,7 +28,7 @@ from stgit.run import *
 from stgit import git, basedir, templates
 from stgit.config import config
 from shutil import copyfile
-
+from stgit.lib import git as libgit, stackupgrade
 
 # stack exception class
 class StackException(StgException):
@@ -279,9 +279,6 @@ class Patch(StgitObject):
         self._set_field('log', value)
         self.__update_log_ref(value)
 
-# The current StGIT metadata format version.
-FORMAT_VERSION = 2
-
 class PatchSet(StgitObject):
     def __init__(self, name = None):
         try:
@@ -349,7 +346,8 @@ class PatchSet(StgitObject):
     def is_initialised(self):
         """Checks if series is already initialised
         """
-        return bool(config.get(self.format_version_key()))
+        return config.get(stackupgrade.format_version_key(self.get_name())
+                          ) != None
 
 
 def shortlog(patches):
@@ -368,7 +366,8 @@ class Series(PatchSet):
 
         # Update the branch to the latest format version if it is
         # initialized, but don't touch it if it isn't.
-        self.update_to_current_format_version()
+        stackupgrade.update_to_current_format_version(
+            libgit.Repository.default(), self.get_name())
 
         self.__refs_base = 'refs/patches/%s' % self.get_name()
 
@@ -382,92 +381,6 @@ class Series(PatchSet):
         # trash directory
         self.__trash_dir = os.path.join(self._dir(), 'trash')
 
-    def format_version_key(self):
-        return 'branch.%s.stgit.stackformatversion' % self.get_name()
-
-    def update_to_current_format_version(self):
-        """Update a potentially older StGIT directory structure to the
-        latest version. Note: This function should depend as little as
-        possible on external functions that may change during a format
-        version bump, since it must remain able to process older formats."""
-
-        branch_dir = os.path.join(self._basedir(), 'patches', self.get_name())
-        def get_format_version():
-            """Return the integer format version number, or None if the
-            branch doesn't have any StGIT metadata at all, of any version."""
-            fv = config.get(self.format_version_key())
-            ofv = config.get('branch.%s.stgitformatversion' % self.get_name())
-            if fv:
-                # Great, there's an explicitly recorded format version
-                # number, which means that the branch is initialized and
-                # of that exact version.
-                return int(fv)
-            elif ofv:
-                # Old name for the version info, upgrade it
-                config.set(self.format_version_key(), ofv)
-                config.unset('branch.%s.stgitformatversion' % self.get_name())
-                return int(ofv)
-            elif os.path.isdir(os.path.join(branch_dir, 'patches')):
-                # There's a .git/patches/<branch>/patches dirctory, which
-                # means this is an initialized version 1 branch.
-                return 1
-            elif os.path.isdir(branch_dir):
-                # There's a .git/patches/<branch> directory, which means
-                # this is an initialized version 0 branch.
-                return 0
-            else:
-                # The branch doesn't seem to be initialized at all.
-                return None
-        def set_format_version(v):
-            out.info('Upgraded branch %s to format version %d' % (self.get_name(), v))
-            config.set(self.format_version_key(), '%d' % v)
-        def mkdir(d):
-            if not os.path.isdir(d):
-                os.makedirs(d)
-        def rm(f):
-            if os.path.exists(f):
-                os.remove(f)
-        def rm_ref(ref):
-            if git.ref_exists(ref):
-                git.delete_ref(ref)
-
-        # Update 0 -> 1.
-        if get_format_version() == 0:
-            mkdir(os.path.join(branch_dir, 'trash'))
-            patch_dir = os.path.join(branch_dir, 'patches')
-            mkdir(patch_dir)
-            refs_base = 'refs/patches/%s' % self.get_name()
-            for patch in (file(os.path.join(branch_dir, 'unapplied')).readlines()
-                          + file(os.path.join(branch_dir, 'applied')).readlines()):
-                patch = patch.strip()
-                os.rename(os.path.join(branch_dir, patch),
-                          os.path.join(patch_dir, patch))
-                topfield = os.path.join(patch_dir, patch, 'top')
-                if os.path.isfile(topfield):
-                    top = read_string(topfield, False)
-                else:
-                    top = None
-                if top:
-                    git.set_ref(refs_base + '/' + patch, top)
-            set_format_version(1)
-
-        # Update 1 -> 2.
-        if get_format_version() == 1:
-            desc_file = os.path.join(branch_dir, 'description')
-            if os.path.isfile(desc_file):
-                desc = read_string(desc_file)
-                if desc:
-                    config.set('branch.%s.description' % self.get_name(), desc)
-                rm(desc_file)
-            rm(os.path.join(branch_dir, 'current'))
-            rm_ref('refs/bases/%s' % self.get_name())
-            set_format_version(2)
-
-        # Make sure we're at the latest version.
-        if not get_format_version() in [None, FORMAT_VERSION]:
-            raise StackException('Branch %s is at format version %d, expected %d'
-                                 % (self.get_name(), get_format_version(), FORMAT_VERSION))
-
     def __patch_name_valid(self, name):
         """Raise an exception if the patch name is not valid.
         """
@@ -620,7 +533,8 @@ class Series(PatchSet):
         self.create_empty_field('applied')
         self.create_empty_field('unapplied')
 
-        config.set(self.format_version_key(), str(FORMAT_VERSION))
+        config.set(stackupgrade.format_version_key(self.get_name()),
+                   str(stackupgrade.FORMAT_VERSION))
 
     def rename(self, to_name):
         """Renames a series
Previous: Karl HasselströmNext: Karl Hasselström
Message 4 of 14 in “Infrastructure rewrite series”
  1. 00/10 Infrastructure rewrite seriesKarl Hasselström, Nov 25, 2007
  2. 01/10 New StGit core infrastructure: repository operationsKarl Hasselström, Nov 25, 2007
  3. 02/10 Write metadata files used by the old infrastructureKarl Hasselström, Nov 25, 2007
  4. 03/10 Upgrade older stacks to newest versionKarl Hasselström, Nov 25, 2007
  5. 04/10 Let "stg clean" use the new infrastructureKarl Hasselström, Nov 25, 2007
  6. 05/10 Add "stg coalesce"Karl Hasselström, Nov 25, 2007
  7. 06/10 Let "stg applied" and "stg unapplied" use the new infrastructureKarl Hasselström, Nov 25, 2007
  8. 07/10 Teach the new infrastructure about the index and worktreeKarl Hasselström, Nov 25, 2007
  9. Karl HasselströmNov 26, 2007
  10. David KågedalNov 26, 2007
  11. Karl HasselströmNov 26, 2007
  12. 08/10 Let "stg clean" use the new transaction primitivesKarl Hasselström, Nov 25, 2007
  13. 09/10 Let "stg goto" use the new infrastructureKarl Hasselström, Nov 25, 2007
  14. 10/10 Convert "stg uncommit" to the new infrastructureKarl Hasselström, Nov 25, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.