--- a/python/mozboot/mozboot/bootstrap.py
+++ b/python/mozboot/mozboot/bootstrap.py
@@ -77,20 +77,23 @@ Would you like to create this directory?
1. Yes
2. No
Your choice:
'''
FINISHED = '''
-Your system should be ready to build %s! If you have not already,
-obtain a copy of the source code by running:
+Your system should be ready to build %s!
+'''
- hg clone https://hg.mozilla.org/mozilla-central
+SOURCE_ADVERTISE = '''
+Source code can be obtained by running
+
+ hg clone https://hg.mozilla.org/firefox
Or, if you prefer Git, you should install git-cinnabar, and follow the
instruction here to clone from the Mercurial repository:
https://github.com/glandium/git-cinnabar/wiki/Mozilla:-A-git-workflow-for-Gecko-development
Or, if you really prefer vanilla flavor Git:
@@ -104,16 +107,25 @@ experience with it.
Would you like to run a configuration wizard to ensure Mercurial is
optimally configured?
1. Yes
2. No
Please enter your reply: '''.lstrip()
+CLONE_MERCURIAL = '''
+If you would like to clone the canonical Mercurial repository, please
+enter the destination path below.
+
+(If you prefer to use Git, leave this blank.)
+
+Destination directory for Mercurial clone (leave empty to not clone): '''.lstrip()
+
+
DEBIAN_DISTROS = (
'Debian',
'debian',
'Ubuntu',
# Most Linux Mint editions are based on Ubuntu. One is based on Debian.
# The difference is reported in dist_id from platform.linux_distribution.
# But it doesn't matter since we share a bootstrapper between Debian and
# Ubuntu.
@@ -238,16 +250,33 @@ class Bootstrapper(object):
if choice == 1:
configure_hg = True
else:
configure_hg = self.hg_configure
if configure_hg:
configure_mercurial(self.instance.which('hg'), state_dir)
+ # Offer to clone if we're not inside a clone.
+ checkout_type = current_vcs()
+ have_clone = False
+
+ if checkout_type:
+ have_clone = True
+ elif hg_installed and not self.instance.no_interactive:
+ dest = raw_input(CLONE_MERCURIAL)
+ dest = dest.strip()
+ if dest:
+ dest = os.path.expanduser(dest)
+ clone_firefox(self.instance.which('hg'), dest)
+ have_clone = True
+
+ if not have_clone:
+ print(SOURCE_ADVERTISE)
+
print(self.finished % name)
# Like 'suggest_browser_mozconfig' or 'suggest_mobile_android_mozconfig'.
getattr(self.instance, 'suggest_%s_mozconfig' % application)()
def update_vct(hg, root_state_dir):
"""Ensure version-control-tools in the state directory is up to date."""
@@ -303,8 +332,60 @@ def update_mercurial_repo(hg, url, dest,
print('=' * 80)
print('Ensuring %s is up to date at %s' % (url, dest))
try:
subprocess.check_call(args, cwd=cwd)
subprocess.check_call([hg, 'update', '-r', revision], cwd=dest)
finally:
print('=' * 80)
+
+
+def clone_firefox(hg, dest):
+ """Clone the Firefox repository to a specified destination."""
+ print('Cloning Firefox Mercurial repository to %s' % dest)
+
+ try:
+ subprocess.check_call([hg, 'config', 'ui.clonebundleprefers'])
+ have_bundle_prefers = True
+ except subprocess.CalledProcessError:
+ have_bundle_prefers = False
+
+ args = [hg]
+
+ # Prefer an uncompressed clone because the delta chains on the server
+ # are optimal and will be preserved on the client, unlike with a gzip
+ # clone.
+ if not have_bundle_prefers:
+ args.extend(['--config', 'ui.clonebundleprefers=VERSION=packed1'])
+
+ args.extend([
+ 'clone',
+ '--noupdate',
+ 'https://hg.mozilla.org/firefox',
+ dest,
+ ])
+
+ subprocess.check_call(args)
+ print('updating to "central" (main head of Firefox development)')
+ subprocess.check_call([hg, 'update', '-r', 'central'], cwd=dest)
+ print('')
+ print('Firefox source code available at %s' % dest)
+
+def current_vcs():
+ """Determine the type of the version control tool for the current directory.
+
+ Returns one of None, ``git``, or ``hg``.
+ """
+ path = os.getcwd()
+ while path:
+ hg = os.path.join(path, '.hg')
+ git = os.path.join(path, '.git')
+ if os.path.exists(hg):
+ return 'hg'
+ elif os.path.exists(git):
+ return 'git'
+
+ path, child = os.path.split(path)
+ if child == '':
+ return None
+
+ return None