+ PatchSet.__init__(self, name)
+
+ # 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()
+
+ self.__refs_base = 'refs/patches/%s' % self.get_name()
+
+ self.__applied_file = os.path.join(self._dir(), 'applied')
+ self.__unapplied_file = os.path.join(self._dir(), 'unapplied')
+ self.__hidden_file = os.path.join(self._dir(), 'hidden')
+
+ # where this series keeps its patches
+ self.__patch_dir = os.path.join(self._dir(), 'patches')
+
+ # 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))
+ Patch(patch, patch_dir, refs_base).update_top_ref()
+ 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.