コード例 #1
0
ファイル: refresh.py プロジェクト: miracle2k/stgit
def make_temp_patch(stack, patch_name, paths, temp_index):
    """Commit index to temp patch, in a complete transaction. If any path
    limiting is in effect, use a temp index."""
    tree = write_tree(stack, paths, temp_index)
    commit = stack.repository.commit(
        git.CommitData(tree=tree, parents=[stack.head], message="Refresh of %s" % patch_name)
    )
    temp_name = utils.make_patch_name("refresh-temp", stack.patches.exists)
    trans = transaction.StackTransaction(stack, "refresh (create temporary patch)")
    trans.patches[temp_name] = commit
    trans.applied.append(temp_name)
    return trans.run(stack.repository.default_iw, print_current_patch=False), temp_name
コード例 #2
0
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise CmdException(
            'Cannot create a new patch -- resolve conflicts first'
        )

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if stack.patches.exists(name):
            raise CmdException('%s: patch already exists' % name)
        elif not stack.patches.is_name_valid(name):
            raise CmdException('Invalid patch name: "%s"' % name)
    else:
        parser.error('incorrect number of arguments')

    cd = CommitData(
        tree=stack.head.data.tree,
        parents=[stack.head],
        message='',
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = update_commit_data(
        cd,
        message=options.message,
        author=options.author(cd.author),
        sign_str=options.sign_str,
        edit=(not options.save_template and options.message is None),
    )

    if options.save_template:
        options.save_template(cd.message.encode('utf-8'))
        return utils.STGIT_SUCCESS

    if not options.no_verify:
        cd = run_commit_msg_hook(stack.repository, cd)

    if name is None:
        name = utils.make_patch_name(cd.message, stack.patches.exists)
        assert stack.patches.is_name_valid(name)

    # Write the new patch.
    stack.repository.default_iw
    trans = StackTransaction(stack, 'new: %s' % name)
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.run()
コード例 #3
0
ファイル: new.py プロジェクト: snits/stgit
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise common.CmdException(
            'Cannot create a new patch -- resolve conflicts first')

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if stack.patches.exists(name):
            raise common.CmdException('%s: patch already exists' % name)
    else:
        parser.error('incorrect number of arguments')

    cd = gitlib.CommitData(tree=stack.head.data.tree,
                           parents=[stack.head],
                           message='',
                           author=gitlib.Person.author(),
                           committer=gitlib.Person.committer())
    cd = common.update_commit_data(cd, options)

    if options.save_template:
        options.save_template(cd.message)
        return utils.STGIT_SUCCESS

    if not options.no_verify:
        cd = common.run_commit_msg_hook(stack.repository, cd)

    if name is None:
        name = utils.make_patch_name(cd.message,
                                     lambda name: stack.patches.exists(name))

    # Write the new patch.
    iw = stack.repository.default_iw
    trans = transaction.StackTransaction(stack, 'new')
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.run()
コード例 #4
0
ファイル: new.py プロジェクト: samv/stgit
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise common.CmdException(
            'Cannot create a new patch -- resolve conflicts first')

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if stack.patches.exists(name):
            raise common.CmdException('%s: patch already exists' % name)
    else:
        parser.error('incorrect number of arguments')

    cd = gitlib.CommitData(
        tree = stack.head.data.tree, parents = [stack.head], message = '',
        author = gitlib.Person.author(), committer = gitlib.Person.committer())
    cd = common.update_commit_data(cd, options)

    # run the commit-msg hook
    cd = cd.set_message(edit.run_commit_msg_hook(stack.repository, cd.message))

    if options.save_template:
        options.save_template(cd.message)
        return utils.STGIT_SUCCESS

    if name == None:
        name = utils.make_patch_name(cd.message,
                                     lambda name: stack.patches.exists(name))

    # Write the new patch.
    iw = stack.repository.default_iw
    trans = transaction.StackTransaction(stack, 'new')
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.run()
コード例 #5
0
ファイル: stack.py プロジェクト: snits/stgit
    def new_patch(self, name, message = None, can_edit = True,
                  unapplied = False, show_patch = False,
                  top = None, bottom = None, commit = True,
                  author_name = None, author_email = None, author_date = None,
                  committer_name = None, committer_email = None,
                  before_existing = False, sign_str = None):
        """Creates a new patch, either pointing to an existing commit object,
        or by creating a new commit object.
        """

        assert commit or (top and bottom)
        assert not before_existing or (top and bottom)
        assert not (commit and before_existing)
        assert (top and bottom) or (not top and not bottom)
        assert commit or (not top or (bottom == git.get_commit(top).get_parent()))

        if name is not None:
            self.__patch_name_valid(name)
            if self.patch_exists(name):
                raise StackException('Patch "%s" already exists' % name)

        # TODO: move this out of the stgit.stack module, it is really
        # for higher level commands to handle the user interaction
        def sign(msg):
            return add_sign_line(msg, sign_str,
                                 committer_name or git.committer().name,
                                 committer_email or git.committer().email)
        if not message and can_edit:
            descr = edit_file(
                self, sign(''),
                'Please enter the description for the patch above.',
                show_patch)
        else:
            descr = sign(message)

        head = git.get_head()

        if name is None:
            name = make_patch_name(descr, self.patch_exists)

        patch = self.get_patch(name)
        patch.create()

        patch.set_description(descr)
        patch.set_authname(author_name)
        patch.set_authemail(author_email)
        patch.set_authdate(author_date)
        patch.set_commname(committer_name)
        patch.set_commemail(committer_email)

        if before_existing:
            insert_string(self.__applied_file, patch.get_name())
        elif unapplied:
            patches = [patch.get_name()] + self.get_unapplied()
            write_strings(self.__unapplied_file, patches)
            set_head = False
        else:
            append_string(self.__applied_file, patch.get_name())
            set_head = True

        if commit:
            if top:
                top_commit = git.get_commit(top)
            else:
                bottom = head
                top_commit = git.get_commit(head)

            # create a commit for the patch (may be empty if top == bottom);
            # only commit on top of the current branch
            assert(unapplied or bottom == head)
            commit_id = git.commit(message = descr, parents = [bottom],
                                   cache_update = False,
                                   tree_id = top_commit.get_tree(),
                                   allowempty = True, set_head = set_head,
                                   author_name = author_name,
                                   author_email = author_email,
                                   author_date = author_date,
                                   committer_name = committer_name,
                                   committer_email = committer_email)
            # set the patch top to the new commit
            patch.set_top(commit_id)
        else:
            patch.set_top(top)

        self.log_patch(patch, 'new')

        return patch
コード例 #6
0
ファイル: uncommit.py プロジェクト: samv/stgit
def func(parser, options, args):
    """Uncommit a number of patches.
    """
    stack = directory.repository.current_stack
    if options.to:
        if options.number:
            parser.error('cannot give both --to and --number')
        if len(args) != 0:
            parser.error('cannot specify patch name with --to')
        patch_nr = patchnames = None
        to_commit = stack.repository.rev_parse(options.to)
        # check whether the --to commit is on a different branch
        merge_bases = directory.repository.get_merge_bases(to_commit, stack.base)
        if not to_commit in merge_bases:
            to_commit = merge_bases[0]
            options.exclusive = True
    elif options.number:
        if options.number <= 0:
            parser.error('invalid value passed to --number')
        patch_nr = options.number
        if len(args) == 0:
            patchnames = None
        elif len(args) == 1:
            # prefix specified
            patchnames = ['%s%d' % (args[0], i)
                          for i in xrange(patch_nr, 0, -1)]
        else:
            parser.error('when using --number, specify at most one patch name')
    elif len(args) == 0:
        patchnames = None
        patch_nr = 1
    else:
        patchnames = args
        patch_nr = len(patchnames)

    def check_and_append(c, n):
        next = n.data.parents;
        try:
            [next] = next
        except ValueError:
            out.done()
            raise common.CmdException(
                'Trying to uncommit %s, which does not have exactly one parent'
                % n.sha1)
        return c.append(n)

    commits = []
    next_commit = stack.base
    if patch_nr:
        out.start('Uncommitting %d patches' % patch_nr)
        for i in xrange(patch_nr):
            check_and_append(commits, next_commit)
            next_commit = next_commit.data.parent
    else:
        if options.exclusive:
            out.start('Uncommitting to %s (exclusive)' % to_commit.sha1)
        else:
            out.start('Uncommitting to %s' % to_commit.sha1)
        while True:
            if next_commit == to_commit:
                if not options.exclusive:
                    check_and_append(commits, next_commit)
                break
            check_and_append(commits, next_commit)
            next_commit = next_commit.data.parent
        patch_nr = len(commits)

    taken_names = set(stack.patchorder.all)
    if patchnames:
        for pn in patchnames:
            if pn in taken_names:
                raise common.CmdException('Patch name "%s" already taken' % pn)
            taken_names.add(pn)
    else:
        patchnames = []
        for c in reversed(commits):
            pn = utils.make_patch_name(c.data.message,
                                       lambda pn: pn in taken_names)
            patchnames.append(pn)
            taken_names.add(pn)
        patchnames.reverse()

    trans = transaction.StackTransaction(stack, 'uncommit',
                                         allow_conflicts = True,
                                         allow_bad_head = True)
    for commit, pn in zip(commits, patchnames):
        trans.patches[pn] = commit
    trans.applied = list(reversed(patchnames)) + trans.applied
    trans.run(set_head = False)
    out.done()
コード例 #7
0
ファイル: squash.py プロジェクト: miracle2k/stgit
 def get_name(cd):
     return name or utils.make_patch_name(cd.message, bad_name)
コード例 #8
0
ファイル: repair.py プロジェクト: snits/stgit
def func(parser, options, args):
    """Repair inconsistencies in StGit metadata."""

    orig_applied = crt_series.get_applied()
    orig_unapplied = crt_series.get_unapplied()
    orig_hidden = crt_series.get_hidden()

    if crt_series.get_protected():
        raise CmdException(
            'This branch is protected. Modification is not permitted.')

    # Find commits that aren't patches, and applied patches.
    head = git.get_commit(git.get_head()).get_id_hash()
    commits, patches = read_commit_dag(crt_series.get_name())
    c = commits[head]
    patchify = []       # commits to definitely patchify
    maybe_patchify = [] # commits to patchify if we find a patch below them
    applied = []
    while len(c.parents) == 1:
        parent, = c.parents
        if c.patch:
            applied.append(c)
            patchify.extend(maybe_patchify)
            maybe_patchify = []
        else:
            maybe_patchify.append(c)
        c = parent
    applied.reverse()
    patchify.reverse()

    # Find patches hidden behind a merge.
    merge = c
    todo = set([c])
    seen = set()
    hidden = set()
    while todo:
        c = todo.pop()
        seen.add(c)
        todo |= c.parents - seen
        if c.patch:
            hidden.add(c)
    if hidden:
        out.warn(('%d patch%s are hidden below the merge commit'
                  % (len(hidden), ['es', ''][len(hidden) == 1])),
                 '%s,' % merge.id, 'and will be considered unapplied.')

    # Make patches of any linear sequence of commits on top of a patch.
    names = set(p.patch for p in patches)
    def name_taken(name):
        return name in names
    if applied and patchify:
        out.start('Creating %d new patch%s'
                  % (len(patchify), ['es', ''][len(patchify) == 1]))
        for p in patchify:
            name = make_patch_name(p.commit.get_log(), name_taken)
            out.info('Creating patch %s from commit %s' % (name, p.id))
            aname, amail, adate = name_email_date(p.commit.get_author())
            cname, cmail, cdate = name_email_date(p.commit.get_committer())
            parent, = p.parents
            crt_series.new_patch(
                name, can_edit = False, commit = False,
                top = p.id, bottom = parent.id, message = p.commit.get_log(),
                author_name = aname, author_email = amail, author_date = adate,
                committer_name = cname, committer_email = cmail)
            p.patch = name
            applied.append(p)
            names.add(name)
        out.done()

    # Figure out hidden
    orig_patches = orig_applied + orig_unapplied + orig_hidden
    orig_applied_name_set = set(orig_applied)
    orig_unapplied_name_set = set(orig_unapplied)
    orig_hidden_name_set = set(orig_hidden)
    orig_patches_name_set = set(orig_patches)
    hidden = [p for p in patches if p.patch in orig_hidden_name_set]

    # Write the applied/unapplied files.
    out.start('Checking patch appliedness')
    unapplied = patches - set(applied) - set(hidden)
    applied_name_set = set(p.patch for p in applied)
    unapplied_name_set = set(p.patch for p in unapplied)
    hidden_name_set = set(p.patch for p in hidden)
    patches_name_set = set(p.patch for p in patches)
    for name in orig_patches_name_set - patches_name_set:
        out.info('%s is gone' % name)
    for name in applied_name_set - orig_applied_name_set:
        out.info('%s is now applied' % name)
    for name in unapplied_name_set - orig_unapplied_name_set:
        out.info('%s is now unapplied' % name)
    for name in hidden_name_set - orig_hidden_name_set:
        out.info('%s is now hidden' % name)
    orig_order = dict(zip(orig_patches, range(len(orig_patches))))

    def patchname_key(p):
        i = orig_order.get(p, len(orig_order))
        return i, p

    crt_series.set_applied(p.patch for p in applied)
    crt_series.set_unapplied(sorted(unapplied_name_set, key=patchname_key))
    crt_series.set_hidden(sorted(hidden_name_set, key=patchname_key))
    out.done()