# HG changeset patch # User Steve Losh # Date 1255296503 14400 # Node ID 65a39843de8da802a6544292cffb512940f16b89 # Parent 74aa03e429205f325164dbc5f3cf766e1c095559 Refactor datastore initialization. diff -r 74aa03e42920 -r 65a39843de8d review/api.py --- 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.""" diff -r 74aa03e42920 -r 65a39843de8d review/extension_ui.py --- 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.' diff -r 74aa03e42920 -r 65a39843de8d review/messages.py --- 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 = """\ diff -r 74aa03e42920 -r 65a39843de8d review/tests/test_init.py --- 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 diff -r 74aa03e42920 -r 65a39843de8d review/tests/util.py --- 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.", }