Rev 1605: Avoid enumerating branches when searching for tags and vice-versa. in http://people.samba.org/bzr/jelmer/bzr-svn/trunk

Jelmer Vernooij jelmer at samba.org
Fri Aug 22 21:41:06 BST 2008


At http://people.samba.org/bzr/jelmer/bzr-svn/trunk

------------------------------------------------------------
revno: 1605
revision-id: jelmer at samba.org-20080822204103-xdf23m6sgj5jvjnc
parent: jelmer at samba.org-20080822163929-9p3ljwe6g6f5gitn
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: 0.4
timestamp: Fri 2008-08-22 22:41:03 +0200
message:
  Avoid enumerating branches when searching for tags and vice-versa.
modified:
  branch.py                      svnbranch.py-20051017135706-11c749eb0dab04a7
  mapping3/__init__.py           __init__.py-20080502174630-9324zh25kka98vlw-1
  mapping3/scheme.py             scheme.py-20060516195850-95181aae6b272f9e
  repository.py                  repository.py-20060306123302-1f8c5069b3fe0265
=== modified file 'branch.py'
--- a/branch.py	2008-08-22 14:20:19 +0000
+++ b/branch.py	2008-08-22 20:41:03 +0000
@@ -93,9 +93,10 @@
         except KeyError:
             raise NoSuchTag(tag_name)
 
-    def get_tag_dict(self):
+    def get_tag_dict(self, _from_revnum=0):
         return self.repository.find_tags(project=self.branch.project, 
-                                         layout=self.branch.layout)
+                                         layout=self.branch.layout,
+                                         from_revnum=_from_revnum)
 
     def get_reverse_tag_dict(self):
         """Returns a dict with revisions as keys
@@ -137,6 +138,45 @@
             if k not in dest_dict:
                 self.delete_tag(k)
 
+    def merge_to(self, to_tags, overwrite=False, _from_revnum=None):
+        """Copy tags between repositories if necessary and possible.
+        
+        This method has common command-line behaviour about handling 
+        error cases.
+
+        All new definitions are copied across, except that tags that already
+        exist keep their existing definitions.
+
+        :param to_tags: Branch to receive these tags
+        :param overwrite: Overwrite conflicting tags in the target branch
+        :param _from_revnum: Revision number since which to check tags.
+
+        :returns: A list of tags that conflicted, each of which is 
+            (tagname, source_target, dest_target), or None if no copying was
+            done.
+        """
+        if self.branch == to_tags.branch:
+            return
+        if not self.supports_tags():
+            # obviously nothing to copy
+            return
+        source_dict = self.get_tag_dict(_from_revnum=_from_revnum)
+        if not source_dict:
+            # no tags in the source, and we don't want to clobber anything
+            # that's in the destination
+            return
+        to_tags.branch.lock_write()
+        try:
+            dest_dict = to_tags.get_tag_dict()
+            result, conflicts = self._reconcile_tags(source_dict, dest_dict,
+                                                     overwrite)
+            if result != dest_dict:
+                to_tags._set_tag_dict(result)
+        finally:
+            to_tags.branch.unlock()
+        return conflicts
+
+
 
 class SvnBranch(Branch):
     """Maps to a Branch in a Subversion repository """
@@ -444,8 +484,10 @@
         source.lock_read()
         try:
             (result.old_revno, result.old_revid) = self.last_revision_info()
+            old_revnum = self.get_revnum()
             self.update_revisions(source, stop_revision, overwrite)
-            result.tag_conflicts = source.tags.merge_to(self.tags, overwrite)
+            result.tag_conflicts = source.tags.merge_to(self.tags, overwrite, 
+                                                        _from_revnum=old_revnum)
             (result.new_revno, result.new_revid) = self.last_revision_info()
             return result
         finally:

=== modified file 'mapping3/__init__.py'
--- a/mapping3/__init__.py	2008-08-22 15:47:02 +0000
+++ b/mapping3/__init__.py	2008-08-22 20:41:03 +0000
@@ -89,7 +89,7 @@
             type = "branch"
         return (type, proj, bp, rp)
 
-    def _get_root_paths(self, revnum, verify_fn, project=None, pb=None):
+    def _get_root_paths(self, itemlist, revnum, verify_fn, project=None, pb=None):
         def check_path(path):
             return self.repository.transport.check_path(path, revnum) == NODE_DIR
         def find_children(path):
@@ -102,19 +102,19 @@
                 raise
             return [d for d in dirents if dirents[d]['kind'] == NODE_DIR]
 
-        for idx, pattern in enumerate(self.scheme.branch_list):
+        for idx, pattern in enumerate(itemlist):
             if pb is not None:
-                pb.update("finding branches", idx, len(self.scheme.branch_list))
+                pb.update("finding branches", idx, len(itemlist))
             for bp in expand_branch_pattern([], pattern.split("/"), check_path,
                     find_children, project):
                 if verify_fn(bp, project):
                     yield "", bp, bp.split("/")[-1]
 
     def get_branches(self, revnum, project=None, pb=None):
-        return self._get_root_paths(revnum, self.scheme.is_branch, project, pb)
+        return self._get_root_paths(self.scheme.branch_list, revnum, self.scheme.is_branch, project, pb)
 
     def get_tags(self, revnum, project=None, pb=None):
-        return self._get_root_paths(revnum, self.scheme.is_tag, project, pb)
+        return self._get_root_paths(self.scheme.tag_list, revnum, self.scheme.is_tag, project, pb)
 
     def get_tag_path(self, name, project=""):
         return self.scheme.get_tag_path(name, project)

=== modified file 'mapping3/scheme.py'
--- a/mapping3/scheme.py	2008-08-22 05:02:07 +0000
+++ b/mapping3/scheme.py	2008-08-22 20:41:03 +0000
@@ -152,7 +152,7 @@
 class ListBranchingScheme(BranchingScheme):
     """Branching scheme that keeps a list of branch paths, including 
     wildcards."""
-    def __init__(self, branch_list):
+    def __init__(self, branch_list, tag_list=[]):
         """Create new ListBranchingScheme instance.
 
         :param branch_list: List of know branch locations.
@@ -161,6 +161,7 @@
         if isinstance(branch_list, str):
             branch_list = bz2.decompress(prop_name_unquote(branch_list.encode("ascii"))).splitlines()
         self.branch_list = [p.strip("/") for p in branch_list]
+        self.tag_list = tag_list
         self.split_branch_list = [p.split("/") for p in self.branch_list]
 
     def __str__(self):
@@ -199,7 +200,8 @@
         raise InvalidSvnBranchPath(path, self)
 
     def __eq__(self, other):
-        return self.branch_list == other.branch_list
+        return (self.branch_list == other.branch_list and \
+                self.tag_list == other.tag_list)
 
     def to_lines(self):
         return self.branch_list
@@ -260,8 +262,8 @@
         self.level = level
         ListBranchingScheme.__init__(self,
             ["*/" * level + "trunk",
-             "*/" * level + "branches/*",
-             "*/" * level + "tags/*"])
+             "*/" * level + "branches/*"])
+        self.tag_list = ["*/" * level + "tags/*"]
 
     def get_tag_path(self, name, project=""):
         if project == "":

=== modified file 'repository.py'
--- a/repository.py	2008-08-22 15:47:02 +0000
+++ b/repository.py	2008-08-22 20:41:03 +0000
@@ -791,7 +791,7 @@
         return branches
 
     @needs_read_lock
-    def find_tags(self, project, layout=None, revnum=None):
+    def find_tags(self, project, layout=None, from_revnum=0, to_revnum=None):
         """Find tags underneath this repository for the specified project.
 
         :param layout: Repository layout to use
@@ -802,8 +802,8 @@
         if layout is None:
             layout = self.get_layout()
 
-        if revnum is None:
-            revnum = self.get_latest_revnum()
+        if to_revnum is None:
+            to_revnum = self.get_latest_revnum()
 
         mapping = self.get_mapping()
 
@@ -811,11 +811,13 @@
         pb = ui.ui_factory.nested_progress_bar()
         pb.update("finding tags")
         try:
-            for project, bp, nick in layout.get_tags(revnum, project=project, pb=pb):
+            for project, bp, nick in layout.get_tags(to_revnum, project=project, pb=pb):
                 pb.tick()
                 npb = ui.ui_factory.nested_progress_bar()
                 try:
-                    it = self.iter_changes(bp, revnum, to_revnum=0, mapping=mapping, pb=npb, limit=2)
+                    it = self.iter_changes(bp, from_revnum=to_revnum, 
+                                           to_revnum=0, mapping=mapping, 
+                                           pb=npb, limit=2)
                     (bp, paths, rev, _) = it.next()
                     if paths.has_key(bp):
                         del paths[bp]




More information about the bazaar-commits mailing list