def func(parser, options, args): """Rebase the current stack """ if len(args) != 1: parser.error('incorrect number of arguments') repository = directory.repository stack = repository.get_stack() iw = repository.default_iw if stack.protected: raise CmdException('This branch is protected. Rebase is not permitted') target = git_commit(args[0], repository) applied = stack.patchorder.applied retval = prepare_rebase(stack, 'rebase') if retval: return retval rebase(stack, iw, target) if not options.nopush: return post_rebase(stack, applied, 'rebase', check_merged=options.merged)
def __create_branch(branch_name, committish): repository = directory.repository branch_commit = None if committish is not None: parentbranch = None try: branchpoint = repository.run( ['git', 'rev-parse', '--symbolic-full-name', committish] ).output_one_line() if branchpoint.startswith('refs/heads/') or branchpoint.startswith( 'refs/remotes/' ): # committish is a valid ref from the branchpoint setting above parentbranch = committish except RunException: out.info( 'Do not know how to determine parent branch from "%s"' % committish ) # exception in branch = rev_parse() leaves branchpoint unbound branchpoint = None branch_commit = git_commit(branchpoint or committish, repository) if parentbranch: out.info('Recording "%s" as parent branch' % parentbranch) else: out.info( 'Do not know how to determine parent branch from "%s"' % committish ) else: try: # branch stack off current branch parentbranch = repository.head_ref except DetachedHeadException: parentbranch = None if parentbranch: parentremote = config.get('branch.%s.remote' % parentbranch) if parentremote: out.info('Using remote "%s" to pull parent from' % parentremote) else: out.info('Recording as a local branch') else: # no known parent branch, can't guess the remote parentremote = None stack = Stack.create( repository, name=branch_name, msg='create %s' % branch_name, create_at=branch_commit, parent_remote=parentremote, parent_branch=parentbranch, switch_to=True, ) return stack
def func(parser, options, args): """Integrate a GNU diff patch into the current patch""" if len(args) > 1: parser.error('incorrect number of arguments') repository = directory.repository stack = repository.get_stack() check_local_changes(repository) check_conflicts(repository.default_iw) check_head_top_equal(stack) if len(args) == 1: filename = args[0] else: filename = None applied = stack.patchorder.applied if not applied: raise CmdException('No patches applied') current = applied[-1] if filename: if os.path.exists(filename): out.start('Folding patch "%s"' % filename) with io.open(filename, 'rb') as f: diff = f.read() else: raise CmdException('No such file: %s' % filename) else: out.start('Folding patch from stdin') diff = sys.stdin.buffer.read() if options.threeway: top_patch = stack.patches.get(current) apply_patch( stack, diff, base=top_patch.commit.data.parent, strip=options.strip, reject=options.reject, ) elif options.base: apply_patch( stack, diff, base=git_commit(options.base, repository), reject=options.reject, strip=options.strip, ) else: apply_patch( stack, diff, strip=options.strip, reject=options.reject, ) out.done()
def func(parser, options, args): """Show the tree diff""" repository = directory.repository if options.revs: rev_list = options.revs.split('..') if len(rev_list) not in [1, 2] or not rev_list[0]: parser.error('incorrect parameters to -r') elif len(rev_list) == 1: rev1 = git_commit(rev_list[0], repository) rev2 = None else: rev1 = git_commit(rev_list[0], repository) if rev_list[1]: rev2 = git_commit(rev_list[1], repository) else: rev2 = None else: rev1 = repository.rev_parse('HEAD') rev2 = None iw = repository.default_iw files = iw.ls_files(rev1.data.tree, args) diff_opts = color_diff_flags() diff_opts.extend(options.diff_flags) if rev1 and rev2: diff = repository.diff_tree( rev1.data.tree, rev2.data.tree, diff_opts=diff_opts, pathlimits=files, stat=options.stat, binary=False, ) else: diff = iw.diff( rev1.data.tree, diff_opts=diff_opts, pathlimits=files, stat=options.stat, binary=False, ) pager(diff)
def func(parser, options, args): """Show the applied patches""" if len(args) == 0: id_str = 'HEAD' elif len(args) == 1: id_str = args[0] else: parser.error('incorrect number of arguments') out.stdout(git_commit(id_str, directory.repository).sha1)
def func(parser, options, args): """Show the applied patches """ if len(args) == 0: id_str = 'HEAD' elif len(args) == 1: id_str = args[0] else: parser.error('incorrect number of arguments') out.stdout(common.git_commit(id_str, directory.repository).sha1)
def func(parser, options, args): """Rebase the current stack""" if options.interactive: # destination is optional for '--interactive' if len(args) not in (0, 1): parser.error('incorrect number of arguments') else: if len(args) != 1: parser.error('incorrect number of arguments') repository = directory.repository stack = repository.get_stack() iw = repository.default_iw if stack.protected: raise CmdException('This branch is protected. Rebase is not permitted') if len(args) > 0: target = git_commit(args[0], repository) else: target = stack.base if options.autostash and not iw.worktree_clean(): repository.run(['git', 'stash', 'push']).run() stashed_worktree = True else: stashed_worktree = False applied = stack.patchorder.applied retval = prepare_rebase(stack, 'rebase') if retval: return retval rebase(stack, iw, target) if options.interactive: retval = __do_rebase_interactive(repository, applied, check_merged=options.merged) elif not options.nopush: retval = post_rebase(stack, applied, 'rebase', check_merged=options.merged) else: retval = None if stashed_worktree: try: repository.run(['git', 'stash', 'pop']).run() except RunException: raise StashPopConflictException() return retval
def func(parser, options, args): """Rebase the current stack""" if options.interactive: # destination is optional for '--interactive' if len(args) not in (0, 1): parser.error('incorrect number of arguments') else: if len(args) != 1: parser.error('incorrect number of arguments') repository = directory.repository stack = repository.get_stack() iw = repository.default_iw if stack.protected: raise CmdException('This branch is protected. Rebase is not permitted') if len(args) > 0: target = git_commit(args[0], repository) else: target = stack.base applied = stack.patchorder.applied retval = prepare_rebase(stack, 'rebase') if retval: return retval rebase(stack, iw, target) if options.interactive: return __do_rebase_interactive(repository, applied, check_merged=options.merged) elif not options.nopush: return post_rebase(stack, applied, 'rebase', check_merged=options.merged)
def func(parser, options, args): """Import a commit object as a new patch """ if not args: parser.error('incorrect number of arguments') if options.file and not options.fold: parser.error('--file can only be specified with --fold') repository = directory.repository stack = repository.get_stack() iw = repository.default_iw if not options.unapplied: check_local_changes(repository) check_conflicts(iw) check_head_top_equal(stack) if options.ref_branch: ref_stack = repository.get_stack(options.ref_branch) else: ref_stack = stack try: patches = parse_patches( args, ref_stack.patchorder.all_visible, len(ref_stack.patchorder.applied), ) commit = None except CmdException: if len(args) > 1: raise branch, patch = parse_rev(args[0]) if not branch: commit = git_commit(patch, repository, options.ref_branch) patches = [] else: ref_stack = repository.get_stack(branch) patches = parse_patches( [patch], ref_stack.patchorder.all_visible, len(ref_stack.patchorder.applied), ) commit = None if not commit and len(patches) > 1: if options.name: raise CmdException('--name can only be specified with one patch') if options.parent: raise CmdException('--parent can only be specified with one patch') if options.update and not stack.patchorder.applied: raise CmdException('No patches applied') if commit: patchname = None retval = __pick_commit(stack, ref_stack, iw, commit, patchname, options) else: if options.unapplied: patches.reverse() for patchname in patches: commit = git_commit(patchname, repository, ref_stack.name) retval = __pick_commit(stack, ref_stack, iw, commit, patchname, options) if retval != STGIT_SUCCESS: break if retval == STGIT_SUCCESS: print_current_patch(stack) return retval
def __pick_commit(stack, ref_stack, iw, commit, patchname, options): """Pick a commit.""" repository = stack.repository if options.name: patchname = options.name elif patchname and options.revert: patchname = 'revert-' + patchname if patchname: patchname = find_patch_name(patchname, stack.patches.exists) else: patchname = make_patch_name(commit.data.message_str, stack.patches.exists) if options.parent: parent = git_commit(options.parent, repository, ref_stack.name) else: parent = commit.data.parent if not options.revert: bottom = parent top = commit else: bottom = commit top = parent if options.fold: out.start('Folding commit %s' % commit.sha1) diff = repository.diff_tree(bottom.data.tree, top.data.tree, pathlimits=options.file) if diff: try: # try a direct git apply first iw.apply(diff, quiet=True) except MergeException: if options.file: out.done('conflict(s)') out.error('%s does not apply cleanly' % patchname) return STGIT_CONFLICT else: try: iw.merge( bottom.data.tree, stack.head.data.tree, top.data.tree, ) except MergeConflictException as e: out.done('%s conflicts' % len(e.conflicts)) out.error('%s does not apply cleanly' % patchname, *e.conflicts) return STGIT_CONFLICT out.done() else: out.done('no changes') return STGIT_SUCCESS elif options.update: files = [ fn1 for _, _, _, _, _, fn1, fn2 in repository.diff_tree_files( stack.top.data.parent.data.tree, stack.top.data.tree) ] diff = repository.diff_tree(bottom.data.tree, top.data.tree, pathlimits=files) out.start('Updating with commit %s' % commit.sha1) try: iw.apply(diff, quiet=True) except MergeException: out.done('conflict(s)') out.error('%s does not apply cleanly' % patchname) return STGIT_CONFLICT else: out.done() return STGIT_SUCCESS else: author = commit.data.author message = commit.data.message_str if options.revert: author = Person.author() if message: lines = message.splitlines() subject = lines[0] body = '\n'.join(lines[2:]) else: subject = commit.sha1 body = '' message = 'Revert "%s"\n\nThis reverts commit %s.\n\n%s\n' % ( subject, commit.sha1, body, ) elif options.expose: fmt = config.get('stgit.pick.expose-format') message = Run('git', 'show', '--no-patch', '--pretty=' + fmt, commit.sha1).raw_output() message = message.rstrip() + '\n' out.start('Importing commit %s' % commit.sha1) new_commit = repository.commit( CommitData( tree=top.data.tree, parents=[bottom], message=message, author=author, )) trans = StackTransaction( stack, 'pick %s from %s' % (patchname, ref_stack.name)) trans.patches[patchname] = new_commit trans.unapplied.append(patchname) if not options.unapplied: try: trans.push_patch(patchname, iw, allow_interactive=True) except TransactionHalted: pass retval = trans.run(iw, print_current_patch=False) if retval == STGIT_CONFLICT: out.done('conflict(s)') elif stack.patches.get(patchname).is_empty(): out.done('empty patch') else: out.done() return retval
def func(parser, options, args): """Pull the changes from a remote repository""" repository = directory.repository iw = repository.default_iw stack = repository.get_stack() policy = config.get('branch.%s.stgit.pull-policy' % stack.name) or config.get('stgit.pull-policy') if policy not in ['pull', 'fetch-rebase', 'rebase']: raise GitConfigException('Unsupported pull-policy "%s"' % policy) remote_name = None if policy == 'rebase': # parent is local if len(args) == 1: parser.error( 'specifying a repository is meaningless for policy="%s"' % (policy, )) elif len(args) > 0: parser.error('incorrect number of arguments') else: # parent is remote if len(args) > 1: parser.error('incorrect number of arguments') if len(args) >= 1: remote_name = args[0] else: remote_name = stack.parent_remote if policy in ['pull', 'fetch-rebase'] and remote_name is None: parser.error( 'There is no tracking information for the current branch.\n' 'Please specify the remote repository to pull from.') if stack.protected: raise CmdException('This branch is protected. Pulls are not permitted') applied = stack.patchorder.applied retval = prepare_rebase(stack, 'pull') if retval: return retval # pull the remote changes if policy == 'pull': out.info('Pulling from "%s"' % remote_name) pull(repository, remote_name) elif policy == 'fetch-rebase': out.info('Fetching from "%s"' % remote_name) fetch(repository, remote_name) try: target = repository.rev_parse('FETCH_HEAD') except RepositoryException: out.error('Could not find the remote head to rebase onto - ' 'fix branch.%s.merge in .git/config' % stack.name) out.error('Pushing any patches back...') post_rebase(stack, applied, 'pull', check_merged=False) raise rebase(stack, iw, target) elif policy == 'rebase': value = config.get('branch.%s.stgit.parentbranch' % stack.name) if value: parent_commit = git_commit(value, repository) else: try: parent_commit = repository.rev_parse('heads/origin') except RepositoryException: raise CmdException('Cannot find a parent branch for "%s"' % stack.name) else: out.warn( 'No parent branch declared for stack "%s", defaulting to' '"heads/origin".' % stack.name, 'Consider setting "branch.%s.stgit.parentbranch" with ' '"git config".' % stack.name, ) rebase(stack, iw, parent_commit) if not options.nopush: post_rebase(stack, applied, 'pull', check_merged=options.merged) # maybe tidy up if config.getbool('stgit.keepoptimized'): repository.repack()