Bug 1257478 - Turn mercurial-setup into vcs-setup and add git support. r=gps

MozReview-Commit-ID: AD6gLqFm8Nn

--HG--
extra : rebase_source : 0214cdc6f6acaaf0621e25f30cb0a2c81849063e
This commit is contained in:
Panos Astithas 2018-07-04 21:48:42 +03:00
parent c449642b76
commit 6a01b19a19
7 changed files with 195 additions and 44 deletions

View file

@ -234,7 +234,7 @@ def bootstrap(topsrcdir, mozilla_dir=None):
def should_skip_dispatch(context, handler):
# The user is performing a maintenance command.
if handler.name in ('bootstrap', 'doctor', 'mach-commands', 'mercurial-setup'):
if handler.name in ('bootstrap', 'doctor', 'mach-commands', 'vcs-setup'):
return True
# We are running in automation.

View file

@ -99,8 +99,8 @@ Source code can be obtained by running
hg clone https://hg.mozilla.org/mozilla-unified
Or, if you prefer Git, you should install git-cinnabar, and follow the
instruction here to clone from the Mercurial repository:
Or, if you prefer Git, by following the instruction here to clone from the
Mercurial repository:
https://github.com/glandium/git-cinnabar/wiki/Mozilla:-A-git-workflow-for-Gecko-development
@ -121,17 +121,26 @@ optimally configured?
Please enter your reply: '''
CLONE_MERCURIAL = '''
If you would like to clone the mozilla-unified Mercurial repository, please
enter the destination path below.
CONFIGURE_GIT = '''
Mozilla recommends using git-cinnabar to work with mozilla-central.
(If you prefer to use Git, leave this blank.)
Would you like to run a few configuration steps to ensure Git is
optimally configured?
1. Yes
2. No
Please enter your reply: '''
CLONE_VCS = '''
If you would like to clone the {} {} repository, please
enter the destination path below.
'''
CLONE_MERCURIAL_PROMPT = '''
Destination directory for Mercurial clone (leave empty to not clone): '''.lstrip()
CLONE_VCS_PROMPT = '''
Destination directory for {} clone (leave empty to not clone): '''.lstrip()
CLONE_MERCURIAL_NOT_EMPTY = '''
CLONE_VCS_NOT_EMPTY = '''
ERROR! Destination directory '{}' is not empty.
Would you like to clone to '{}'?
@ -142,11 +151,11 @@ Would you like to clone to '{}'?
Please enter your reply: '''.lstrip()
CLONE_MERCURIAL_NOT_EMPTY_FALLBACK_FAILED = '''
CLONE_VCS_NOT_EMPTY_FALLBACK_FAILED = '''
ERROR! Destination directory '{}' is not empty.
'''
CLONE_MERCURIAL_NOT_DIR = '''
CLONE_VCS_NOT_DIR = '''
ERROR! Destination '{}' exists but is not a directory.
'''
@ -166,6 +175,16 @@ DEBIAN_DISTROS = (
'"elementary"'
)
ADD_GIT_TOOLS_PATH = '''
To add git-cinnabar to the PATH, edit your shell initialization script, which
may be called ~/.bashrc or ~/.bash_profile or ~/.profile, and add the following
lines:
export PATH="{}:$PATH"
Then restart your shell.
'''
class Bootstrapper(object):
"""Main class that performs system bootstrap."""
@ -231,11 +250,16 @@ class Bootstrapper(object):
self.instance = cls(**args)
def input_clone_dest(self):
print(CLONE_MERCURIAL)
def input_clone_dest(self, with_hg=True):
repo_name = 'mozilla-unified'
vcs = 'Mercurial'
if not with_hg:
repo_name = 'gecko'
vcs = 'Git'
print(CLONE_VCS.format(repo_name, vcs))
while True:
dest = raw_input(CLONE_MERCURIAL_PROMPT)
dest = raw_input(CLONE_VCS_PROMPT.format(vcs))
dest = dest.strip()
if not dest:
return ''
@ -245,18 +269,18 @@ class Bootstrapper(object):
return dest
if not os.path.isdir(dest):
print(CLONE_MERCURIAL_NOT_DIR.format(dest))
print(CLONE_VCS_NOT_DIR.format(dest))
continue
if os.listdir(dest) == []:
return dest
newdest = os.path.join(dest, 'mozilla-unified')
newdest = os.path.join(dest, repo_name)
if os.path.exists(newdest):
print(CLONE_MERCURIAL_NOT_EMPTY_FALLBACK_FAILED.format(dest))
print(CLONE_VCS_NOT_EMPTY_FALLBACK_FAILED.format(dest))
continue
choice = self.instance.prompt_int(prompt=CLONE_MERCURIAL_NOT_EMPTY.format(dest,
choice = self.instance.prompt_int(prompt=CLONE_VCS_NOT_EMPTY.format(dest,
newdest), low=1, high=3)
if choice == 1:
return newdest
@ -360,7 +384,6 @@ class Bootstrapper(object):
(checkout_type, checkout_root) = r
# Possibly configure Mercurial, but not if the current checkout is Git.
# TODO offer to configure Git.
if hg_installed and state_dir_available and checkout_type != 'git':
configure_hg = False
if not self.instance.no_interactive:
@ -374,6 +397,21 @@ class Bootstrapper(object):
if configure_hg:
configure_mercurial(self.instance.which('hg'), state_dir)
# Offer to configure Git, if the current checkout is Git.
elif self.instance.which('git') and checkout_type == 'git':
should_configure_git = False
if not self.instance.no_interactive:
choice = self.instance.prompt_int(prompt=CONFIGURE_GIT,
low=1, high=2)
if choice == 1:
should_configure_git = True
else:
# Assuming default configuration setting applies to all VCS.
should_configure_git = self.hg_configure
if should_configure_git:
configure_git(self.instance.which('git'), state_dir)
# Offer to clone if we're not inside a clone.
have_clone = False
@ -382,7 +420,14 @@ class Bootstrapper(object):
elif hg_installed and not self.instance.no_interactive:
dest = self.input_clone_dest()
if dest:
have_clone = clone_firefox(self.instance.which('hg'), dest)
have_clone = hg_clone_firefox(self.instance.which('hg'), dest)
checkout_root = dest
elif self.instance.which('git') and checkout_type == 'git':
dest = self.input_clone_dest(False)
if dest:
git = self.instance.which('git')
watchman = self.instance.which('watchman')
have_clone = git_clone_firefox(git, dest, watchman)
checkout_root = dest
if not have_clone:
@ -470,7 +515,7 @@ def update_mercurial_repo(hg, url, dest, revision):
print('=' * 80)
def clone_firefox(hg, dest):
def hg_clone_firefox(hg, dest):
"""Clone the Firefox repository to a specified destination."""
print('Cloning Firefox Mercurial repository to %s' % dest)
@ -562,3 +607,90 @@ def current_firefox_checkout(check_output, env, hg=None):
break
return (None, None)
def update_git_tools(git, root_state_dir):
"""Ensure git-cinnabar is up to date."""
cinnabar_dir = os.path.join(root_state_dir, 'git-cinnabar')
# Ensure the latest revision of git-cinnabar is present.
update_git_repo(git, 'https://github.com/glandium/git-cinnabar.git',
cinnabar_dir)
# Perform a download of cinnabar.
download_args = [git, 'cinnabar', 'download']
try:
subprocess.check_call(download_args, cwd=cinnabar_dir)
except subprocess.CalledProcessError as e:
print(e)
return cinnabar_dir
def update_git_repo(git, url, dest):
"""Perform a clone/pull + update of a Git repository."""
pull_args = [git]
if os.path.exists(dest):
pull_args.extend(['pull'])
cwd = dest
else:
pull_args.extend(['clone', '--no-checkout', url, dest])
cwd = '/'
update_args = [git, 'checkout']
print('=' * 80)
print('Ensuring %s is up to date at %s' % (url, dest))
try:
subprocess.check_call(pull_args, cwd=cwd)
subprocess.check_call(update_args, cwd=dest)
finally:
print('=' * 80)
def configure_git(git, root_state_dir):
"""Run the Git configuration steps."""
cinnabar_dir = update_git_tools(git, root_state_dir)
print(ADD_GIT_TOOLS_PATH.format(cinnabar_dir))
def git_clone_firefox(git, dest, watchman=None):
"""Clone the Firefox repository to a specified destination."""
print('Cloning Firefox repository to %s' % dest)
try:
# Configure git per the git-cinnabar requirements.
subprocess.check_call([git, 'clone', '-b', 'bookmarks/central',
'hg::https://hg.mozilla.org/mozilla-unified', dest])
subprocess.check_call([git, 'remote', 'add', 'inbound',
'hg::ssh://hg.mozilla.org/integration/mozilla-inbound'],
cwd=dest)
subprocess.check_call([git, 'config', 'remote.inbound.skipDefaultUpdate',
'true'], cwd=dest)
subprocess.check_call([git, 'config', 'remote.inbound.push',
'+HEAD:refs/heads/branches/default/tip'], cwd=dest)
subprocess.check_call([git, 'config', 'fetch.prune', 'true'], cwd=dest)
subprocess.check_call([git, 'config', 'pull.ff', 'only'], cwd=dest)
watchman_sample = os.path.join(dest, '.git/hooks/fsmonitor-watchman.sample')
# Older versions of git didn't include fsmonitor-watchman.sample.
if watchman and watchman_sample:
print('Configuring watchman')
watchman_config = os.path.join(dest, '.git/hooks/query-watchman')
if not os.path.exists(watchman_config):
print('Copying %s to %s' % (watchman_sample, watchman_config))
copy_args = ['cp', '.git/hooks/fsmonitor-watchman.sample',
'.git/hooks/query-watchman']
subprocess.check_call(copy_args, cwd=dest)
config_args = [git, 'config', 'core.fsmonitor', '.git/hooks/query-watchman']
subprocess.check_call(config_args, cwd=dest)
except Exception as e:
print(e)
return False
print('Firefox source code available at %s' % dest)
return True

View file

@ -43,37 +43,53 @@ class VersionControlCommands(object):
def __init__(self, context):
self._context = context
@Command('mercurial-setup', category='devenv',
description='Help configure Mercurial for optimal development.')
@Command('vcs-setup', category='devenv',
description='Help configure a VCS for optimal development.')
@CommandArgument('-u', '--update-only', action='store_true',
help='Only update recommended extensions, don\'t run the wizard.')
def mercurial_setup(self, update_only=False):
"""Ensure Mercurial is optimally configured.
@CommandArgument('-g', '--git', action='store_true',
help='Use Git instead of Mercurial.')
def vcs_setup(self, update_only=False, git=False):
"""Ensure a Version Control System (Mercurial or Git) is optimally
configured.
This command will inspect your Mercurial configuration and
This command will inspect your VCS configuration and
guide you through an interactive wizard helping you configure
Mercurial for optimal use on Mozilla projects.
VCS for optimal use on Mozilla projects.
User choice is respected: no changes are made without explicit
confirmation from you.
If "--update-only" is used, the interactive wizard is disabled
and this command only ensures that remote repositories providing
Mercurial extensions are up to date.
VCS extensions are up to date.
If "--git" is used, then Git is selected as the VCS instead of Mercurial,
which is the default.
"""
import which
import mozboot.bootstrap as bootstrap
vcs = 'hg'
if git:
vcs = 'git'
# "hg" is an executable script with a shebang, which will be found
# be which.which. We need to pass a win32 executable to the function
# by which.which. We need to pass a win32 executable to the function
# because we spawn a process
# from it.
if sys.platform in ('win32', 'msys'):
hg = which.which('hg.exe')
vcs = which.which(vcs + '.exe')
else:
hg = which.which('hg')
vcs = which.which(vcs)
if update_only:
bootstrap.update_vct(hg, self._context.state_dir)
if git:
bootstrap.update_git_tools(vcs, self._context.state_dir)
else:
bootstrap.configure_mercurial(hg, self._context.state_dir)
bootstrap.update_vct(vcs, self._context.state_dir)
else:
if git:
bootstrap.configure_git(vcs, self._context.state_dir)
else:
bootstrap.configure_mercurial(vcs, self._context.state_dir)

View file

@ -96,7 +96,7 @@ Getting the code, running tests
just calls code in runtests.py).
* Configure Mercurial with helpful extensions for Mozilla
development by running `./mach mercurial-setup`.
development by running `./mach vcs-setup`.
* It should install extensions like firefox-trees and set
you up to be able to use MozReview, our code-review tool.

View file

@ -24,7 +24,7 @@ The recommended way to push to try is via the ``mach try`` command. This require
.. code-block:: shell
$ mach mercurial-setup
$ mach vcs-setup
You should also enable the ``firefoxtree`` extension which will provide a handy ``try`` path alias.
You can also create this alias manually by adding
@ -39,8 +39,12 @@ This is only necessary if not using ``firefoxtree``.
Configuring Try with Git Cinnabar
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The recommended way to use try with git is with `git cinnabar`_. You can follow `this tutorial`_ for
a workflow which includes setting up the ability to push to try.
The recommended way to use try with git is with `git cinnabar`, which can be
installed by running:
.. code-block:: shell
$ mach vcs-setup --git
Configuring Try with Vanilla Git

View file

@ -212,8 +212,8 @@ class TrySelect(MachCommandBase):
the AUTOTRY_PLATFORM_HINT environment variable, if set.
The command requires either its own mercurial extension ("push-to-try",
installable from mach mercurial-setup) or a git repo using git-cinnabar
(available at https://github.com/glandium/git-cinnabar).
installable from mach vcs-setup) or a git repo using git-cinnabar
(installable from mach vcs-setup --git).
"""
from tryselect.selectors.syntax import AutoTry

View file

@ -17,10 +17,9 @@ GIT_CINNABAR_NOT_FOUND = """
Could not detect `git-cinnabar`.
The `mach try` command requires git-cinnabar to be installed when
pushing from git. For more information and installation instruction,
please see:
pushing from git. Please install it by running:
https://github.com/glandium/git-cinnabar
$ ./mach vcs-setup --git
""".lstrip()
HG_PUSH_TO_TRY_NOT_FOUND = """
@ -29,7 +28,7 @@ Could not detect `push-to-try`.
The `mach try` command requires the push-to-try extension enabled
when pushing from hg. Please install it by running:
$ ./mach mercurial-setup
$ ./mach vcs-setup
""".lstrip()
VCS_NOT_FOUND = """