Rev 1: Initial implementation of the srevid: revision spec. in http://bzr.arbash-meinel.com/plugins/short_revid_spec
John Arbash Meinel
john at arbash-meinel.com
Wed Apr 11 02:46:49 BST 2007
At http://bzr.arbash-meinel.com/plugins/short_revid_spec
------------------------------------------------------------
revno: 1
revision-id: john at arbash-meinel.com-20070411014644-ghyfdebn2stler1h
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: short_revid_spec
timestamp: Tue 2007-04-10 20:46:44 -0500
message:
Initial implementation of the srevid: revision spec.
Basically it just matches the tail of revision ids,
which makes it a bit easier to handle long revision ids.
added:
__init__.py __init__.py-20070411002806-hc1qgc5ne5r41ral-1
srevid_spec.py srevid_spec.py-20070411002806-hc1qgc5ne5r41ral-2
test_short_revid_spec.py test_short_revid_spe-20070411002806-hc1qgc5ne5r41ral-3
-------------- next part --------------
=== added file '__init__.py'
--- a/__init__.py 1970-01-01 00:00:00 +0000
+++ b/__init__.py 2007-04-11 01:46:44 +0000
@@ -0,0 +1,33 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Implement the srevid: revision spec.
+
+An attempt to do simple matching for revision ids, allowing you to only supply
+a portion of the revision id, rather than the whole thing (revid:) or a number
+(revno:).
+"""
+
+import srevid_spec
+
+
+def test_suite():
+ from bzrlib import tests
+
+ import test_short_revid_spec
+
+ loader = tests.TestLoader()
+ return loader.loadTestsFromModule(test_short_revid_spec)
=== added file 'srevid_spec.py'
--- a/srevid_spec.py 1970-01-01 00:00:00 +0000
+++ b/srevid_spec.py 2007-04-11 01:46:44 +0000
@@ -0,0 +1,90 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""The srevid: revision spec."""
+
+from bzrlib import (
+ errors,
+ revisionspec,
+ )
+
+
+class RevisionSpec_srevid(revisionspec.RevisionSpec):
+ """Selects a revision id using basic matching."""
+
+ help_txt = """Selects a revision id using a matching algorithm.
+
+ Basically, you supply the last few characters of the revision id, and if
+ that is unique, it will be considered a match.
+
+ examples:
+ srevid:abe7e7 -> Select revision id 'john at foo.com-2007-on2efb7e7'
+ """
+
+ prefix = 'srevid:'
+
+ def _match_on(self, branch, revs):
+ all_revision_ids = branch.repository.get_ancestry(
+ branch.last_revision())
+ # get_ancestry always returns None as the first entry, but we don't
+ # want to match against anything but strings.
+ first = all_revision_ids.pop(0)
+ assert first is None, 'first was not None: %s' % (first,)
+ matches = self._match_against_all(all_revision_ids)
+ return self._matches_to_revision_info(branch, matches)
+
+ def _match_against_all(self, revision_ids):
+ """Match self.spec against a list of revisions.
+
+ :param revision_ids: A list of revisions to check against.
+ :param branch: Used when raising an exception because of a failure to
+ match. (Or too many matches)
+ """
+ matches = []
+ for revision_id in revision_ids:
+ if revision_id.endswith(self.spec):
+ matches.append(revision_id)
+ return matches
+
+ def _matches_to_revision_info(self, branch, revision_ids):
+ """Convert the list of matches into a RevisionInfo object.
+
+ There should actually be exactly one revision_id in the list, but we
+ will raise the correct error if there are more.
+ """
+ if not revision_ids:
+ raise errors.InvalidRevisionSpec(self.user_spec, branch=branch,
+ extra="no matching revisions")
+ if len(revision_ids) > 1:
+ raise errors.InvalidRevisionSpec(self.user_spec, branch=branch,
+ extra='matched multiple revisions:\n'
+ + '\n'.join(revision_ids))
+ revision_id = revision_ids[0]
+ try:
+ revno = branch.revision_id_to_revno(revision_id)
+ except errors.NoSuchRevision:
+ revno = None
+ return revisionspec.RevisionInfo(branch, revno, revision_ids[0])
+
+
+class RevisionSpec_r(RevisionSpec_srevid):
+ """Same as srevid:, just a shortcut."""
+ prefix = 'r:'
+
+
+revisionspec.SPEC_TYPES.append(RevisionSpec_srevid)
+revisionspec.SPEC_TYPES.append(RevisionSpec_r)
+
=== added file 'test_short_revid_spec.py'
--- a/test_short_revid_spec.py 1970-01-01 00:00:00 +0000
+++ b/test_short_revid_spec.py 2007-04-11 01:46:44 +0000
@@ -0,0 +1,118 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Tests for the srevid: spec."""
+
+from bzrlib import (
+ errors,
+ tests,
+ revisionspec,
+ )
+
+import srevid_spec
+
+
+class TestSRevid(tests.TestCase):
+ """Tests for the srevid: spec."""
+
+ def test_from_string(self):
+ """make sure we get the right object back for matching."""
+ spec = revisionspec.RevisionSpec.from_string('srevid:a')
+ self.assertIsInstance(spec, srevid_spec.RevisionSpec_srevid)
+
+ def test_from_string_r(self):
+ spec = revisionspec.RevisionSpec.from_string('r:a')
+ self.assertIsInstance(spec, srevid_spec.RevisionSpec_r)
+
+ def test_simple_ending(self):
+ revision_ids = ['test-one', 'test-two']
+ spec = revisionspec.RevisionSpec.from_string('srevid:two')
+ self.assertEqual(['test-two'], spec._match_against_all(revision_ids))
+
+ def test_multiple_matches(self):
+ """If a spec matches more than one revision, it Error"""
+ revision_ids = ['test-one', 'test-two', 'test-three']
+ spec = revisionspec.RevisionSpec.from_string('srevid:e')
+ self.assertEqual(['test-one', 'test-three'],
+ spec._match_against_all(revision_ids))
+ def test_no_matches(self):
+ revision_ids = ['test-one', 'test-two', 'test-three']
+ spec = revisionspec.RevisionSpec.from_string('srevid:four')
+ self.assertEqual([], spec._match_against_all(revision_ids))
+
+ def test_matches_to_info_none(self):
+ spec = revisionspec.RevisionSpec.from_string('srevid:four')
+ e = self.assertRaises(errors.InvalidRevisionSpec,
+ spec._matches_to_revision_info, 'branch', [])
+ self.assertEqual('srevid:four', e.spec)
+ self.assertEqual('\nno matching revisions', e.extra)
+ self.assertEqual('branch', e.branch)
+
+ def test_matches_to_info_multiple(self):
+ spec = revisionspec.RevisionSpec.from_string('srevid:e')
+ e = self.assertRaises(errors.InvalidRevisionSpec,
+ spec._matches_to_revision_info, 'branch',
+ ['test-one', 'test-three'])
+ self.assertEqual('srevid:e', e.spec)
+ self.assertEqual('\nmatched multiple revisions:\n'
+ 'test-one\ntest-three',
+ e.extra)
+ self.assertEqual('branch', e.branch)
+
+
+class TestSRevidWithBranch(tests.TestCaseWithTransport):
+ """Tests of srevid: with a real branch."""
+
+ revision_ids = ['joe at foo.com-20070411005646-h1cquzuek4fppq6d',
+ 'joe at foo.com-20070411005646-mf4fdoco5vcst5rt',
+ 'joe at foo.com-20070411005646-jekc4tb3ego9vz8q',
+ 'joe at foo.com-20070411005646-qh2f5lvu79vtfwso',
+ 'joe at foo.com-20070411005646-ocfdmf62d439nukv',
+ 'barry at foo.com-20070411005646-aoeuhoudfe423ort',
+ ]
+
+ def make_basic_branch(self):
+ tree1 = self.make_branch_and_tree('tree1')
+ tree1.lock_write()
+ try:
+ tree1.commit('first', rev_id=self.revision_ids[0])
+ tree2 = tree1.bzrdir.sprout('tree2').open_workingtree()
+ tree2.commit('alt-second', rev_id=self.revision_ids[1])
+ tree1.merge_from_branch(tree2.branch)
+ tree1.commit('second', rev_id=self.revision_ids[2])
+ tree1.commit('third', rev_id=self.revision_ids[3])
+ tree1.commit('fourth', rev_id=self.revision_ids[4])
+ tree1.commit('fifth', rev_id=self.revision_ids[5])
+ finally:
+ tree1.unlock()
+
+ return tree1.branch
+
+ def test_find_merged_revision(self):
+ branch = self.make_basic_branch()
+ spec = revisionspec.RevisionSpec.from_string('srevid:st5rt')
+ info = spec.in_history(branch)
+ self.assertEqual(self.revision_ids[1], info.rev_id)
+ self.assertEqual(branch, info.branch)
+ self.assertEqual(None, info.revno)
+
+ def test_matches_to_info_single(self):
+ branch = self.make_basic_branch()
+ spec = revisionspec.RevisionSpec.from_string('srevid:vz8q')
+ info = spec.in_history(branch)
+ self.assertEqual(self.revision_ids[2], info.rev_id)
+ self.assertEqual(branch, info.branch)
+ self.assertEqual(2, info.revno)
More information about the bazaar-commits
mailing list