예제 #1
0
    def _get_revision(self, revision):
        """
        Gets an ID revision given as str. This will always return a fill
        40 char revision number

        :param revision: str or int or None
        """
        if isinstance(revision, unicode):
            revision = safe_str(revision)

        if self._empty:
            raise EmptyRepositoryError("There are no changesets yet")

        if revision in [-1, 'tip', None]:
            revision = 'tip'

        try:
            revision = hex(self._repo.lookup(revision))
        except (IndexError, ValueError, RepoLookupError, TypeError):
            msg = ("Revision %s does not exist for %s" % (revision, self))
            raise ChangesetDoesNotExistError(msg)
        except (LookupError, ):
            msg = ("Ambiguous identifier `%s` for %s" % (revision, self))
            raise ChangesetDoesNotExistError(msg)

        return revision
예제 #2
0
    def _get_revision(self, revision):
        """
        Gets an ID revision given as str. This will always return a fill
        40 char revision number

        :param revision: str or int or None
        """
        if isinstance(revision, unicode):
            revision = safe_str(revision)

        if self._empty:
            raise EmptyRepositoryError("There are no changesets yet")

        if revision in [-1, 'tip', None]:
            revision = 'tip'

        try:
            revision = hex(self._repo.lookup(revision))
        except (LookupError, ):
            msg = ("Ambiguous identifier `%s` for %s" % (revision, self))
            raise ChangesetDoesNotExistError(msg)
        except (IndexError, ValueError, RepoLookupError, TypeError):
            msg = ("Revision %s does not exist for %s" % (revision, self))
            raise ChangesetDoesNotExistError(msg)

        return revision
예제 #3
0
    def _get_bookmarks(self):
        if self._empty:
            return {}

        sortkey = lambda ctx: ctx[0]  # sort by name
        _bookmarks = [(safe_unicode(n), hex(h),) for n, h in
                 self._repo._bookmarks.items()]
        return OrderedDict(sorted(_bookmarks, key=sortkey, reverse=True))
예제 #4
0
 def precursors(self):
     precursors = set()
     nm = self._ctx._repo.changelog.nodemap
     for p in self._ctx._repo.obsstore.precursors.get(self._ctx.node(), ()):
         pr = nm.get(p[0])
         if pr is not None:
             precursors.add(hex(p[0])[:12])
     return precursors
예제 #5
0
    def successors(self):
        successors = obsolete.successorssets(self._ctx._repo, self._ctx.node())
        if successors:
            # flatten the list here handles both divergent (len > 1)
            # and the usual case (len = 1)
            successors = [hex(n)[:12] for sub in successors for n in sub if n != self._ctx.node()]

        return successors
예제 #6
0
    def _get_bookmarks(self):
        if self._empty:
            return {}

        sortkey = lambda ctx: ctx[0]  # sort by name
        _bookmarks = [(
            safe_unicode(n),
            hex(h),
        ) for n, h in self._repo._bookmarks.items()]
        return OrderedDict(sorted(_bookmarks, key=sortkey, reverse=True))
예제 #7
0
    def get_file_annotate(self, path):
        """
        Returns a generator of four element tuples with
            lineno, sha, changeset lazy loader and line
        """

        fctx = self._get_filectx(path)
        for i, annotate_data in enumerate(fctx.annotate()):
            ln_no = i + 1
            sha = hex(annotate_data[0].node())
            yield (ln_no, sha, lambda: self.repository.get_changeset(sha), annotate_data[1],)
예제 #8
0
    def get_file_annotate(self, path):
        """
        Returns a generator of four element tuples with
            lineno, sha, changeset lazy loader and line
        """

        fctx = self._get_filectx(path)
        for i, annotate_data in enumerate(fctx.annotate(linenumber=False)):
            ln_no = i + 1
            sha = hex(annotate_data[0][0].node())
            yield (ln_no, sha, lambda: self.repository.get_changeset(sha), annotate_data[1],)
예제 #9
0
    def _get_branches(self, normal=True, closed=False):
        """
        Gets branches for this repository
        Returns only not closed branches by default

        :param closed: return also closed branches for mercurial
        :param normal: return also normal branches
        """

        if self._empty:
            return {}

        bt = OrderedDict()
        for bn, _heads, tip, isclosed in sorted(self._repo.branchmap().iterbranches()):
            if isclosed:
                if closed:
                    bt[safe_unicode(bn)] = hex(tip)
            else:
                if normal:
                    bt[safe_unicode(bn)] = hex(tip)

        return bt
예제 #10
0
    def _get_branches(self, normal=True, closed=False):
        """
        Gets branches for this repository
        Returns only not closed branches by default

        :param closed: return also closed branches for mercurial
        :param normal: return also normal branches
        """

        if self._empty:
            return {}

        bt = OrderedDict()
        for bn, _heads, tip, isclosed in sorted(
                self._repo.branchmap().iterbranches()):
            if isclosed:
                if closed:
                    bt[safe_unicode(bn)] = hex(tip)
            else:
                if normal:
                    bt[safe_unicode(bn)] = hex(tip)

        return bt
예제 #11
0
    def get_file_history(self, path, limit=None):
        """
        Returns history of file as reversed list of ``Changeset`` objects for
        which file at given ``path`` has been modified.
        """
        fctx = self._get_filectx(path)
        hist = []
        cnt = 0
        for cs in reversed([x for x in fctx.filelog()]):
            cnt += 1
            hist.append(hex(fctx.filectx(cs).node()))
            if limit and cnt == limit:
                break

        return [self.repository.get_changeset(node) for node in hist]
예제 #12
0
    def get_file_history(self, path, limit=None):
        """
        Returns history of file as reversed list of ``Changeset`` objects for
        which file at given ``path`` has been modified.
        """
        fctx = self._get_filectx(path)
        hist = []
        cnt = 0
        for cs in reversed([x for x in fctx.filelog()]):
            cnt += 1
            hist.append(hex(fctx.filectx(cs).node()))
            if limit is not None and cnt == limit:
                break

        return [self.repository.get_changeset(node) for node in hist]
예제 #13
0
    def commit(self, message, author, parents=None, branch=None, date=None,
            **kwargs):
        """
        Performs in-memory commit (doesn't check workdir in any way) and
        returns newly created ``Changeset``. Updates repository's
        ``revisions``.

        :param message: message of the commit
        :param author: full username, i.e. "Joe Doe <*****@*****.**>"
        :param parents: single parent or sequence of parents from which commit
          would be derived
        :param date: ``datetime.datetime`` instance. Defaults to
          ``datetime.datetime.now()``.
        :param branch: branch name, as string. If none given, default backend's
          branch would be used.

        :raises ``CommitError``: if any error occurs while committing
        """
        self.check_integrity(parents)

        from .repository import MercurialRepository
        if not isinstance(message, unicode) or not isinstance(author, unicode):
            raise RepositoryError('Given message and author needs to be '
                                  'an <unicode> instance got %r & %r instead'
                                  % (type(message), type(author)))

        if branch is None:
            branch = MercurialRepository.DEFAULT_BRANCH_NAME
        kwargs['branch'] = branch

        def filectxfn(_repo, memctx, path):
            """
            Marks given path as added/changed/removed in a given _repo. This is
            for internal mercurial commit function.
            """

            # check if this path is removed
            if path in (node.path for node in self.removed):
                if getattr(memctx, '_returnnoneformissingfiles', False):
                    return None
                else:
                    # (hg < 3.2) Raising exception is the way to mark node for
                    # removal
                    raise IOError(errno.ENOENT, '%s is deleted' % path)

            # check if this path is added
            for node in self.added:
                if node.path == path:
                    return memfilectx(_repo, path=node.path,
                        data=(node.content.encode('utf8')
                              if not node.is_binary else node.content),
                        islink=False,
                        isexec=node.is_executable,
                        copied=False)

            # or changed
            for node in self.changed:
                if node.path == path:
                    return memfilectx(_repo, path=node.path,
                        data=(node.content.encode('utf8')
                              if not node.is_binary else node.content),
                        islink=False,
                        isexec=node.is_executable,
                        copied=False)

            raise RepositoryError("Given path haven't been marked as added,"
                                  "changed or removed (%s)" % path)

        parents = [None, None]
        for i, parent in enumerate(self.parents):
            if parent is not None:
                parents[i] = parent._ctx.node()

        if date and isinstance(date, datetime.datetime):
            date = date.ctime()

        commit_ctx = memctx(repo=self.repository._repo,
            parents=parents,
            text='',
            files=self.get_paths(),
            filectxfn=filectxfn,
            user=author,
            date=date,
            extra=kwargs)

        loc = lambda u: tolocal(u.encode('utf-8'))

        # injecting given _repo params
        commit_ctx._text = loc(message)
        commit_ctx._user = loc(author)
        commit_ctx._date = date

        # TODO: Catch exceptions!
        n = self.repository._repo.commitctx(commit_ctx)
        # Returns mercurial node
        self._commit_ctx = commit_ctx  # For reference
        # Update vcs repository object & recreate mercurial _repo
        # new_ctx = self.repository._repo[node]
        # new_tip = self.repository.get_changeset(new_ctx.hex())
        new_id = hex(n)
        self.repository.revisions.append(new_id)
        self._repo = self.repository._get_repo(create=False)
        self.repository.branches = self.repository._get_branches()
        tip = self.repository.get_changeset()
        self.reset()
        return tip
예제 #14
0
    def _get_all_revisions(self):

        return map(lambda x: hex(x[7]), self._repo.changelog.index)[:-1]
예제 #15
0
    def commit(self,
               message,
               author,
               parents=None,
               branch=None,
               date=None,
               **kwargs):
        """
        Performs in-memory commit (doesn't check workdir in any way) and
        returns newly created ``Changeset``. Updates repository's
        ``revisions``.

        :param message: message of the commit
        :param author: full username, i.e. "Joe Doe <*****@*****.**>"
        :param parents: single parent or sequence of parents from which commit
          would be derived
        :param date: ``datetime.datetime`` instance. Defaults to
          ``datetime.datetime.now()``.
        :param branch: branch name, as string. If none given, default backend's
          branch would be used.

        :raises ``CommitError``: if any error occurs while committing
        """
        self.check_integrity(parents)

        from .repository import MercurialRepository
        if not isinstance(message, unicode) or not isinstance(author, unicode):
            raise RepositoryError('Given message and author needs to be '
                                  'an <unicode> instance got %r & %r instead' %
                                  (type(message), type(author)))

        if branch is None:
            branch = MercurialRepository.DEFAULT_BRANCH_NAME
        kwargs['branch'] = branch

        def filectxfn(_repo, memctx, path):
            """
            Marks given path as added/changed/removed in a given _repo. This is
            for internal mercurial commit function.
            """

            # check if this path is removed
            if path in (node.path for node in self.removed):
                if getattr(memctx, '_returnnoneformissingfiles', False):
                    return None
                else:
                    # (hg < 3.2) Raising exception is the way to mark node for
                    # removal
                    raise IOError(errno.ENOENT, '%s is deleted' % path)

            # check if this path is added
            for node in self.added:
                if node.path == path:
                    return memfilectx(
                        _repo,
                        path=node.path,
                        data=(node.content.encode('utf8')
                              if not node.is_binary else node.content),
                        islink=False,
                        isexec=node.is_executable,
                        copied=False)

            # or changed
            for node in self.changed:
                if node.path == path:
                    return memfilectx(
                        _repo,
                        path=node.path,
                        data=(node.content.encode('utf8')
                              if not node.is_binary else node.content),
                        islink=False,
                        isexec=node.is_executable,
                        copied=False)

            raise RepositoryError("Given path haven't been marked as added,"
                                  "changed or removed (%s)" % path)

        parents = [None, None]
        for i, parent in enumerate(self.parents):
            if parent is not None:
                parents[i] = parent._ctx.node()

        if date and isinstance(date, datetime.datetime):
            date = date.strftime('%a, %d %b %Y %H:%M:%S')

        commit_ctx = memctx(repo=self.repository._repo,
                            parents=parents,
                            text='',
                            files=self.get_paths(),
                            filectxfn=filectxfn,
                            user=author,
                            date=date,
                            extra=kwargs)

        loc = lambda u: tolocal(u.encode('utf-8'))

        # injecting given _repo params
        commit_ctx._text = loc(message)
        commit_ctx._user = loc(author)
        commit_ctx._date = date

        # TODO: Catch exceptions!
        n = self.repository._repo.commitctx(commit_ctx)
        # Returns mercurial node
        self._commit_ctx = commit_ctx  # For reference
        # Update vcs repository object & recreate mercurial _repo
        # new_ctx = self.repository._repo[node]
        # new_tip = self.repository.get_changeset(new_ctx.hex())
        new_id = hex(n)
        self.repository.revisions.append(new_id)
        self._repo = self.repository._get_repo(create=False)
        self.repository.branches = self.repository._get_branches()
        tip = self.repository.get_changeset()
        self.reset()
        return tip
예제 #16
0
    def _get_all_revisions(self):

        return map(lambda x: hex(x[7]), self._repo.changelog.index)[:-1]