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