예제 #1
0
    def push_empty_patch(self, name):
        """Pushes an empty patch on the stack
        """
        unapplied = self.get_unapplied()
        assert(name in unapplied)

        # patch = self.get_patch(name)
        head = git.get_head()

        append_string(self.__applied_file, name)

        unapplied.remove(name)
        write_strings(self.__unapplied_file, unapplied)

        self.refresh_patch(bottom=head, cache_update=False, log='push(m)')
예제 #2
0
파일: stack.py 프로젝트: snits/stgit
    def push_empty_patch(self, name):
        """Pushes an empty patch on the stack
        """
        unapplied = self.get_unapplied()
        assert(name in unapplied)

        # patch = self.get_patch(name)
        head = git.get_head()

        append_string(self.__applied_file, name)

        unapplied.remove(name)
        write_strings(self.__unapplied_file, unapplied)

        self.refresh_patch(bottom = head, cache_update = False, log = 'push(m)')
예제 #3
0
파일: stack.py 프로젝트: snits/stgit
    def push_patch(self, name):
        """Pushes a patch on the stack
        """
        unapplied = self.get_unapplied()
        assert(name in unapplied)

        patch = self.get_patch(name)

        head = git.get_head()
        bottom = patch.get_bottom()
        top = patch.get_top()
        # top != bottom always since we have a commit for each patch

        if head == bottom:
            # A fast-forward push. Just reset the backup
            # information. No need for logging
            patch.set_top(top, backup = True)

            git.switch(top)
            append_string(self.__applied_file, name)

            unapplied.remove(name)
            write_strings(self.__unapplied_file, unapplied)
            return False

        # Need to create a new commit an merge in the old patch
        ex = None
        modified = False

        # Try the fast applying first. If this fails, fall back to the
        # three-way merge
        if not git.apply_diff(bottom, top):
            # if git.apply_diff() fails, the patch requires a diff3
            # merge and can be reported as modified
            modified = True

            # merge can fail but the patch needs to be pushed
            try:
                git.merge_recursive(bottom, head, top)
            except git.GitException:
                out.error('The merge failed during "push".',
                          'Revert the operation with "stg undo".')

        append_string(self.__applied_file, name)

        unapplied.remove(name)
        write_strings(self.__unapplied_file, unapplied)

        if not ex:
            # if the merge was OK and no conflicts, just refresh the patch
            # The GIT cache was already updated by the merge operation
            if modified:
                log = 'push(m)'
            else:
                log = 'push'
            self.refresh_patch(bottom = head, cache_update = False, log = log)
        else:
            # we make the patch empty, with the merged state in the
            # working tree.
            self.refresh_patch(bottom = head, cache_update = False,
                               empty = True, log = 'push(c)')
            raise StackException(str(ex))

        return modified
예제 #4
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
예제 #5
0
def __conflict(path):
    """Write the conflict file for the 'path' variable and exit
    """
    append_string(os.path.join(basedir.get(), 'conflicts'), path)
예제 #6
0
    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,
        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 (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 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
예제 #7
0
    def push_patch(self, name):
        """Pushes a patch on the stack
        """
        unapplied = self.get_unapplied()
        assert(name in unapplied)

        patch = self.get_patch(name)

        head = git.get_head()
        bottom = patch.get_bottom()
        top = patch.get_top()
        # top != bottom always since we have a commit for each patch

        if head == bottom:
            # A fast-forward push. Just reset the backup
            # information. No need for logging
            patch.set_top(top, backup=True)

            git.switch(top)
            append_string(self.__applied_file, name)

            unapplied.remove(name)
            write_strings(self.__unapplied_file, unapplied)
            return False

        # Need to create a new commit an merge in the old patch
        ex = None
        modified = False

        # Try the fast applying first. If this fails, fall back to the
        # three-way merge
        if not git.apply_diff(bottom, top):
            # if git.apply_diff() fails, the patch requires a diff3
            # merge and can be reported as modified
            modified = True

            # merge can fail but the patch needs to be pushed
            try:
                git.merge_recursive(bottom, head, top)
            except git.GitException:
                out.error('The merge failed during "push".',
                          'Revert the operation with "stg undo".')

        append_string(self.__applied_file, name)

        unapplied.remove(name)
        write_strings(self.__unapplied_file, unapplied)

        if not ex:
            # if the merge was OK and no conflicts, just refresh the patch
            # The GIT cache was already updated by the merge operation
            if modified:
                log = 'push(m)'
            else:
                log = 'push'
            self.refresh_patch(bottom=head, cache_update=False, log=log)
        else:
            # we make the patch empty, with the merged state in the
            # working tree.
            self.refresh_patch(
                bottom=head,
                cache_update=False,
                empty=True,
                log='push(c)',
            )
            raise StackException(str(ex))

        return modified
예제 #8
0
def __conflict(path):
    """Write the conflict file for the 'path' variable and exit
    """
    append_string(os.path.join(basedir.get(), 'conflicts'), path)