示例#1
0
文件: git.py 项目: lupine37/gps
    def async_fetch_status_for_all_files(self, from_user, extra_files=[]):
        """
        :param List(GPS.File) extra_files: files for which we need to
           set the status eventually
        """

        s = self.set_status_for_all_files()

        # Do we need to reset the "ls-tree" cache ? After the initial
        # loading, this list no longer changes without also impacting the
        # output of "git status", so we do not need to execute it again.
        if from_user or self._non_default_files is None:
            all_files = []  # faster to update than a set
            yield join(self.__git_ls_tree(all_files), self.__git_status(s))
            self._non_default_files = s.files_with_explicit_status
            now_default = set(all_files).difference(self._non_default_files)
        else:
            # Reuse caches: we do not need to recompute the full list of files
            # for git, since this will not change without also changing the
            # output of "git status". We also do not reset the default status
            # for all the files not in the git status output: that might be a
            # slow operation that is blocking GPS. Instead, we only reset the
            # default status for files that used to be in "git status" (for
            # instance modified files), and are no longer there (either after
            # a "reset" or a "commit").

            yield self.__git_status(s)
            nondefault = s.files_with_explicit_status
            now_default = self._non_default_files.difference(nondefault)
            self._non_default_files = nondefault

        for f in now_default:
            s.set_status(f, GPS.VCS2.Status.UNMODIFIED)

        s.set_status_for_remaining_files()
示例#2
0
    def async_branches(self, visitor):
        url = ''

        p = self._svn(['info'])
        while True:
            line = yield p.wait_line()
            if line is None:
                break
            if line.startswith('URL: '):
                url = line[5:]
                break

        if url:
            # Assume the standard 'trunk', 'branches' and 'tags' naming
            parent = url
            while True:
                parent, tail = os.path.split(parent)
                if tail in ('trunk', 'branches', 'tags'):
                    break

            yield join(self._branches(visitor, parent),
                       self._tags(visitor, parent))
示例#3
0
文件: git.py 项目: MichelKramer31/gps
    def async_fetch_status_for_all_files(self, from_user, extra_files=[]):
        """
        :param List(GPS.File) extra_files: files for which we need to
           set the status eventually
        """

        s = self.set_status_for_all_files()
        files = set(extra_files)

        # Do we need to reset the "ls-tree" cache ? After the initial
        # loading, this list no longer changes without also impacting the
        # output of "git status", so we do not need to execute it again.
        if from_user or self._non_default_files is None:
            all_files = []   # faster to update than a set
            yield join(self.__git_ls_tree(all_files), self.__git_status(s))
            self._non_default_files = s.files_with_explicit_status
            files.update(all_files)

        else:
            # Reuse caches: we do not need to recompute the full list of files
            # for git, since this will not change without also changing the
            # output of "git status". We also do not reset the default status
            # for all the files not in the git status output: that might be a
            # slow operation that is blocking GPS. Instead, we only reset the
            # default status for files that used to be in "git status" (for
            # instance modified files), and are no longer there (either after
            # a "reset" or a "commit").

            yield self.__git_status(s)
            nondefault = s.files_with_explicit_status
            now_default = self._non_default_files.difference(nondefault)
            self._non_default_files = nondefault
            for f in now_default:
                s.set_status(f, self.default_status)

        s.set_status_for_remaining_files(files)
示例#4
0
文件: git.py 项目: lupine37/gps
    def async_action_on_branch(self, visitor, action, category, id, text=''):
        if category == CAT_BRANCHES:
            if action == GPS.VCS2.Actions.DOUBLE_CLICK and id:
                p = self._git(['checkout', id])
                yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.TOOLTIP and id:
                visitor.tooltip(
                    '\nDouble-click to checkout this branch.\n'
                    'Click [+] to create a new branch from this one.\n'
                    'Click [-] to delete current branch.')

            elif action == GPS.VCS2.Actions.ADD and id:
                name = GPS.MDI.input_dialog('Choose a name for the new branch',
                                            'name=%s-new' % id)
                if name:
                    name = name[0]
                    p = self._git(['branch', '--track', name, id])
                    s, _ = yield p.wait_until_terminate(show_if_error=True)
                    if s == 0:
                        # Checkout will not succeed if there are local changes
                        p = self._git(['checkout', name])
                        yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.RENAME and id and text:
                p = self._git(['branch', '-m', id, text])
                yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.REMOVE and id:
                if (id != 'master' and GPS.MDI.yes_no_dialog(
                        "Delete branch `%s` ?" % id)):

                    # If this is the current branch, fallback to master
                    current = yield self._current_branch()
                    if current == id:
                        p = self._git(['checkout', 'master'])
                        s, _ = yield p.wait_until_terminate(show_if_error=True)

                    p = self._git(['branch', '-D', id])
                    yield p.wait_until_terminate(show_if_error=True)

        elif category == CAT_TAGS:
            if action == GPS.VCS2.Actions.DOUBLE_CLICK and id:
                p = self._git(['checkout', id])
                yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.TOOLTIP:
                visitor.tooltip('\nDouble-click to checkout this tag' + (
                    '\nClick [+] to create a new tag on current branch'
                    if not id else '') +
                                ('\nClick [-] to delete tag' if id else ''))

            elif action == GPS.VCS2.Actions.ADD and not id:
                name = GPS.MDI.input_dialog(
                    'Choose a name for the new tag', 'name',
                    'Commit Message (will annotate if set)')
                if name and name[0]:  # not cancelled
                    p = self._git([
                        'tag', '-a' if name[1] else '',
                        '--message=%s' % name[1] if name[1] else '', name[0]
                    ])
                    yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.REMOVE:
                if id and GPS.MDI.yes_no_dialog("Delete tag `%s` ?" % id):
                    p = self._git(['tag', '-d', id])
                    yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.RENAME and id and text:
                # ??? Can we create an annotated tag ?
                p = self._git(['tag', text, id])
                s, _ = yield p.wait_until_terminate(show_if_error=True)
                if s == 0:
                    p = self._git(['tag', '-d', id])
                    s, _ = yield p.wait_until_terminate(show_if_error=True)
                # ??? Should we push to origin to remote ?

        elif category == CAT_STASHES:
            if action == GPS.VCS2.Actions.DOUBLE_CLICK and id:
                p = self._git(['stash', 'apply', id])
                yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.TOOLTIP:
                visitor.tooltip(
                    ('\nDouble-click to apply this stash on HEAD' +
                     '\nClick [-] to drop this stash' if id else '') +
                    ('' if id else '\nClick [+] to stash all local changes'))

            elif action == GPS.VCS2.Actions.ADD and not id:
                p = self._git(['stash', 'save', 'created from GPS'])
                yield p.wait_until_terminate(show_if_error=True)

            elif action == GPS.VCS2.Actions.REMOVE and id:
                p = self._git(['stash', 'drop', id])
                yield p.wait_until_terminate(show_if_error=True)

        elif category == CAT_REMOTES:
            if action == GPS.VCS2.Actions.DOUBLE_CLICK:
                pass

            elif action == GPS.VCS2.Actions.TOOLTIP:
                visitor.tooltip(
                    '\nDouble-click to checkout this remote branch locally' +
                    '\nClick [-] to delete this remote branch' if id else '')
                pass

            elif action == GPS.VCS2.Actions.ADD:
                pass

            elif action == GPS.VCS2.Actions.REMOVE and id:
                # id is of the form 'remotes/origin/some/name'
                _, origin, name = id.split('/', 2)
                if GPS.MDI.yes_no_dialog("Delete remote branch `%s` ?" % id):
                    p = self._git(['push', origin, ':%s' % name])
                    yield p.wait_until_terminate(show_if_error=True)

        elif category in (CAT_WORKTREES, CAT_SUBMODULES):
            pass

        else:
            yield join(*self.extensions('async_action_on_branch', visitor,
                                        action, category, id, text))
示例#5
0
文件: git.py 项目: lupine37/gps
 def async_branches(self, visitor):
     yield join(self._branches(visitor), self._tags(visitor),
                self._stashes(visitor), self._worktrees(visitor),
                self._submodules(visitor),
                *self.extensions('async_branches', visitor))
示例#6
0
文件: git.py 项目: lupine37/gps
    def async_fetch_history(self, visitor, filter):
        # Compute, in parallel, needed pieces of information
        (unpushed, has_local) = yield join(self._unpushed_local_changes(),
                                           self._has_local_changes())

        # Then fetch the history

        max_lines = filter[0]
        for_file = filter[1]
        pattern = filter[2]
        current_branch_only = filter[3]
        branch_commits_only = filter[4]

        filter_switch = ''
        if pattern:
            if pattern.startswith('author:'):
                filter_switch = '--author=%s' % pattern[7:]
            elif pattern.startswith('code:'):
                filter_switch = '-S=%s' % pattern[5:]
            else:
                filter_switch = '--grep=%s' % pattern

        git_cmd = [
            'log',
            # use tformat to get final newline
            '--pretty=tformat:%H@@%P@@%an@@%D@@%cD@@%s'
        ]
        if not current_branch_only:
            git_cmd.append('--branches')
            git_cmd.append('--tags')
            git_cmd.append('--remotes')
        if for_file:
            git_cmd.append('--follow')
        git_cmd += [
            '--topo-order',  # children before parents
            filter_switch,
            '--max-count=%d' % max_lines if not branch_commits_only else '',
            '%s' % for_file.path if for_file else ''
        ]
        p = self._git(git_cmd)

        nb_added_lines = 0

        while True:
            line = yield p.wait_line()
            if line is None or '@@' not in line:
                GPS.Logger("GIT").log("finished git-status")
                break

            id, parents, author, branches, date, subject = line.split('@@')
            parents = parents.split()
            branches = None if not branches else branches.split(',')

            flags = 0
            if id in unpushed:
                flags |= GPS.VCS2.Commit.Flags.UNPUSHED

            if branches is None:
                branch_descr = None
            else:
                branch_descr = []
                for b in branches:
                    b = b.strip()

                    # ??? How do we detect other remotes
                    if b.startswith('origin/'):
                        f = (b, GPS.VCS2.Commit.Kind.REMOTE)
                    elif b.startswith("HEAD"):
                        f = (b, GPS.VCS2.Commit.Kind.HEAD)
                        # Append a dummy entry if we have local changes, and
                        # we have the HEAD
                        if has_local:
                            visitor.history_line(
                                GPS.VCS2.Commit(
                                    LOCAL_CHANGES_ID,
                                    '',
                                    '',
                                    '<uncommitted changes>',
                                    parents=[id],
                                    flags=GPS.VCS2.Commit.Flags.UNCOMMITTED
                                    | GPS.VCS2.Commit.Flags.UNPUSHED))

                    elif b.startswith("tag: "):
                        f = (b[5:], GPS.VCS2.Commit.Kind.TAG)
                    else:
                        f = (b, GPS.VCS2.Commit.Kind.LOCAL)

                    branch_descr.append(f)

            visitor.history_line(
                GPS.VCS2.Commit(id,
                                author,
                                date,
                                subject,
                                parents,
                                branch_descr,
                                flags=flags))
            nb_added_lines += 1

        GPS.Logger("GIT").log("done parsing git-log (%s lines)" %
                              (nb_added_lines, ))
示例#7
0
文件: git.py 项目: zackboll/gps
    def async_fetch_history(self, visitor, filter):
        # Compute, in parallel, needed pieces of information
        (unpushed, has_local) = yield join(self._unpushed_local_changes(),
                                           self._has_local_changes())

        # Then fetch the history

        max_lines = filter[0]
        for_file = filter[1]
        pattern = filter[2]
        current_branch_only = filter[3]
        branch_commits_only = filter[4]

        filter_switch = ''
        if pattern:
            if pattern.startswith('author:'):
                filter_switch = '--author=%s' % pattern[7:]
            elif pattern.startswith('code:'):
                filter_switch = '-S=%s' % pattern[5:]
            else:
                filter_switch = '--grep=%s' % pattern

        p = self._git([
            'log',
            # use tformat to get final newline
            '--pretty=tformat:%H@@%P@@%an@@%D@@%cD@@%s',
            '--branches' if not current_branch_only else '',
            '--tags' if not current_branch_only else '',
            '--remotes' if not current_branch_only else '',
            '--follow',
            '--topo-order',  # children before parents
            filter_switch,
            '--max-count=%d' % max_lines if not branch_commits_only else '',
            '%s' % for_file.path if for_file else ''
        ])

        children = {}  # number of children for each sha1
        result = []
        count = 0

        while True:
            line = yield p.wait_line()
            if line is None or '@@' not in line:
                GPS.Logger("GIT").log("finished git-status")
                break

            id, parents, author, branches, date, subject = line.split('@@')
            parents = parents.split()
            branches = None if not branches else branches.split(',')

            has_head = None

            flags = 0
            if id in unpushed:
                flags |= GPS.VCS2.Commit.Flags.UNPUSHED

            if branches is None:
                branch_descr = None
            else:
                branch_descr = []
                for b in branches:
                    b = b.strip()

                    # ??? How do we detect other remotes
                    if b.startswith('origin/'):
                        f = (b, GPS.VCS2.Commit.Kind.REMOTE)
                    elif b.startswith("HEAD"):
                        has_head = id
                        f = (b, GPS.VCS2.Commit.Kind.HEAD)
                    elif b.startswith("tag: "):
                        f = (b[5:], GPS.VCS2.Commit.Kind.TAG)
                    else:
                        f = (b, GPS.VCS2.Commit.Kind.LOCAL)

                    branch_descr.append(f)

            # Append a dummy entry if we have local changes, and
            # we have the HEAD
            if has_head is not None and has_local:
                result.insert(
                    0,
                    GPS.VCS2.Commit(LOCAL_CHANGES_ID,
                                    '',
                                    '',
                                    '<uncommitted changes>',
                                    parents=[has_head],
                                    flags=GPS.VCS2.Commit.Flags.UNCOMMITTED
                                    | GPS.VCS2.Commit.Flags.UNPUSHED))

            current = GPS.VCS2.Commit(id,
                                      author,
                                      date,
                                      subject,
                                      parents,
                                      branch_descr,
                                      flags=flags)

            if branch_commits_only:
                for pa in parents:
                    children[pa] = children.setdefault(pa, 0) + 1

                # Count only relevant commits
                if (len(parents) > 1 or branches is not None
                        or id not in children or children[id] > 1):
                    count += 1

            result.append(current)
            if count >= max_lines:
                break

        GPS.Logger("GIT").log("done parsing git-log (%s lines)" %
                              (len(result), ))
        visitor.history_lines(result)
示例#8
0
文件: git.py 项目: MichelKramer31/gps
    def async_branches(self, visitor):
        def __branches():
            branches = []
            remotes = []
            r = re.compile(
                "^(?P<current>\*)?\s+"
                "(?P<name>\S+)"
                "\s+"
                "(?P<id>[a-z0-9]+)"
                "\s+"
                "(\[(?P<tracking>.*\]))?")
            emblem_r = re.compile(
                "^(?P<tracking>.*):\s"
                "(ahead (?P<ahead>\d+),?)?\s*"
                "(behind (?P<behind>\d+))?")

            p = self._git(['branch', '-a', '--list', '--no-color', '-vv'])
            while True:
                line = yield p.wait_line()
                if line is None:
                    visitor.branches(
                        'branches', 'vcs-branch-symbolic', branches)
                    visitor.branches('remotes', 'vcs-cloud-symbolic', remotes)
                    break
                m = r.search(line)
                if m:
                    n = m.group('name')
                    emblem = []
                    m2 = emblem_r.search(m.group('tracking') or '')
                    if m2:
                        n = '%s (%s)' % (n, m2.group('tracking'))
                        if m2.group('ahead'):
                            emblem.append("%s%s%s%s" % (
                                chr(226), chr(134), chr(145),
                                m2.group('ahead')))
                        if m2.group('behind'):
                            emblem.append("%s%s%s%s" % (
                                chr(226), chr(134), chr(147),
                                m2.group('behind')))

                    emblem = ' '.join(emblem)

                    if n.startswith('remotes/'):
                        remotes.append(
                            (n[8:],
                             m.group('current') is not None,
                             emblem,
                             m.group('name')))
                    else:
                        branches.append(
                            (n,
                             m.group('current') is not None,
                             emblem,
                             m.group('name')))

        def __tags():
            p = self._git(['tag'])
            tags = []
            while True:
                line = yield p.wait_line()
                if line is None:
                    visitor.branches('tags', 'vcs-tag-symbolic', tags)
                    break
                tags.append((line, False, '', line))

        def __stashes():
            p = self._git(['stash', 'list'])
            stashes = []
            while True:
                line = yield p.wait_line()
                if line is None:
                    visitor.branches('stashes', 'vcs-stash-symbolic', stashes)
                    break
                name, branch, descr = line.split(':', 3)
                stashes.append(('%s: %s' % (name, descr), False, branch, name))

        a = yield join(__branches(), __tags(), __stashes())