Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
-import sys, os
+import sys, os, re
from stgit.utils import *
from stgit import git, basedir, templates
f.close()
# the editor
- if config.has_option('stgit', 'editor'):
- editor = config.get('stgit', 'editor')
+ editor = config.get('stgit.editor')
+ if editor:
+ pass
elif 'EDITOR' in os.environ:
editor = os.environ['EDITOR']
else:
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')
self.__current_file = os.path.join(self._dir(), 'current')
self.__descr_file = os.path.join(self._dir(), 'description')
if self.is_initialised() and not os.path.isdir(self.__trash_dir):
os.makedirs(self.__trash_dir)
+ def __patch_name_valid(self, name):
+ """Raise an exception if the patch name is not valid.
+ """
+ if not name or re.search('[^\w.-]', name):
+ raise StackException, 'Invalid patch name: "%s"' % name
+
def get_branch(self):
"""Return the branch name for the Series object
"""
f.close()
return names
+ def get_hidden(self):
+ if not os.path.isfile(self.__hidden_file):
+ return []
+ f = file(self.__hidden_file)
+ names = [line.strip() for line in f.readlines()]
+ f.close()
+ return names
+
def get_base_file(self):
self.__begin_stack_check()
return self.__base_file
def set_description(self, line):
self._set_field('description', line)
+ def get_parent_remote(self):
+ value = config.get('branch.%s.remote' % self.__name)
+ if value:
+ return value
+ elif 'origin' in git.remotes_list():
+ print 'Notice: no parent remote declared for stack "%s", defaulting to "origin".' \
+ 'Consider setting "branch.%s.remote" with "git repo-config".' \
+ % (self.__name, self.__name)
+ return 'origin'
+ else:
+ raise StackException, 'Cannot find a parent remote for "%s"' % self.__name
+
+ def __set_parent_remote(self, remote):
+ value = config.set('branch.%s.remote' % self.__name, remote)
+
+ def get_parent_branch(self):
+ value = config.get('branch.%s.merge' % self.__name)
+ if value:
+ return value
+ elif git.rev_parse('heads/origin'):
+ print 'Notice: no parent branch declared for stack "%s", defaulting to "heads/origin".' \
+ 'Consider setting "branch.%s.merge" with "git repo-config".' \
+ % (self.__name, self.__name)
+ return 'heads/origin'
+ else:
+ raise StackException, 'Cannot find a parent branch for "%s"' % self.__name
+
+ def __set_parent_branch(self, name):
+ config.set('branch.%s.merge' % self.__name, name)
+
+ def set_parent(self, remote, localbranch):
+ if localbranch:
+ self.__set_parent_branch(localbranch)
+ if remote:
+ self.__set_parent_remote(remote)
+ elif remote:
+ raise StackException, 'Remote "%s" without a branch cannot be used as parent' % remote
+
def __patch_is_current(self, patch):
return patch.get_name() == self.get_current()
"""
return name in self.get_unapplied()
+ def patch_hidden(self, name):
+ """Return true if the patch is hidden.
+ """
+ return name in self.get_hidden()
+
def patch_exists(self, name):
"""Return true if there is a patch with the given name, false
otherwise."""
"""
return os.path.isdir(self.__patch_dir)
- def init(self, create_at=False):
+ def init(self, create_at=False, parent_remote=None, parent_branch=None):
"""Initialises the stgit series
"""
bases_dir = os.path.join(self.__base_dir, 'refs', 'bases')
os.makedirs(self.__patch_dir)
+ self.set_parent(parent_remote, parent_branch)
+
create_dirs(bases_dir)
self.create_empty_field('applied')
os.remove(self.__applied_file)
if os.path.exists(self.__unapplied_file):
os.remove(self.__unapplied_file)
+ if os.path.exists(self.__hidden_file):
+ os.remove(self.__hidden_file)
if os.path.exists(self.__current_file):
os.remove(self.__current_file)
if os.path.exists(self.__descr_file):
# old_bottom is different, there wasn't any previous 'refresh'
# command (probably only a 'push')
if old_bottom != patch.get_bottom() or old_top == patch.get_top():
- raise StackException, 'No refresh undo information available'
+ raise StackException, 'No undo information available'
git.reset(tree_id = old_top, check_out = False)
if patch.restore_old_boundaries():
before_existing = False, refresh = True):
"""Creates a new patch
"""
+ self.__patch_name_valid(name)
+
if self.patch_applied(name) or self.patch_unapplied(name):
raise StackException, 'Patch "%s" already exists' % name
def delete_patch(self, name):
"""Deletes a patch
"""
+ self.__patch_name_valid(name)
patch = Patch(name, self.__patch_dir, self.__refs_dir)
if self.__patch_is_current(patch):
f = file(self.__unapplied_file, 'w+')
f.writelines([line + '\n' for line in unapplied])
f.close()
+
+ if self.patch_hidden(name):
+ self.unhide_patch(name)
+
self.__begin_stack_check()
def forward_patches(self, names):
# merge can fail but the patch needs to be pushed
try:
- git.merge(bottom, head, top)
+ git.merge(bottom, head, top, recursive = True)
except git.GitException, ex:
print >> sys.stderr, \
'The merge failed during "push". ' \
log = 'push'
self.refresh_patch(cache_update = False, log = log)
else:
+ # we store the correctly merged files only for
+ # tracking the conflict history. Note that the
+ # git.merge() operations shouls always leave the index
+ # in a valid state (i.e. only stage 0 files)
+ self.refresh_patch(cache_update = False, log = 'push(c)')
raise StackException, str(ex)
return modified
# modified by 'refresh'). If they are both unchanged, there
# was a fast forward
if old_bottom == patch.get_bottom() and old_top != patch.get_top():
- raise StackException, 'No push undo information available'
+ raise StackException, 'No undo information available'
git.reset()
self.pop_patch(name)
def empty_patch(self, name):
"""Returns True if the patch is empty
"""
+ self.__patch_name_valid(name)
patch = Patch(name, self.__patch_dir, self.__refs_dir)
bottom = patch.get_bottom()
top = patch.get_top()
return False
def rename_patch(self, oldname, newname):
+ self.__patch_name_valid(newname)
+
applied = self.get_applied()
unapplied = self.get_unapplied()
if newname in applied or newname in unapplied:
raise StackException, 'Patch "%s" already exists' % newname
+ if self.patch_hidden(oldname):
+ self.unhide_patch(oldname)
+ self.hide_patch(newname)
+
if oldname in unapplied:
Patch(oldname, self.__patch_dir, self.__refs_dir).rename(newname)
unapplied[unapplied.index(oldname)] = newname
cache_update = False, tree_id = top.get_tree(),
allowempty = True)
patch.set_log(log)
+
+ def hide_patch(self, name):
+ """Add the patch to the hidden list.
+ """
+ if not self.patch_exists(name):
+ raise StackException, 'Unknown patch "%s"' % name
+ elif self.patch_hidden(name):
+ raise StackException, 'Patch "%s" already hidden' % name
+
+ append_string(self.__hidden_file, name)
+
+ def unhide_patch(self, name):
+ """Add the patch to the hidden list.
+ """
+ if not self.patch_exists(name):
+ raise StackException, 'Unknown patch "%s"' % name
+ hidden = self.get_hidden()
+ if not name in hidden:
+ raise StackException, 'Patch "%s" not hidden' % name
+
+ hidden.remove(name)
+
+ f = file(self.__hidden_file, 'w+')
+ f.writelines([line + '\n' for line in hidden])
+ f.close()