Rev 1428: Merge tags support. in http://people.samba.org/bzr/jelmer/bzr-svn/trunk
Jelmer Vernooij
jelmer at samba.org
Thu Jul 3 22:18:45 BST 2008
At http://people.samba.org/bzr/jelmer/bzr-svn/trunk
------------------------------------------------------------
revno: 1428
revision-id: jelmer at samba.org-20080703211843-5twv11n03hlqcedq
parent: jelmer at samba.org-20080703173958-z5y00jn963j3absk
parent: jelmer at samba.org-20080703211244-2vlo1z5fshvrq1li
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: 0.4
timestamp: Thu 2008-07-03 23:18:43 +0200
message:
Merge tags support.
modified:
NEWS news-20061231030336-h9fhq245ie0de8bs-1
branch.py svnbranch.py-20051017135706-11c749eb0dab04a7
layout.py layout.py-20080323165407-y9qw8nx4oykvoe1k-1
mapping3/__init__.py __init__.py-20080502174630-9324zh25kka98vlw-1
mapping3/scheme.py scheme.py-20060516195850-95181aae6b272f9e
repository.py repository.py-20060306123302-1f8c5069b3fe0265
tests/test_branch.py test_branch.py-20060508162215-74ffeb5d608f8e20
tests/test_repository.py test_repos.py-20060508151940-ddc49a59257ca712
tests/test_scheme.py test_scheme.py-20060621221855-va2xabhlxpmc9llx-1
------------------------------------------------------------
revno: 1427.1.7
revision-id: jelmer at samba.org-20080703211244-2vlo1z5fshvrq1li
parent: jelmer at samba.org-20080703211228-3bvk5itd516n75px
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 23:12:44 +0200
message:
Support proper Bazaar tags.
modified:
NEWS news-20061231030336-h9fhq245ie0de8bs-1
------------------------------------------------------------
revno: 1427.1.6
revision-id: jelmer at samba.org-20080703211228-3bvk5itd516n75px
parent: jelmer at samba.org-20080703203944-ro3eh9caweh59aav
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 23:12:28 +0200
message:
Support setting tags.
modified:
branch.py svnbranch.py-20051017135706-11c749eb0dab04a7
tests/test_branch.py test_branch.py-20060508162215-74ffeb5d608f8e20
------------------------------------------------------------
revno: 1427.1.5
revision-id: jelmer at samba.org-20080703203944-ro3eh9caweh59aav
parent: jelmer at samba.org-20080703203327-5bplovdvone200dp
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 22:39:44 +0200
message:
Implement tag lookup.
modified:
branch.py svnbranch.py-20051017135706-11c749eb0dab04a7
tests/test_branch.py test_branch.py-20060508162215-74ffeb5d608f8e20
------------------------------------------------------------
revno: 1427.1.4
revision-id: jelmer at samba.org-20080703203327-5bplovdvone200dp
parent: jelmer at samba.org-20080703201334-n4gkcyfsndegaoi2
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 22:33:27 +0200
message:
Support deleting tags.
modified:
branch.py svnbranch.py-20051017135706-11c749eb0dab04a7
mapping3/__init__.py __init__.py-20080502174630-9324zh25kka98vlw-1
mapping3/scheme.py scheme.py-20060516195850-95181aae6b272f9e
tests/test_branch.py test_branch.py-20060508162215-74ffeb5d608f8e20
tests/test_scheme.py test_scheme.py-20060621221855-va2xabhlxpmc9llx-1
------------------------------------------------------------
revno: 1427.1.3
revision-id: jelmer at samba.org-20080703201334-n4gkcyfsndegaoi2
parent: jelmer at samba.org-20080703185323-pfj2a2qtitnh6zop
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 22:13:34 +0200
message:
Implement get_tag_dict for subversion branches.
modified:
branch.py svnbranch.py-20051017135706-11c749eb0dab04a7
layout.py layout.py-20080323165407-y9qw8nx4oykvoe1k-1
repository.py repository.py-20060306123302-1f8c5069b3fe0265
tests/test_branch.py test_branch.py-20060508162215-74ffeb5d608f8e20
------------------------------------------------------------
revno: 1427.1.2
revision-id: jelmer at samba.org-20080703185323-pfj2a2qtitnh6zop
parent: jelmer at samba.org-20080703184844-6s1i7aakg9glmmfh
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 20:53:23 +0200
message:
Add find_tags.
modified:
repository.py repository.py-20060306123302-1f8c5069b3fe0265
tests/test_repository.py test_repos.py-20060508151940-ddc49a59257ca712
------------------------------------------------------------
revno: 1427.1.1
revision-id: jelmer at samba.org-20080703184844-6s1i7aakg9glmmfh
parent: jelmer at samba.org-20080703173958-z5y00jn963j3absk
committer: Jelmer Vernooij <jelmer at samba.org>
branch nick: tags
timestamp: Thu 2008-07-03 20:48:44 +0200
message:
Implement get_tags, skip tags in get_branches.
modified:
mapping3/__init__.py __init__.py-20080502174630-9324zh25kka98vlw-1
=== modified file 'NEWS'
--- a/NEWS 2008-07-01 15:58:38 +0000
+++ b/NEWS 2008-07-03 21:12:44 +0000
@@ -28,6 +28,8 @@
* Add new "dpush" command that works similar to git-svn's dcommit.
+ * Support proper Bazaar tags. (#81102)
+
BUG FIXES
* More efficient use of mutter.
=== modified file 'branch.py'
--- a/branch.py 2008-07-01 21:10:34 +0000
+++ b/branch.py 2008-07-03 21:12:28 +0000
@@ -19,9 +19,10 @@
from bzrlib.branch import Branch, BranchFormat, BranchCheckResult, PullResult
from bzrlib.bzrdir import BzrDir
from bzrlib.errors import (NoSuchFile, DivergedBranches, NoSuchRevision,
- NotBranchError, UnstackableBranchFormat)
+ NoSuchTag, NotBranchError, UnstackableBranchFormat)
from bzrlib.inventory import (Inventory)
from bzrlib.revision import is_null, ensure_null, NULL_REVISION
+from bzrlib.tag import BasicTags
from bzrlib.workingtree import WorkingTree
from bzrlib.plugins.svn import core
@@ -51,6 +52,76 @@
pass
+class SubversionTags(BasicTags):
+ def __init__(self, branch, layout=None, project=""):
+ self.branch = branch
+ self.repository = branch.repository
+ self.layout = layout or self.repository.get_layout()
+ self.project = project
+
+ def set_tag(self, tag_name, tag_target):
+ path = self.layout.get_tag_path(tag_name, self.project)
+ parent = urlutils.dirname(path)
+ (from_bp, from_revnum, mapping) = self.repository.lookup_revision_id(tag_target)
+ conn = self.repository.transport.connections.get(urlutils.join(self.repository.base, parent))
+ deletefirst = (conn.check_path(urlutils.basename(path), self.repository.get_latest_revnum()) != core.NODE_NONE)
+ try:
+ ci = conn.get_commit_editor({"svn:log": "Add tag %s" % tag_name})
+ try:
+ root = ci.open_root()
+ if deletefirst:
+ root.delete_entry(urlutils.basename(path))
+ root.add_directory(urlutils.basename(path), urlutils.join(self.repository.base, from_bp), from_revnum)
+ root.close()
+ except:
+ ci.abort()
+ raise
+ ci.close()
+ finally:
+ self.repository.transport.add_connection(conn)
+
+ def lookup_tag(self, tag_name):
+ try:
+ return self.get_tag_dict()[tag_name]
+ except KeyError:
+ raise NoSuchTag(tag_name)
+
+ def get_tag_dict(self):
+ return self.repository.find_tags(project=self.project,
+ layout=self.layout)
+
+ def get_reverse_tag_dict(self):
+ """Returns a dict with revisions as keys
+ and a list of tags for that revision as value"""
+ d = self.get_tag_dict()
+ rev = {}
+ for key in d:
+ try:
+ rev[d[key]].append(key)
+ except KeyError:
+ rev[d[key]] = [key]
+ return rev
+
+ def delete_tag(self, tag_name):
+ path = self.layout.get_tag_path(tag_name, self.project)
+ parent = urlutils.dirname(path)
+ conn = self.repository.transport.connections.get(urlutils.join(self.repository.base, parent))
+ if conn.check_path(urlutils.basename(path), self.repository.get_latest_revnum()) != core.NODE_DIR:
+ raise NoSuchTag(tag_name)
+ try:
+ ci = conn.get_commit_editor({"svn:log": "Remove tag %s" % tag_name})
+ try:
+ root = ci.open_root()
+ root.delete_entry(urlutils.basename(path))
+ root.close()
+ except:
+ ci.abort()
+ raise
+ ci.close()
+ finally:
+ self.repository.transport.add_connection(conn)
+
+
class SvnBranch(Branch):
"""Maps to a Branch in a Subversion repository """
def __init__(self, repository, branch_path):
@@ -62,8 +133,8 @@
:param revnum: Subversion revision number of the branch to
look at; none for latest.
"""
+ self.repository = repository
super(SvnBranch, self).__init__()
- self.repository = repository
assert isinstance(self.repository, SvnRepository)
self.control_files = FakeControlFiles()
self._format = SvnBranchFormat()
@@ -86,6 +157,9 @@
if not self.mapping.is_branch(branch_path):
raise NotSvnBranchPath(branch_path, mapping=self.mapping)
+ def _make_tags(self):
+ return SubversionTags(self)
+
def set_branch_path(self, branch_path):
"""Change the branch path for this branch.
=== modified file 'layout.py'
--- a/layout.py 2008-07-01 19:26:24 +0000
+++ b/layout.py 2008-07-03 20:13:34 +0000
@@ -70,7 +70,7 @@
"""
raise NotImplementedError
- def get_tags(self, project="", revnum=None):
+ def get_tags(self, revnum, project="", pb=None):
"""Retrieve a list of paths that refer to tags in a specific revision.
:result: Iterator over tuples with (project, branch path)
=== modified file 'mapping3/__init__.py'
--- a/mapping3/__init__.py 2008-07-02 00:25:10 +0000
+++ b/mapping3/__init__.py 2008-07-03 20:33:27 +0000
@@ -82,7 +82,7 @@
type = "branch"
return (type, "", bp, rp)
- def get_branches(self, revnum, project="", pb=None):
+ def _get_root_paths(self, revnum, verify_fn, project="", pb=None):
def check_path(path):
return self.repository.transport.check_path(path, revnum) == NODE_DIR
def find_children(path):
@@ -100,7 +100,17 @@
pb.update("finding branches", idx, len(self.scheme.branch_list))
for bp in expand_branch_pattern([], pattern.split("/"), check_path,
find_children):
- yield "", bp, bp.split("/")[-1]
+ if verify_fn(bp):
+ yield "", bp, bp.split("/")[-1]
+
+ def get_branches(self, revnum, project="", pb=None):
+ return self._get_root_paths(revnum, self.scheme.is_branch, project, pb)
+
+ def get_tags(self, revnum, project="", pb=None):
+ return self._get_root_paths(revnum, self.scheme.is_tag, project, pb)
+
+ def get_tag_path(self, name, project=""):
+ return self.scheme.get_tag_path(name)
def is_branch_parent(self, path):
# Na, na, na...
=== modified file 'mapping3/scheme.py'
--- a/mapping3/scheme.py 2008-06-05 17:26:28 +0000
+++ b/mapping3/scheme.py 2008-07-03 20:33:27 +0000
@@ -15,7 +15,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Branching scheme implementations."""
-from bzrlib import ui
+from bzrlib import ui, urlutils
from bzrlib.errors import BzrError
from bzrlib.trace import mutter
@@ -47,6 +47,13 @@
"""
raise NotImplementedError
+ def get_tag_path(self, name):
+ """Find the path for a tag.
+
+ :param name: Tag name.
+ """
+ raise NotImplementedError
+
@staticmethod
def find_scheme(name):
"""Find a branching scheme by name.
@@ -246,6 +253,12 @@
"*/" * level + "branches/*",
"*/" * level + "tags/*"])
+ def get_tag_path(self, name):
+ # Only implemented for level 0
+ if self.level == 0:
+ return urlutils.join("tags", name)
+ raise NotImplementedError
+
def is_branch(self, path):
"""See BranchingScheme.is_branch()."""
parts = path.strip("/").split("/")
=== modified file 'repository.py'
--- a/repository.py 2008-07-03 17:39:58 +0000
+++ b/repository.py 2008-07-03 20:13:34 +0000
@@ -728,6 +728,30 @@
pb.finished()
return branches
+ @needs_read_lock
+ def find_tags(self, layout=None, revnum=None, project=None):
+ """Find branches underneath this repository.
+
+ """
+ if layout is None:
+ layout = self.get_layout()
+
+ if revnum is None:
+ revnum = self.get_latest_revnum()
+
+ tags = {}
+ pb = ui.ui_factory.nested_progress_bar()
+ try:
+ for project, bp, nick in layout.get_tags(revnum, project=project, pb=pb):
+ try:
+ tags[nick] = self.generate_revision_id(revnum, bp,
+ self.get_mapping())
+ except NotBranchError: # Skip non-directories
+ pass
+ finally:
+ pb.finished()
+ return tags
+
def find_branchpaths(self, layout, from_revnum=0, to_revnum=None):
"""Find all branch paths that were changed in the specified revision
range.
=== modified file 'tests/test_branch.py'
--- a/tests/test_branch.py 2008-07-01 21:10:09 +0000
+++ b/tests/test_branch.py 2008-07-03 21:12:28 +0000
@@ -19,7 +19,7 @@
from bzrlib import urlutils
from bzrlib.branch import Branch
from bzrlib.bzrdir import BzrDir
-from bzrlib.errors import NoSuchFile, NoSuchRevision, NotBranchError
+from bzrlib.errors import NoSuchFile, NoSuchRevision, NotBranchError, NoSuchTag
from bzrlib.repository import Repository
from bzrlib.revision import NULL_REVISION
from bzrlib.trace import mutter
@@ -27,6 +27,7 @@
import os
from unittest import TestCase
+from bzrlib.plugins.svn import core
from bzrlib.plugins.svn.branch import FakeControlFiles, SvnBranchFormat
from bzrlib.plugins.svn.convert import load_dumpfile
from bzrlib.plugins.svn.mapping import SVN_PROP_BZR_REVISION_ID
@@ -46,6 +47,84 @@
branch = Branch.open(repos_url)
self.assertEqual("", branch.get_branch_path())
+ def test_tags_dict(self):
+ repos_url = self.make_repository("a")
+
+ dc = self.get_commit_editor(repos_url)
+ tags = dc.add_dir("tags")
+ tags.add_dir("tags/foo")
+ dc.add_dir("trunk")
+ dc.close()
+
+ b = Branch.open(repos_url + "/trunk")
+ self.assertEquals(["foo"], b.tags.get_tag_dict().keys())
+
+ def test_tag_set(self):
+ repos_url = self.make_repository('a')
+
+ dc = self.get_commit_editor(repos_url)
+ dc.add_dir("trunk")
+ dc.add_dir("tags")
+ dc.close()
+
+ dc = self.get_commit_editor(repos_url)
+ trunk = dc.open_dir("trunk")
+ trunk.add_file("trunk/bla").modify()
+ dc.close()
+
+ b = Branch.open(repos_url + "/trunk")
+ b.tags.set_tag("mytag", b.repository.generate_revision_id(1, "trunk", b.repository.get_mapping()))
+
+ self.assertEquals(core.NODE_DIR,
+ b.repository.transport.check_path("tags/mytag", 3))
+
+ def test_tags_delete(self):
+ repos_url = self.make_repository("a")
+
+ dc = self.get_commit_editor(repos_url)
+ tags = dc.add_dir("tags")
+ tags.add_dir("tags/foo")
+ dc.add_dir("trunk")
+ dc.close()
+
+ b = Branch.open(repos_url + "/trunk")
+ self.assertEquals(["foo"], b.tags.get_tag_dict().keys())
+ b.tags.delete_tag("foo")
+ b = Branch.open(repos_url + "/trunk")
+ self.assertEquals([], b.tags.get_tag_dict().keys())
+
+ def test_tag_lookup(self):
+ repos_url = self.make_repository("a")
+
+ dc = self.get_commit_editor(repos_url)
+ tags = dc.add_dir("tags")
+ tags.add_dir("tags/foo")
+ dc.add_dir("trunk")
+ dc.close()
+
+ b = Branch.open(repos_url + "/trunk")
+ self.assertEquals(b.repository.generate_revision_id(1, "tags/foo", b.repository.get_mapping()), b.tags.lookup_tag("foo"))
+
+ def test_tag_lookup_nonexistant(self):
+ repos_url = self.make_repository("a")
+
+ dc = self.get_commit_editor(repos_url)
+ dc.add_dir("trunk")
+ dc.close()
+
+ b = Branch.open(repos_url + "/trunk")
+ self.assertRaises(NoSuchTag, b.tags.lookup_tag, "foo")
+
+ def test_tags_delete_nonexistent(self):
+ repos_url = self.make_repository("a")
+
+ dc = self.get_commit_editor(repos_url)
+ dc.add_dir("trunk")
+ dc.close()
+
+ b = Branch.open(repos_url + "/trunk")
+ self.assertRaises(NoSuchTag, b.tags.delete_tag, "foo")
+
def test_get_branch_path_old(self):
repos_url = self.make_repository("a")
=== modified file 'tests/test_repository.py'
--- a/tests/test_repository.py 2008-07-01 12:46:51 +0000
+++ b/tests/test_repository.py 2008-07-03 18:53:23 +0000
@@ -401,6 +401,21 @@
self.assertEquals(urlutils.join(repos.base, "branches/branchab"),
branches[0].base)
+ def test_find_tags(self):
+ repos_url = self.make_client('a', 'dc')
+ self.build_tree({
+ 'dc/tags/brancha': None,
+ 'dc/tags/branchab': None,
+ 'dc/tags/brancha/data': "data",
+ "dc/tags/branchab/data":"data"})
+ self.client_add("dc/tags")
+ self.client_commit("dc", "My Message")
+ repos = Repository.open(repos_url)
+ set_branching_scheme(repos, TrunkBranchingScheme())
+ tags = repos.find_tags()
+ self.assertEquals({"brancha": repos.generate_revision_id(1, "tags/brancha", repos.get_mapping()),
+ "branchab": repos.generate_revision_id(1, "tags/branchab", repos.get_mapping())}, tags)
+
def test_find_branchpaths_moved(self):
repos_url = self.make_client("a", "dc")
self.build_tree({
=== modified file 'tests/test_scheme.py'
--- a/tests/test_scheme.py 2008-06-04 15:20:12 +0000
+++ b/tests/test_scheme.py 2008-07-03 20:33:27 +0000
@@ -446,6 +446,15 @@
def test_is_branch_parent_other(self):
self.assertFalse(TrunkBranchingScheme().is_branch_parent("trunk/foo"))
+ def test_get_tag_path_zero(self):
+ self.assertEquals("tags/foo",
+ TrunkBranchingScheme().get_tag_path("foo"))
+
+ def test_get_tag_path_nonzero(self):
+ self.assertRaises(NotImplementedError,
+ TrunkBranchingScheme(2).get_tag_path, "foo")
+
+
class SingleBranchingSchemeTests(TestCase):
def test_is_branch(self):
More information about the bazaar-commits
mailing list