forked from mirrors/gecko-dev
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:
parent
c449642b76
commit
6a01b19a19
7 changed files with 195 additions and 44 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.update_vct(vcs, self._context.state_dir)
|
||||
else:
|
||||
bootstrap.configure_mercurial(hg, self._context.state_dir)
|
||||
if git:
|
||||
bootstrap.configure_git(vcs, self._context.state_dir)
|
||||
else:
|
||||
bootstrap.configure_mercurial(vcs, self._context.state_dir)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = """
|
||||
|
|
|
|||
Loading…
Reference in a new issue