Skip to content

Commit

Permalink
Bug 1033656 - Add reviewboard to mach mercurial-setup; version checki…
Browse files Browse the repository at this point in the history
…ng; r=smacleod

We want to make it turnkey for people to use reviewboard. So, we add
reviewboard and related functionality to |mach mercurial-setup|.

Since the reviewboard extension only works in Mercurial 3.0 and newer,
we add some version detection for the Mercurial version. This should
have been done months ago. We now have it.

I also took the opportunity to inform |mach bootstrap| that Mercurial
2.x is no longer modern.

I also updated the messaging around mq to encourage fewer new users to
use it. You may find this controversial. People can always ignore the
message.

Finally, I also added a histedit prompt to the mix, since a lot of
people don't know about that and many find it useful.

I could have broken this into multiple patches. Meh.

--HG--
extra : rebase_source : d33f8abcabb6ad6511c2f9e202283d43613fafc4
extra : amend_source : 3a56bc4d49ee6200cbdd0e87b4f28489518fee79
  • Loading branch information
indygreg committed Jul 2, 2014
1 parent 737a51a commit c5c6819
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 5 deletions.
2 changes: 1 addition & 1 deletion python/mozboot/mozboot/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@


# Upgrade Mercurial older than this.
MODERN_MERCURIAL_VERSION = StrictVersion('2.5')
MODERN_MERCURIAL_VERSION = StrictVersion('3.0')

# Upgrade Python older than this.
MODERN_PYTHON_VERSION = StrictVersion('2.7.3')
Expand Down
24 changes: 24 additions & 0 deletions python/mozversioncontrol/mozversioncontrol/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this,
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import unicode_literals

import os
import re
import subprocess

from distutils.version import StrictVersion

def get_hg_version(hg):
"""Obtain the version of the Mercurial client."""

env = os.environ.copy()
env[b'HGPLAIN'] = b'1'

info = subprocess.check_output([hg, 'version'], env=env)
match = re.search('version ([^\+\)]+)', info)
if not match:
raise Exception('Unable to identify Mercurial version.')

return StrictVersion(match.group(1))
1 change: 0 additions & 1 deletion python/mozversioncontrol/mozversioncontrol/repoupdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import os
import subprocess


# The logic here is far from robust. Improvements are welcome.

def update_mercurial_repo(hg, repo, path, revision='default',
Expand Down
14 changes: 14 additions & 0 deletions tools/mercurial/hgsetup/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,17 @@ def ensure_qnew_currentuser_default(self):
d['qnew'] = '-U'
else:
d['qnew'] = '-U ' + d['qnew']

def get_bugzilla_credentials(self):
if 'bugzilla' not in self._c:
return None, None

b = self._c['bugzilla']
return b.get('username', None), b.get('password', None)

def set_bugzilla_credentials(self, username, password):
b = self._c.setdefault('bugzilla', {})
if username:
b['username'] = username
if password:
b['password'] = password
100 changes: 97 additions & 3 deletions tools/mercurial/hgsetup/wizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
import sys
import which

from distutils.version import StrictVersion

from configobj import ConfigObjError
from StringIO import StringIO

from mozversioncontrol import get_hg_version
from mozversioncontrol.repoupdate import (
update_mercurial_repo,
update_git_repo,
Expand All @@ -39,6 +42,14 @@
To begin, press the enter/return key.
'''.strip()

OLDEST_NON_LEGACY_VERSION = StrictVersion('3.0')
LEGACY_MERCURIAL = '''
You are running an out of date Mercurial client (%s).
For a faster and better Mercurial experience, we HIGHLY recommend you
upgrade.
'''.strip()

MISSING_USERNAME = '''
You don't have a username defined in your Mercurial config file. In order to
send patches to Mozilla, you'll need to attach a name and email address. If you
Expand All @@ -50,6 +61,16 @@
not configured to produce patches in that format.
'''.strip()

MQ_INFO = '''
The mq extension manages patches as separate files. It provides an
alternative to the recommended bookmark-based development workflow.
If you are a newcomer to Mercurial or are coming from Git, it is
recommended to avoid mq.
Would you like to activate the mq extension
'''.strip()

BZEXPORT_INFO = '''
If you plan on uploading patches to Mozilla, there is an extension called
bzexport that makes it easy to upload patches from the command line via the
Expand Down Expand Up @@ -87,6 +108,25 @@
should be up to date!
'''.strip()

REVIEWBOARD_MINIMUM_VERSION = StrictVersion('3.0.1')

REVIEWBOARD_INCOMPATIBLE = '''
Your Mercurial is too old to use the reviewboard extension, which is necessary
to conduct code review.
Please upgrade to Mercurial %s or newer to use this extension.
'''.strip()

MISSING_BUGZILLA_CREDENTIALS = '''
You do not have your Bugzilla credentials defined in your Mercurial config.
Various extensions make use of your Bugzilla credentials to interface with
Bugzilla to enrich your development experience.
Bugzilla credentials are optional. If you do not provide them, associated
functionality will not be enabled or you will be prompted for your
Bugzilla credentials when they are needed.
'''.lstrip()

class MercurialSetupWizard(object):
"""Command-line wizard to help users configure Mercurial."""
Expand Down Expand Up @@ -125,6 +165,24 @@ def run(self, config_paths):
print(INITIAL_MESSAGE)
raw_input()

hg_version = get_hg_version(hg)
if hg_version < OLDEST_NON_LEGACY_VERSION:
print(LEGACY_MERCURIAL % hg_version)
print('')

if os.name == 'nt':
print('Please upgrade to the latest MozillaBuild to upgrade '
'your Mercurial install.')
print('')
else:
print('Please run |mach bootstrap| to upgrade your Mercurial '
'install.')
print('')

if not self._prompt_yn('Would you like to continue using an old '
'Mercurial version'):
return 1

if not c.have_valid_username():
print(MISSING_USERNAME)
print('')
Expand Down Expand Up @@ -153,11 +211,27 @@ def run(self, config_paths):
'Would you like to enable the rebase extension to allow you to move'
' changesets around (which can help maintain a linear history)')

self.prompt_native_extension(c, 'mq',
'Would you like to activate the mq extension to manage patches')
self.prompt_native_extension(c, 'histedit',
'Would you like to enable the histedit extension to allow history '
'rewriting via the "histedit" command (similar to '
'`git rebase -i`)')

self.prompt_native_extension(c, 'mq', MQ_INFO)

self.prompt_external_extension(c, 'bzexport', BZEXPORT_INFO)

if 'reviewboard' not in c.extensions:
if hg_version < REVIEWBOARD_MINIMUM_VERSION:
print(REVIEWBOARD_INCOMPATIBLE % REVIEWBOARD_MINIMUM_VERSION)
else:
p = os.path.join(self.vcs_tools_dir, 'hgext', 'reviewboard',
'client.py')
self.prompt_external_extension(c, 'reviewboard',
'Would you like to enable the reviewboard extension so '
'you can easily initiate code reviews against Mozilla '
'projects',
path=p)

if 'mq' in c.extensions:
self.prompt_external_extension(c, 'mqext', MQEXT_INFO,
os.path.join(self.ext_dir, 'mqext'))
Expand Down Expand Up @@ -186,6 +260,23 @@ def run(self, config_paths):
print('Configured qnew to set patch author by default.')
print('')

if 'reviewboard' in c.extensions:
bzuser, bzpass = c.get_bugzilla_credentials()

if not bzuser or not bzpass:
print(MISSING_BUGZILLA_CREDENTIALS)

if not bzuser:
bzuser = self._prompt('What is your Bugzilla email address?',
allow_empty=True)

if bzuser and not bzpass:
bzpass = self._prompt('What is your Bugzilla password?',
allow_empty=True)

if bzuser or bzpass:
c.set_bugzilla_credentials(bzuser, bzpass)

if self.update_vcs_tools:
self.update_mercurial_repo(
hg,
Expand Down Expand Up @@ -281,7 +372,7 @@ def _update_repo(self, binary, url, dest, branch, msg, fn, *args, **kwargs):
print('=' * 80)
print('')

def _prompt(self, msg):
def _prompt(self, msg, allow_empty=False):
print(msg)

while True:
Expand All @@ -290,6 +381,9 @@ def _prompt(self, msg):
if response:
return response

if allow_empty:
return None

print('You must type something!')

def _prompt_yn(self, msg):
Expand Down

0 comments on commit c5c6819

Please sign in to comment.