65a39843de8d

Refactor datastore initialization.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 11 Oct 2009 17:28:23 -0400
parents 74aa03e42920
children 351195574f80
branches/tags (none)
files review/api.py review/extension_ui.py review/messages.py review/tests/test_init.py review/tests/util.py

Changes

--- a/review/api.py	Sun Oct 11 11:38:15 2009 -0400
+++ b/review/api.py	Sun Oct 11 17:28:23 2009 -0400
@@ -4,7 +4,7 @@
 
 import datetime, operator, os
 import messages, templates
-from mercurial import cmdutil, hg, patch, util
+from mercurial import cmdutil, error, hg, patch, util
 from mercurial.node import hex
 
 
@@ -17,6 +17,28 @@
         self.committed = committed
     
 
+class UninitializedDatastore(Exception):
+    """Raised when trying to access a datastore that does not exist.
+    
+    The committed attribute will be True if someone else has already
+    initialized code review for the target (i.e. the .hgreview file is present
+    in the target repository), or False otherwise.
+    
+    """
+    def __init__(self, committed):
+        super(UninitializedDatastore, self).__init__()
+        self.committed = committed
+    
+
+class DatastoreRequiresRemotePath(Exception):
+    """Raised when initializing a fresh datastore without a remote path."""
+    pass
+
+class RelativeRemotePath(Exception):
+    """Raised when trying to use a relative remote path (for now)."""
+    pass
+
+
 class SignoffExists(Exception):
     """Raised when trying to signoff twice without forcing."""
     pass
@@ -157,29 +179,54 @@
         
         """
         self.ui = ui
+        self.target = repo
         
         if not create:
+            if not '.hgreview' in repo['tip']:
+                raise UninitializedDatastore(False)
+            
             data = _parse_hgrf(repo)
             self.lpath = data['lpath']
             self.rpath = data['rpath']
-        else:
-            if '.hgreview' in repo['tip']:
+            
+            datastore_root = os.path.join(self.target.root, self.lpath)
+            try:
+                self.repo = hg.repository(ui, datastore_root)
+            except error.RepoError:
+                raise UninitializedDatastore(True)
+        elif '.hgreview' in repo['tip']:
+            data = _parse_hgrf(self.target)
+            self.lpath = data['lpath']
+            self.rpath = data['rpath']
+            
+            if self.rpath.startswith('.'):
+                raise RelativeRemotePath
+            
+            try:
+                hg.repository(ui, self.lpath)
+            except error.RepoError:    
+                hg.clone(cmdutil.remoteui(self.ui, {}), self.rpath, self.lpath)
+            else:
                 raise PreexistingDatastore(True)
-            if os.path.exists(os.path.join(repo.root, '.hgreview')):
-                raise PreexistingDatastore(False)
+        elif os.path.exists(os.path.join(self.target.root, '.hgreview')):
+            raise PreexistingDatastore(False)
+        else:
+            if not rpath:
+                raise DatastoreRequiresRemotePath
+            elif rpath.startswith('.'):
+                raise RelativeRemotePath
+            else:
+                self.rpath = rpath
+            
             self.lpath = lpath or DEFAULT_DATASTORE_DIRNAME
-            self.rpath = rpath or ('../%s-review' % os.path.basename(repo.root))
-        
-        root = os.path.join(repo.root, self.lpath)
-        self.target = repo
-        self.repo = hg.repository(ui, root, create)
-        
-        if create:
-            hgrpath = os.path.join(repo.root, '.hgreview')
-            with open(hgrpath, 'w') as hgrf:
+            
+            with open(os.path.join(self.target.root, '.hgreview'), 'w') as hgrf:
                 hgrf.write('local = %s\n' % self.lpath)
                 hgrf.write('remote = %s\n' % self.rpath)
-            repo.add(['.hgreview'])
+            self.target.add(['.hgreview'])
+            
+            self.repo = hg.repository(ui,
+                os.path.join(self.target.root, self.lpath), create)
     
     def __getitem__(self, rev):
         """Return a ReviewChangeset for the given revision."""
--- a/review/extension_ui.py	Sun Oct 11 11:38:15 2009 -0400
+++ b/review/extension_ui.py	Sun Oct 11 17:28:23 2009 -0400
@@ -13,18 +13,22 @@
 
 
 def _init_command(ui, repo, **opts):
-    if not opts['remote_path']:
-        raise util.Abort(messages.INIT_REQUIRES_REMOTE_PATH)
+    ui.note(messages.INIT_START)
     
-    ui.note(messages.INIT_START)
     try:
         ReviewDatastore(ui, repo, lpath=opts.pop('local_path'),
             rpath=opts.pop('remote_path'), create=True)
-        ui.status(messages.INIT_SUCCESS)
-        return
+        if '.hgreview' not in repo['tip'].files():
+            ui.status(messages.INIT_SUCCESS_UNCOMMITTED)
+        else:
+            ui.status(messages.INIT_SUCCESS_CLONED)
+    except RelativeRemotePath:
+        raise util.Abort(messages.INIT_UNSUPPORTED_RELATIVE_RPATH)
+    except DatastoreRequiresRemotePath:
+        raise util.Abort(messages.INIT_REQUIRES_REMOTE_PATH)
     except PreexistingDatastore, e:
         if e.committed:
-            ui.note(messages.INIT_EXISTS_COMMITTED)
+            ui.note(messages.INIT_EXISTS)
         else:
             raise util.Abort(messages.INIT_EXISTS_UNCOMMITTED)
 
@@ -264,6 +268,7 @@
         * Create a new Mercurial repository called "code-review" in the root
           of the current repository.  This name can be changed with the
           --local-path option.
+        
         * Create and 'hg add' a .hgreview file in the current repository. You
           will need to commit this file yourself with:
           hg commmit .hgreview -m 'Initialize code review data.'
--- a/review/messages.py	Sun Oct 11 11:38:15 2009 -0400
+++ b/review/messages.py	Sun Oct 11 17:28:23 2009 -0400
@@ -10,22 +10,30 @@
 initializing the code review data store and config
 """
 
-INIT_SUCCESS = """\
+INIT_SUCCESS_UNCOMMITTED = """\
 the review data has been initialized
-run "hg commit .hgreview -m'initialize code review'" to record it permanently
+run "hg commit .hgreview -m 'initialize code review'" to record it permanently
+"""
+
+INIT_SUCCESS_CLONED = """\
+the review data has been initialized
 """
 
 INIT_REQUIRES_REMOTE_PATH ="""\
 you must provide a remote path (see 'hg help review-init')!
 """
 
-INIT_EXISTS_COMMITTED = """\
-the review data was already initialized by someone else
+INIT_EXISTS = """\
+the review data has already been initialized!
 """
 
 INIT_EXISTS_UNCOMMITTED = """\
 the review data has already been initialized, but is not recorded!
-run "hg commit .hgreview -m'initialize code review'" to record it permanently
+run "hg commit .hgreview -m 'initialize code review'" to record it permanently
+"""
+
+INIT_UNSUPPORTED_RELATIVE_RPATH = """\
+relative remote paths are not supported (yet)!
 """
 
 COMMENT_REQUIRES_MESSAGE = """\
--- a/review/tests/test_init.py	Sun Oct 11 11:38:15 2009 -0400
+++ b/review/tests/test_init.py	Sun Oct 11 17:28:23 2009 -0400
@@ -11,8 +11,8 @@
 def test_init():
     sandbox = get_sandbox_repo()
     
-    output = review(init=True, remote_path='../sandbox-review')
-    assert messages.INIT_SUCCESS in output
+    output = review(init=True, remote_path='/sandbox-review')
+    assert messages.INIT_SUCCESS_UNCOMMITTED in output
     
     assert '.hgreview' not in sandbox['tip']
     assert os.path.exists('.hgreview')
@@ -22,15 +22,15 @@
     with open('.hgreview', 'r') as hgrf:
         hgr = hgrf.read()
         assert 'local = %s' % api.DEFAULT_DATASTORE_DIRNAME in hgr
-        assert 'remote = ../sandbox-review' in hgr
+        assert 'remote = /sandbox-review' in hgr
 
 
 @with_setup(setup_sandbox, teardown_sandbox)
 def test_init_with_local_path():
     sandbox = get_sandbox_repo()
     
-    output = review(init=True, local_path='NEW', remote_path='../sandbox-review')
-    assert messages.INIT_SUCCESS in output
+    output = review(init=True, local_path='NEW', remote_path='/sandbox-review')
+    assert messages.INIT_SUCCESS_UNCOMMITTED in output
     
     assert '.hgreview' not in sandbox['tip']
     assert os.path.exists('.hgreview')
@@ -39,8 +39,9 @@
     
     with open('.hgreview', 'r') as hgrf:
         hgr = hgrf.read()
+        print hgr
         assert 'local = NEW' in hgr
-        assert 'remote = ../sandbox-review' in hgr
+        assert 'remote = /sandbox-review' in hgr
 
 
 @with_setup(setup_sandbox, teardown_sandbox)
@@ -60,10 +61,10 @@
 def test_init_twice():
     sandbox = get_sandbox_repo()
     
-    review(init=True, remote_path='../sandbox-review')
+    review(init=True, remote_path='/sandbox-review')
     
     try:
-        review(init=True, remote_path='../sandbox-review')
+        review(init=True, remote_path='/sandbox-review')
     except hgutil.Abort, e:
         error = str(e)
         assert messages.INIT_EXISTS_UNCOMMITTED in error
--- a/review/tests/util.py	Sun Oct 11 11:38:15 2009 -0400
+++ b/review/tests/util.py	Sun Oct 11 17:28:23 2009 -0400
@@ -3,7 +3,7 @@
 import os, shutil
 import sample_data
 from mercurial import commands, hg, ui
-from .. import extension_ui
+from .. import api, extension_ui
 
 
 _ui = ui.ui()
@@ -57,7 +57,8 @@
     setup_sandbox()
     sandbox = get_sandbox_repo()
     
-    review(init=True, remote_path='../sandbox-review')
+    rpath = os.path.join(sandbox.root, api.DEFAULT_DATASTORE_DIRNAME)
+    review(init=True, remote_path=rpath)
     
     opts = { 'addremove': True, 'date': None, 'user': 'Review Tester',
              'logfile': None, 'message': "Add the code review.", }