elif patch_id == 'log':
return series.get_patch(patch).get_log()
if patch == 'base' and patch_id == None:
- return read_string(series.get_base_file())
+ return series.get_base()
except RevParseException:
pass
return git.rev_parse(rev + '^{commit}')
def check_local_changes():
if git.local_changes():
raise CmdException, \
- 'local changes in the tree. Use "refresh" to commit them'
+ 'local changes in the tree. Use "refresh" or "status --reset"'
def check_head_top_equal():
if not crt_series.head_top_equal():
def check_conflicts():
if os.path.exists(os.path.join(basedir.get(), 'conflicts')):
- raise CmdException, 'Unsolved conflicts. Please resolve them first'
+ raise CmdException, \
+ 'Unsolved conflicts. Please resolve them first or\n' \
+ ' revert the changes with "status --reset"'
def print_crt_patch(branch = None):
if not branch:
patch = stack.Series(branch).get_current()
if patch:
- print 'Now at patch "%s"' % patch
+ out.info('Now at patch "%s"' % patch)
else:
- print 'No patches applied'
+ out.info('No patches applied')
def resolved(filename, reset = None):
if reset:
"""
forwarded = crt_series.forward_patches(patches)
if forwarded > 1:
- print 'Fast-forwarded patches "%s" - "%s"' % (patches[0],
- patches[forwarded - 1])
+ out.info('Fast-forwarded patches "%s" - "%s"'
+ % (patches[0], patches[forwarded - 1]))
elif forwarded == 1:
- print 'Fast-forwarded patch "%s"' % patches[0]
+ out.info('Fast-forwarded patch "%s"' % patches[0])
names = patches[forwarded:]
# check for patches merged upstream
- if check_merged:
- print 'Checking for patches merged upstream...',
- sys.stdout.flush()
+ if names and check_merged:
+ out.start('Checking for patches merged upstream')
merged = crt_series.merged_patches(names)
- print 'done (%d found)' % len(merged)
+ out.done('%d found' % len(merged))
else:
merged = []
for p in names:
- print 'Pushing patch "%s"...' % p,
- sys.stdout.flush()
+ out.start('Pushing patch "%s"' % p)
if p in merged:
crt_series.push_patch(p, empty = True)
- print 'done (merged upstream)'
+ out.done('merged upstream')
else:
modified = crt_series.push_patch(p)
if crt_series.empty_patch(p):
- print 'done (empty patch)'
+ out.done('empty patch')
elif modified:
- print 'done (modified)'
+ out.done('modified')
else:
- print 'done'
+ out.done()
def pop_patches(patches, keep = False):
"""Pop the patches in the list from the stack. It is assumed that
the patches are listed in the stack reverse order.
"""
if len(patches) == 0:
- print 'nothing to push/pop'
+ out.info('Nothing to push/pop')
else:
p = patches[-1]
if len(patches) == 1:
- print 'Popping patch "%s"...' % p,
+ out.start('Popping patch "%s"' % p)
else:
- print 'Popping "%s" - "%s" patches...' % (patches[0], p),
- sys.stdout.flush()
-
+ out.start('Popping patches "%s" - "%s"' % (patches[0], p))
crt_series.pop_patch(p, keep)
+ out.done()
- print 'done'
-
-def parse_patches(patch_args, patch_list):
+def parse_patches(patch_args, patch_list, boundary = 0, ordered = False):
"""Parse patch_args list for patch names in patch_list and return
a list. The names can be individual patches and/or in the
patch1..patch2 format.
if pair[0]:
first = patch_list.index(pair[0])
else:
- first = 0
+ first = -1
# exclusive boundary
if pair[1]:
last = patch_list.index(pair[1]) + 1
else:
- last = len(patch_list)
+ last = -1
+
+ # only cross the boundary if explicitly asked
+ if not boundary:
+ boundary = len(patch_list)
+ if first < 0:
+ if last <= boundary:
+ first = 0
+ else:
+ first = boundary
+ if last < 0:
+ if first < boundary:
+ last = boundary
+ else:
+ last = len(patch_list)
if last > first:
pl = patch_list[first:last]
patches += pl
+ if ordered:
+ patches = [p for p in patch_list if p in patches]
+
return patches
def name_email(address):
return str_list[0]
-def make_patch_name(msg):
- """Return a string to be used as a patch name. This is generated
- from the top line of the string passed as argument.
+def address_or_alias(addr_str):
+ """Return the address if it contains an e-mail address or look up
+ the aliases in the config files.
"""
- if not msg:
- return None
-
- subject_line = msg.lstrip().split('\n', 1)[0].lower()
- return re.sub('[\W]+', '-', subject_line).strip('-')
+ def __address_or_alias(addr):
+ if not addr:
+ return None
+ if addr.find('@') >= 0:
+ # it's an e-mail address
+ return addr
+ alias = config.get('mail.alias.'+addr)
+ if alias:
+ # it's an alias
+ return alias
+ raise CmdException, 'unknown e-mail alias: %s' % addr
+
+ addr_list = [__address_or_alias(addr.strip())
+ for addr in addr_str.split(',')]
+ return ', '.join([addr for addr in addr_list if addr])
+
+def prepare_rebase(force=None):
+ if not force:
+ # Be sure we won't loose results of stg-(un)commit by error.
+ # Do not require an existing orig-base for compatibility with 0.12 and earlier.
+ origbase = crt_series._get_field('orig-base')
+ if origbase and crt_series.get_base() != origbase:
+ raise CmdException, 'Rebasing would possibly lose data'
+
+ # pop all patches
+ applied = crt_series.get_applied()
+ if len(applied) > 0:
+ out.start('Popping all applied patches')
+ crt_series.pop_patch(applied[0])
+ out.done()
+ return applied
+
+def rebase(target):
+ if target == git.get_head():
+ out.info('Already at "%s", no need for rebasing.' % target)
+ return
+ out.start('Rebasing to "%s"' % target)
+ git.reset(tree_id = git_id(target))
+ out.done()
+
+def post_rebase(applied, nopush, merged):
+ # memorize that we rebased to here
+ crt_series._set_field('orig-base', git.get_head())
+ # push the patches back
+ if not nopush:
+ push_patches(applied, merged)