Example #1
0
    def _fetch_revisions(self, to_revnum, pb=None):
        """Fetch information about all revisions in the remote repository
        until to_revnum.

        :param to_revnum: End of range to fetch information for
        """
        assert isinstance(self.saved_maxrevnum, int)

        if to_revnum <= self.saved_maxrevnum and self.saved_minrevnum == 0:
            return

        # Try to fetch log data in lumps, if possible.
        if self._latest_revnum is None:
            self._latest_revnum = self.actual._transport.get_latest_revnum()
        assert isinstance(self._latest_revnum, int)
        to_revnum = max(min(self._latest_revnum, to_revnum+MAX_OVERHEAD_FETCH),
                        to_revnum)

        # Subversion 1.4 clients and servers can only deliver a limited set of
        # revprops
        if self._transport.has_capability("log-revprops"):
            todo_revprops = None
        else:
            todo_revprops = ["svn:author", "svn:log", "svn:date"]

        rcvr = CachingLogWalkerUpdater(self, todo_revprops is None)
        try:
            try:
                # The get_log bounds are inclusive at both ends, so the total
                # number of revisions requested is A - B.
                rcvr.total = to_revnum - self.saved_maxrevnum
                # Try to keep the cache consistent by closing any holes early
                # in the history
                if self.saved_minrevnum:
                    rcvr.total += self.saved_minrevnum
                    self.mutter("get_log %d->%d", self.saved_minrevnum, 0)
                    self.actual._transport.get_log(rcvr, [u""],
                        self.saved_minrevnum - 1, 0, 0, True, True, False,
                        todo_revprops)
                    if self.saved_minrevnum:
                        raise bzrsvn_errors.IncompleteRepositoryHistory(
                            "first available revision: %d" % self.saved_minrevnum)
                if to_revnum > self.saved_maxrevnum:
                    self.mutter("get_log %d->%d", to_revnum,
                            self.saved_maxrevnum)
                    self.actual._transport.get_log(rcvr, [u""], to_revnum,
                        self.saved_maxrevnum, 0, True, True, False,
                        todo_revprops)
                    if to_revnum > self.saved_maxrevnum and to_revnum > 0:
                        raise bzrsvn_errors.IncompleteRepositoryHistory(
                            "last available revision: %d" % self.saved_maxrevnum)
            except subvertpy.SubversionException as e:
                msg, num = e.args
                if num == subvertpy.ERR_FS_NO_SUCH_REVISION:
                    raise NoSuchRevision(branch=self,
                        revision="Revision number %d: %s" % (to_revnum, msg))
                raise
        finally:
            rcvr.finished()
            self.cache.commit()
Example #2
0
 def _real_get_properties(self, path, revnum):
     try:
         (_, _, props) = self.log._transport.get_dir(path, revnum)
     except SubversionException as e:
         if e.args[1] == ERR_FS_NO_SUCH_REVISION:
             raise NoSuchRevision(self, revnum)
         raise
     return props
Example #3
0
    def iter_changes(self,
                     prefixes,
                     from_revnum,
                     to_revnum=0,
                     limit=0,
                     pb=None):
        """Return iterator over all the revisions between revnum and 0 named
        path or inside path.

        :param prefixes:    Prefixes to report about (in from_revnum)
        :param from_revnum:  Start revision.
        :param to_revnum: End revision.
        :return: An iterator that yields tuples with (paths, revnum, revprops)
            where paths is a dictionary with all changes that happened in revnum.
        """
        assert from_revnum >= 0 and to_revnum >= 0

        # Subversion 1.4 clients and servers can only deliver a limited set of revprops
        if self._transport.has_capability("log-revprops"):
            todo_revprops = None
        else:
            todo_revprops = ["svn:author", "svn:log", "svn:date"]

        try:
            iterator = self._transport.iter_log(prefixes,
                                                from_revnum,
                                                to_revnum,
                                                limit,
                                                True,
                                                False,
                                                False,
                                                revprops=todo_revprops)

            for (changed_paths, revnum, known_revprops,
                 has_children) in iterator:
                if revnum == 0 and changed_paths is None:
                    revpaths = changes.REV0_CHANGES
                elif isinstance(changed_paths, dict):
                    revpaths = strip_slashes(changed_paths)
                else:
                    revpaths = {}
                if todo_revprops is None:
                    revprops = known_revprops
                    if revprops is None:
                        revprops = {}
                else:
                    revprops = lazy_dict(known_revprops,
                                         self._transport.revprop_list, revnum)
                yield (revpaths, revnum, revprops)
        except subvertpy.SubversionException as e:
            msg, num = e.args
            if num == subvertpy.ERR_FS_NO_SUCH_REVISION:
                raise NoSuchRevision(branch=self,
                                     revision="Revision number %d" %
                                     from_revnum)
            raise
Example #4
0
 def revision_id_to_revno(self, revision_id):
     """Given a revision id, return its revno"""
     if is_null(revision_id):
         return 0
     revmeta_history = self._revision_meta_history()
     # FIXME: Maybe we can parse revision_id as a bzr-svn roundtripped
     # revision?
     for revmeta, hidden, mapping in revmeta_history:
         if hidden:
             continue
         if revmeta.get_revision_id(mapping) == revision_id:
             return revmeta.get_revno(mapping)
     raise NoSuchRevision(self, revision_id)
Example #5
0
 def generate_revision_id(self, revnum):
     """Generate a new revision id for a revision on this branch."""
     assert isinstance(revnum, int)
     revmeta_history = self._revision_meta_history()
     take_next = False
     for revmeta, hidden, mapping in revmeta_history:
         if revmeta.metarev.revnum == revnum or take_next:
             if hidden:
                 take_next = True
                 continue
             return revmeta.get_revision_id(mapping)
         if revmeta.metarev.revnum < revnum:
             break
     if take_next:
         return NULL_REVISION
     raise NoSuchRevision(self, revnum)
Example #6
0
 def get_rev_id(self, revno, history=None):
     """Find the revision id of the specified revno."""
     if revno == 0:
         return NULL_REVISION
     last_revno = self.revno()
     if revno <= 0 or revno > last_revno:
         raise NoSuchRevision(self, revno)
     count = last_revno - revno
     for (revmeta, hidden, mapping) in self._revision_meta_history():
         if hidden:
             continue
         if count == 0:
             if revmeta.get_revno(mapping) != revno:
                 raise AssertionError(
                     "Expected %d, was (%r,%r) %d" %
                     (revno, revmeta, mapping, revmeta.get_revno(mapping)))
             return revmeta.get_revision_id(mapping)
         count -= 1
     raise AssertionError
Example #7
0
    def find_latest_change(self, path, revnum):
        """Find latest revision that touched path.

        :param path: Path to check for changes
        :param revnum: First revision to check
        """
        assert isinstance(path, text_type)
        assert isinstance(revnum, int) and revnum >= 0

        try:
            return self._transport.iter_log([path], revnum, 0, 2, True, False,
                    False, []).next()[1]
        except subvertpy.SubversionException as e:
            msg, num = e.args
            if num == subvertpy.ERR_FS_NO_SUCH_REVISION:
                raise NoSuchRevision(branch=self,
                    revision="Revision number %d" % revnum)
            if num == subvertpy.ERR_FS_NOT_FOUND:
                return None
            raise
Example #8
0
    def get_revision_paths(self, revnum):
        """Obtain dictionary with all the changes in a particular revision.

        :param revnum: Subversion revision number
        :returns: dictionary with paths as keys and
                  (action, copyfrom_path, copyfrom_rev) as values.
        """
        # To make the existing code happy:
        if revnum == 0:
            return changes.REV0_CHANGES

        try:
            log_iter = self._transport.iter_log([u""], revnum, revnum, 1, True,
                True, False, [])
            return strip_slashes(log_iter.next()[0])
        except subvertpy.SubversionException as e:
            msg, num = e.args
            if num == subvertpy.ERR_FS_NO_SUCH_REVISION:
                raise NoSuchRevision(branch=self,
                    revision="Revision number %d" % revnum)
            raise
Example #9
0
    def get_branch_revnum(self, revid, layout, project=None):
        if revid in self._cache:
            return self._cache[revid]

        last_revnum = self.actual.repos.get_latest_revnum()
        if self._nonexistant_revnum is not None:
            if last_revnum <= self._nonexistant_revnum:
                if revid in self._nonexistant:
                    raise NoSuchRevision(self, revid)

        try:
            ret = self.actual.get_branch_revnum(revid, layout, project)
        except NoSuchRevision:
            if self._nonexistant_revnum != last_revnum:
                self._nonexistant_revnum = last_revnum
                self._nonexistant = set()
            self._nonexistant.add(revid)
            raise
        else:
            self._cache[revid] = ret
            return ret
Example #10
0
    def get_branch_revnum(self, revid, layout, project=None):
        """Find the (branch, revnum) tuple for a revision id.

        :return: Tuple with foreign revision id and mapping.
        """
        last_revnum = self.repos.get_latest_revnum()
        fileprops_to_revnum = last_revnum
        with ui.ui_factory.nested_progress_bar() as pb:
            for entry_revid, branch, revnum, mapping in self.discover_revprop_revids(
                    last_revnum, 0, pb=pb):
                if revid == entry_revid:
                    return (self.repos.uuid, branch, revnum), mapping
                fileprops_to_revnum = min(fileprops_to_revnum, revnum)

            for entry_revid, branch, min_revno, max_revno, mapping in self.discover_fileprop_revids(
                    layout, fileprops_to_revnum, 0, project, pb=pb):
                if revid == entry_revid:
                    (foreign_revid,
                     mapping_name) = self.bisect_fileprop_revid_revnum(
                         revid, branch, min_revno, max_revno)
                    return (foreign_revid, mapping_name)
        raise NoSuchRevision(self, revid)
Example #11
0
    def copy_content(self, revision_id=None, pb=None, project=None,
            mapping=None, limit=None, lossy=False, exclude_non_mainline=None):
        """See InterRepository.copy_content."""
        with self.source.lock_read(), self.target.lock_write():
            graph = self.get_graph()
            if revision_id is not None:
                heads = [revision_id]
            else:
                heads = graph.heads(self.source.all_revision_ids())
                exclude_non_mainline = False
            todo = []
            # Go back over the LHS parent until we reach a revid we know
            for head in heads:
                try:
                    for revid in graph.iter_lefthand_ancestry(head,
                            (NULL_REVISION, None)):
                        if self._target_has_revision(revid):
                            break
                        todo.append(revid)
                except RevisionNotPresent as e:
                    raise NoSuchRevision(self.source, e.revision_id)
            todo.reverse()
            if limit is not None:
                # FIXME: This only considers mainline revisions.
                # Properly keeping track of how many revisions have been
                # pushed will be fairly complicated though, so for the
                # moment this is reasonable enough (and passes tests).
                todo = todo[:limit]
            mutter("pushing %r into svn", todo)
            base_foreign_info = None
            layout = self.target.get_layout()
            for rev in self.source.get_revisions(todo):
                if pb is not None:
                    pb.update("pushing revisions",
                        todo.index(rev.revision_id), len(todo))
                mutter('pushing %r', rev.revision_id)

                if base_foreign_info is None:
                    if rev.parent_ids:
                        base_revid = rev.parent_ids[0]
                    else:
                        base_revid = NULL_REVISION
                    base_foreign_info  = self._get_foreign_revision_info(
                        base_revid)

                (base_foreign_revid, base_mapping) = base_foreign_info
                if base_foreign_revid is None:
                    target_project = None
                else:
                    (_, target_project, _, _) = layout.parse(
                        base_foreign_revid[1])
                bp = determine_branch_path(rev, layout, target_project)
                mutter("pushing revision include %r to %s",
                        rev.revision_id, bp)
                target_config = self._get_branch_config(bp)
                can_push_merged = layout.push_merged_revisions(target_project)
                if exclude_non_mainline is None:
                    push_merged = can_push_merged and (
                        target_config.get('push_merged_revisions'))
                else:
                    push_merged = (not exclude_non_mainline)
                if push_merged and not can_push_merged:
                    raise BzrError(
                        "Unable to push merged revisions, layout "
                        "does not provide branch path")
                append_revisions_only = target_config.get('append_revisions_only')
                if append_revisions_only is None:
                    append_revisions_only = True
                root_action = self._get_root_action(bp, rev.parent_ids,
                    overwrite=False,
                    append_revisions_only=append_revisions_only,
                    create_prefix=True)
                (pushed_revid,
                        base_foreign_info) = self.push_revision_inclusive(
                    bp, target_config, rev, push_metadata=not lossy,
                    push_merged=push_merged, root_action=root_action,
                    layout=layout, project=target_project,
                    base_foreign_info=base_foreign_info)
Example #12
0
 def revision_id_to_revno(s, r):
     raise NoSuchRevision(s, r)