def update_all(self): hg = get_hg_path() repo_existed = os.path.isdir(self.vcs_tools_dir) self.update_mercurial_repo( hg, 'https://hg.mozilla.org/hgcustom/version-control-tools', self.vcs_tools_dir, 'default', 'Ensuring version-control-tools is up to date...') if repo_existed: print(FINISHED) return 0
def update_all(self): hg = get_hg_path() repo_existed = os.path.isdir(self.vcs_tools_dir) self.update_mercurial_repo( hg, 'https://hg.mozilla.org/hgcustom/version-control-tools', self.vcs_tools_dir, 'default', 'Ensuring version-control-tools is up to date...') self.update_mercurial_repo( hg, 'https://bitbucket.org/facebook/hgwatchman', self.hgwatchman_dir, '5ca0f920df7ec8a93d322f06d554f778184cdcd1', 'Ensuring hgwatchman is up to date...') if repo_existed: print(FINISHED) return 0
def update_all(self): hg = get_hg_path() repo_existed = os.path.isdir(self.vcs_tools_dir) self.update_mercurial_repo( hg, "https://hg.mozilla.org/hgcustom/version-control-tools", self.vcs_tools_dir, "default", "Ensuring version-control-tools is up to date...", ) self.update_mercurial_repo( hg, "https://bitbucket.org/facebook/hgwatchman", self.hgwatchman_dir, "5ca0f920df7ec8a93d322f06d554f778184cdcd1", "Ensuring hgwatchman is up to date...", ) if repo_existed: print(FINISHED) return 0
def run(self, config_paths): try: os.makedirs(self.ext_dir) except OSError as e: if e.errno != errno.EEXIST: raise hg = get_hg_path() config_path = config_file(config_paths) try: c = MercurialConfig(config_path) except ConfigObjError as e: print('Error importing existing Mercurial config: %s\n' % config_path) for error in e.errors: print(error.message) return 1 except ParseException as e: print('Error importing existing Mercurial config: %s\n' % config_path) print('Line %d: %s' % (e.line, e.message)) return 1 self.updater.update_all() 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('') name = self._prompt('What is your name?') email = self._prompt('What is your email address?') c.set_username(name, email) print('Updated your username.') print('') if not c.have_recommended_diff_settings(): print(BAD_DIFF_SETTINGS) print('') if self._prompt_yn('Would you like me to fix this for you'): c.ensure_recommended_diff_settings() print('Fixed patch settings.') print('') # Progress is built into core and enabled by default in Mercurial 3.5. if hg_version < LooseVersion('3.5'): self.prompt_native_extension(c, 'progress', 'Would you like to see progress bars during Mercurial operations') self.prompt_native_extension(c, 'color', 'Would you like Mercurial to colorize output to your terminal') self.prompt_native_extension(c, 'rebase', '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, 'histedit', 'Would you like to enable the histedit extension to allow history ' 'rewriting via the "histedit" command (similar to ' '`git rebase -i`)') # hgwatchman is provided by MozillaBuild and we don't yet support # Linux/BSD. # Note that the hgwatchman project has been renamed to fsmonitor and has # been moved into Mercurial core, as of version 3.8. So, if your Mercurial # version is modern enough (>=3.8), you could set fsmonitor in hgrc file # directly. if ('hgwatchman' not in c.extensions and sys.platform.startswith('darwin') and hg_version >= HGWATCHMAN_MINIMUM_VERSION and self._prompt_yn(FSMONITOR_INFO)): if (hg_version >= FSMONITOR_MINIMUM_VERSION): c.activate_extension('fsmonitor') else: # Unlike other extensions, we need to run an installer # to compile a Python C extension. try: subprocess.check_output( ['make', 'local'], cwd=self.updater.hgwatchman_dir, stderr=subprocess.STDOUT) ext_path = os.path.join(self.updater.hgwatchman_dir, 'hgwatchman') if self.can_use_extension(c, 'hgwatchman', ext_path): c.activate_extension('hgwatchman', ext_path) except subprocess.CalledProcessError as e: print('Error compiling hgwatchman; will not install hgwatchman') print(e.output) 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) self.prompt_external_extension(c, 'bzexport', BZEXPORT_INFO) if hg_version >= BZPOST_MINIMUM_VERSION: self.prompt_external_extension(c, 'bzpost', BZPOST_INFO) if hg_version >= FIREFOXTREE_MINIMUM_VERSION: self.prompt_external_extension(c, 'firefoxtree', FIREFOXTREE_INFO) # Functionality from bundleclone is experimental in Mercurial 3.6. # There was a bug in 3.6, so look for 3.6.1. if hg_version >= LooseVersion('3.6.1'): if not c.have_clonebundles() and self._prompt_yn(CLONEBUNDLES_INFO): c.activate_clonebundles() print('Enabled the clonebundles feature.\n') elif hg_version >= BUNDLECLONE_MINIMUM_VERSION: self.prompt_external_extension(c, 'bundleclone', BUNDLECLONE_INFO) if hg_version >= PUSHTOTRY_MINIMUM_VERSION: self.prompt_external_extension(c, 'push-to-try', PUSHTOTRY_INFO) if not c.have_wip(): if self._prompt_yn(WIP_INFO): c.install_wip_alias() if 'reviewboard' in c.extensions or 'bzpost' in c.extensions: bzuser, bzpass, bzuserid, bzcookie, bzapikey = c.get_bugzilla_credentials() if not bzuser or not bzapikey: print(MISSING_BUGZILLA_CREDENTIALS) if not bzuser: bzuser = self._prompt('What is your Bugzilla email address? (optional)', allow_empty=True) if bzuser and not bzapikey: print(BUGZILLA_API_KEY_INSTRUCTIONS) bzapikey = self._prompt('Please enter a Bugzilla API Key: (optional)', allow_empty=True) if bzuser or bzapikey: c.set_bugzilla_credentials(bzuser, bzapikey) if bzpass or bzuserid or bzcookie: print(LEGACY_BUGZILLA_CREDENTIALS_DETECTED) # Clear legacy credentials automatically if an API Key is # found as it supercedes all other credentials. if bzapikey: print('The legacy credentials have been removed.\n') c.clear_legacy_bugzilla_credentials() elif self._prompt_yn('Remove legacy credentials'): c.clear_legacy_bugzilla_credentials() # Look for and clean up old extensions. for ext in {'bzexport', 'qimportbz', 'mqext'}: path = os.path.join(self.ext_dir, ext) if os.path.exists(path): if self._prompt_yn('Would you like to remove the old and no ' 'longer referenced repository at %s' % path): print('Cleaning up old repository: %s' % path) shutil.rmtree(path) # Python + Mercurial didn't have terrific TLS handling until Python # 2.7.9 and Mercurial 3.4. For this reason, it was recommended to pin # certificates in Mercurial config files. In modern versions of # Mercurial, the system CA store is used and old, legacy TLS protocols # are disabled. The default connection/security setting should # be sufficient and pinning certificates is no longer needed. have_modern_ssl = hasattr(ssl, 'SSLContext') if hg_version < LooseVersion('3.4') or not have_modern_ssl: c.add_mozilla_host_fingerprints() # We always update fingerprints if they are present. We /could/ offer to # remove fingerprints if running modern Python and Mercurial. But that # just adds more UI complexity and isn't worth it. c.update_mozilla_host_fingerprints() # References to multiple version-control-tools checkouts can confuse # version-control-tools, since various Mercurial extensions resolve # dependencies via __file__ and repos could reference another copy. seen_vct = set() for k, v in c.config.get('extensions', {}).items(): if 'version-control-tools' not in v: continue i = v.index('version-control-tools') vct = v[0:i + len('version-control-tools')] seen_vct.add(os.path.realpath(os.path.expanduser(vct))) if len(seen_vct) > 1: print(MULTIPLE_VCT % c.config_path) # At this point the config should be finalized. b = StringIO() c.write(b) new_lines = [line.rstrip() for line in b.getvalue().splitlines()] old_lines = [] config_path = c.config_path if os.path.exists(config_path): with open(config_path, 'rt') as fh: old_lines = [line.rstrip() for line in fh.readlines()] diff = list(difflib.unified_diff(old_lines, new_lines, 'hgrc.old', 'hgrc.new')) if len(diff): print('Your Mercurial config file needs updating. I can do this ' 'for you if you like!') if self._prompt_yn('Would you like to see a diff of the changes ' 'first'): for line in diff: print(line) print('') if self._prompt_yn('Would you like me to update your hgrc file'): with open(config_path, 'wt') as fh: c.write(fh) print('Wrote changes to %s.' % config_path) else: print('hgrc changes not written to file. I would have ' 'written the following:\n') c.write(sys.stdout) return 1 if sys.platform != 'win32': # Config file may contain sensitive content, such as passwords. # Prompt to remove global permissions. mode = os.stat(config_path).st_mode if mode & (stat.S_IRWXG | stat.S_IRWXO): print(FILE_PERMISSIONS_WARNING) if self._prompt_yn('Remove permissions for others to ' 'read your hgrc file'): # We don't care about sticky and set UID bits because # this is a regular file. mode = mode & stat.S_IRWXU print('Changing permissions of %s' % config_path) os.chmod(config_path, mode) print(FINISHED) return 0
def run(self, config_paths): try: os.makedirs(self.ext_dir) except OSError as e: if e.errno != errno.EEXIST: raise hg = get_hg_path() config_path = config_file(config_paths) try: c = MercurialConfig(config_path) except ConfigObjError as e: print("Error importing existing Mercurial config: %s\n" % config_path) for error in e.errors: print(error.message) return 1 except ParseException as e: print("Error importing existing Mercurial config: %s\n" % config_path) print("Line %d: %s" % (e.line, e.message)) return 1 self.updater.update_all() 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("") name = self._prompt("What is your name?") email = self._prompt("What is your email address?") c.set_username(name, email) print("Updated your username.") print("") if not c.have_recommended_diff_settings(): print(BAD_DIFF_SETTINGS) print("") if self._prompt_yn("Would you like me to fix this for you"): c.ensure_recommended_diff_settings() print("Fixed patch settings.") print("") # Progress is built into core and enabled by default in Mercurial 3.5. if hg_version < LooseVersion("3.5"): self.prompt_native_extension( c, "progress", "Would you like to see progress bars during Mercurial operations" ) self.prompt_native_extension(c, "color", "Would you like Mercurial to colorize output to your terminal") self.prompt_native_extension( c, "rebase", "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, "histedit", "Would you like to enable the histedit extension to allow history " 'rewriting via the "histedit" command (similar to ' "`git rebase -i`)", ) # hgwatchman is provided by MozillaBuild and we don't yet support # Linux/BSD. if ( "hgwatchman" not in c.extensions and sys.platform.startswith("darwin") and hg_version >= HGWATCHMAN_MINIMUM_VERSION and self._prompt_yn(HGWATCHMAN_INFO) ): # Unlike other extensions, we need to run an installer # to compile a Python C extension. try: subprocess.check_output(["make", "local"], cwd=self.updater.hgwatchman_dir, stderr=subprocess.STDOUT) ext_path = os.path.join(self.updater.hgwatchman_dir, "hgwatchman") if self.can_use_extension(c, "hgwatchman", ext_path): c.activate_extension("hgwatchman", ext_path) except subprocess.CalledProcessError as e: print("Error compiling hgwatchman; will not install hgwatchman") print(e.output) self.prompt_native_extension(c, "mq", MQ_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, ) self.prompt_external_extension(c, "bzexport", BZEXPORT_INFO) if hg_version >= BZPOST_MINIMUM_VERSION: self.prompt_external_extension(c, "bzpost", BZPOST_INFO) if hg_version >= FIREFOXTREE_MINIMUM_VERSION: self.prompt_external_extension(c, "firefoxtree", FIREFOXTREE_INFO) # Functionality from bundleclone is experimental in Mercurial 3.6. # There was a bug in 3.6, so look for 3.6.1. if hg_version >= LooseVersion("3.6.1"): if not c.have_clonebundles() and self._prompt_yn(CLONEBUNDLES_INFO): c.activate_clonebundles() print("Enabled the clonebundles feature.\n") elif hg_version >= BUNDLECLONE_MINIMUM_VERSION: self.prompt_external_extension(c, "bundleclone", BUNDLECLONE_INFO) if hg_version >= PUSHTOTRY_MINIMUM_VERSION: self.prompt_external_extension(c, "push-to-try", PUSHTOTRY_INFO) if not c.have_wip(): if self._prompt_yn(WIP_INFO): c.install_wip_alias() if "mq" in c.extensions: self.prompt_external_extension(c, "mqext", MQEXT_INFO) if "mqext" in c.extensions and not c.have_mqext_autocommit_mq(): if self._prompt_yn( "Would you like to configure mqext to " "automatically commit changes as you modify patches" ): c.ensure_mqext_autocommit_mq() print("Configured mqext to auto-commit.\n") self.prompt_external_extension(c, "qimportbz", QIMPORTBZ_INFO) if not c.have_qnew_currentuser_default(): print(QNEWCURRENTUSER_INFO) if self._prompt_yn("Would you like qnew to set patch author by " "default"): c.ensure_qnew_currentuser_default() print("Configured qnew to set patch author by default.") print("") if "reviewboard" in c.extensions or "bzpost" in c.extensions: bzuser, bzpass, bzuserid, bzcookie, bzapikey = c.get_bugzilla_credentials() if not bzuser or not bzapikey: print(MISSING_BUGZILLA_CREDENTIALS) if not bzuser: bzuser = self._prompt("What is your Bugzilla email address? (optional)", allow_empty=True) if bzuser and not bzapikey: print(BUGZILLA_API_KEY_INSTRUCTIONS) bzapikey = self._prompt("Please enter a Bugzilla API Key: (optional)", allow_empty=True) if bzuser or bzapikey: c.set_bugzilla_credentials(bzuser, bzapikey) if bzpass or bzuserid or bzcookie: print(LEGACY_BUGZILLA_CREDENTIALS_DETECTED) # Clear legacy credentials automatically if an API Key is # found as it supercedes all other credentials. if bzapikey: print("The legacy credentials have been removed.\n") c.clear_legacy_bugzilla_credentials() elif self._prompt_yn("Remove legacy credentials"): c.clear_legacy_bugzilla_credentials() # Look for and clean up old extensions. for ext in {"bzexport", "qimportbz", "mqext"}: path = os.path.join(self.ext_dir, ext) if os.path.exists(path): if self._prompt_yn( "Would you like to remove the old and no " "longer referenced repository at %s" % path ): print("Cleaning up old repository: %s" % path) shutil.rmtree(path) # Python + Mercurial didn't have terrific TLS handling until Python # 2.7.9 and Mercurial 3.4. For this reason, it was recommended to pin # certificates in Mercurial config files. In modern versions of # Mercurial, the system CA store is used and old, legacy TLS protocols # are disabled. The default connection/security setting should # be sufficient and pinning certificates is no longer needed. have_modern_ssl = hasattr(ssl, "SSLContext") if hg_version < LooseVersion("3.4") or not have_modern_ssl: c.add_mozilla_host_fingerprints() # We always update fingerprints if they are present. We /could/ offer to # remove fingerprints if running modern Python and Mercurial. But that # just adds more UI complexity and isn't worth it. c.update_mozilla_host_fingerprints() # References to multiple version-control-tools checkouts can confuse # version-control-tools, since various Mercurial extensions resolve # dependencies via __file__ and repos could reference another copy. seen_vct = set() for k, v in c.config.get("extensions", {}).items(): if "version-control-tools" not in v: continue i = v.index("version-control-tools") vct = v[0 : i + len("version-control-tools")] seen_vct.add(os.path.realpath(os.path.expanduser(vct))) if len(seen_vct) > 1: print(MULTIPLE_VCT % c.config_path) # At this point the config should be finalized. b = StringIO() c.write(b) new_lines = [line.rstrip() for line in b.getvalue().splitlines()] old_lines = [] config_path = c.config_path if os.path.exists(config_path): with open(config_path, "rt") as fh: old_lines = [line.rstrip() for line in fh.readlines()] diff = list(difflib.unified_diff(old_lines, new_lines, "hgrc.old", "hgrc.new")) if len(diff): print("Your Mercurial config file needs updating. I can do this " "for you if you like!") if self._prompt_yn("Would you like to see a diff of the changes " "first"): for line in diff: print(line) print("") if self._prompt_yn("Would you like me to update your hgrc file"): with open(config_path, "wt") as fh: c.write(fh) print("Wrote changes to %s." % config_path) else: print("hgrc changes not written to file. I would have " "written the following:\n") c.write(sys.stdout) return 1 if sys.platform != "win32": # Config file may contain sensitive content, such as passwords. # Prompt to remove global permissions. mode = os.stat(config_path).st_mode if mode & (stat.S_IRWXG | stat.S_IRWXO): print(FILE_PERMISSIONS_WARNING) if self._prompt_yn("Remove permissions for others to " "read your hgrc file"): # We don't care about sticky and set UID bits because # this is a regular file. mode = mode & stat.S_IRWXU print("Changing permissions of %s" % config_path) os.chmod(config_path, mode) print(FINISHED) return 0
def run(self, config_paths): try: os.makedirs(self.ext_dir) except OSError as e: if e.errno != errno.EEXIST: raise hg = get_hg_path() config_path = config_file(config_paths) try: c = MercurialConfig(config_path) except ConfigObjError as e: print('Error importing existing Mercurial config: %s\n' % config_path) for error in e.errors: print(error.message) return 1 except ParseException as e: print('Error importing existing Mercurial config: %s\n' % config_path) print('Line %d: %s' % (e.line, e.message)) return 1 self.updater.update_all() 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('') name = self._prompt('What is your name?') email = self._prompt('What is your email address?') c.set_username(name, email) print('Updated your username.') print('') if not c.have_recommended_diff_settings(): print(BAD_DIFF_SETTINGS) print('') if self._prompt_yn('Would you like me to fix this for you'): c.ensure_recommended_diff_settings() print('Fixed patch settings.') print('') # Progress is built into core and enabled by default in Mercurial 3.5. if hg_version < LooseVersion('3.5'): self.prompt_native_extension(c, 'progress', 'Would you like to see progress bars during Mercurial operations') self.prompt_native_extension(c, 'color', 'Would you like Mercurial to colorize output to your terminal') self.prompt_native_extension(c, 'rebase', '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, '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) 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) self.prompt_external_extension(c, 'bzexport', BZEXPORT_INFO) if hg_version >= BZPOST_MINIMUM_VERSION: self.prompt_external_extension(c, 'bzpost', BZPOST_INFO) if hg_version >= FIREFOXTREE_MINIMUM_VERSION: self.prompt_external_extension(c, 'firefoxtree', FIREFOXTREE_INFO) if hg_version >= BUNDLECLONE_MINIMUM_VERSION: self.prompt_external_extension(c, 'bundleclone', BUNDLECLONE_INFO) if hg_version >= PUSHTOTRY_MINIMUM_VERSION: self.prompt_external_extension(c, 'push-to-try', PUSHTOTRY_INFO) if 'mq' in c.extensions: self.prompt_external_extension(c, 'mqext', MQEXT_INFO) if 'mqext' in c.extensions and not c.have_mqext_autocommit_mq(): if self._prompt_yn('Would you like to configure mqext to ' 'automatically commit changes as you modify patches'): c.ensure_mqext_autocommit_mq() print('Configured mqext to auto-commit.\n') self.prompt_external_extension(c, 'qimportbz', QIMPORTBZ_INFO) if not c.have_qnew_currentuser_default(): print(QNEWCURRENTUSER_INFO) if self._prompt_yn('Would you like qnew to set patch author by ' 'default'): c.ensure_qnew_currentuser_default() print('Configured qnew to set patch author by default.') print('') if 'reviewboard' in c.extensions or 'bzpost' in c.extensions: bzuser, bzpass, bzuserid, bzcookie, bzapikey = c.get_bugzilla_credentials() if not bzuser or not bzapikey: print(MISSING_BUGZILLA_CREDENTIALS) if not bzuser: bzuser = self._prompt('What is your Bugzilla email address? (optional)', allow_empty=True) if bzuser and not bzapikey: print(BUGZILLA_API_KEY_INSTRUCTIONS) bzapikey = self._prompt('Please enter a Bugzilla API Key: (optional)', allow_empty=True) if bzuser or bzapikey: c.set_bugzilla_credentials(bzuser, bzapikey) if bzpass or bzuserid or bzcookie: print(LEGACY_BUGZILLA_CREDENTIALS_DETECTED) # Clear legacy credentials automatically if an API Key is # found as it supercedes all other credentials. if bzapikey: print('The legacy credentials have been removed.\n') c.clear_legacy_bugzilla_credentials() elif self._prompt_yn('Remove legacy credentials'): c.clear_legacy_bugzilla_credentials() # Look for and clean up old extensions. for ext in {'bzexport', 'qimportbz', 'mqext'}: path = os.path.join(self.ext_dir, ext) if os.path.exists(path): if self._prompt_yn('Would you like to remove the old and no ' 'longer referenced repository at %s' % path): print('Cleaning up old repository: %s' % path) shutil.rmtree(path) c.add_mozilla_host_fingerprints() # References to multiple version-control-tools checkouts can confuse # version-control-tools, since various Mercurial extensions resolve # dependencies via __file__ and repos could reference another copy. seen_vct = set() for k, v in c.config.get('extensions', {}).items(): if 'version-control-tools' not in v: continue i = v.index('version-control-tools') vct = v[0:i + len('version-control-tools')] seen_vct.add(os.path.realpath(os.path.expanduser(vct))) if len(seen_vct) > 1: print(MULTIPLE_VCT % c.config_path) # At this point the config should be finalized. b = StringIO() c.write(b) new_lines = [line.rstrip() for line in b.getvalue().splitlines()] old_lines = [] config_path = c.config_path if os.path.exists(config_path): with open(config_path, 'rt') as fh: old_lines = [line.rstrip() for line in fh.readlines()] diff = list(difflib.unified_diff(old_lines, new_lines, 'hgrc.old', 'hgrc.new')) if len(diff): print('Your Mercurial config file needs updating. I can do this ' 'for you if you like!') if self._prompt_yn('Would you like to see a diff of the changes ' 'first'): for line in diff: print(line) print('') if self._prompt_yn('Would you like me to update your hgrc file'): with open(config_path, 'wt') as fh: c.write(fh) print('Wrote changes to %s.' % config_path) else: print('hgrc changes not written to file. I would have ' 'written the following:\n') c.write(sys.stdout) return 1 if sys.platform != 'win32': # Config file may contain sensitive content, such as passwords. # Prompt to remove global permissions. mode = os.stat(config_path).st_mode if mode & (stat.S_IRWXG | stat.S_IRWXO): print(FILE_PERMISSIONS_WARNING) if self._prompt_yn('Remove permissions for others to ' 'read your hgrc file'): # We don't care about sticky and set UID bits because # this is a regular file. mode = mode & stat.S_IRWXU print('Changing permissions of %s' % config_path) os.chmod(config_path, mode) print(FINISHED) return 0
def run(self, config_paths): try: os.makedirs(self.ext_dir) except OSError as e: if e.errno != errno.EEXIST: raise hg = get_hg_path() config_path = config_file(config_paths) try: c = MercurialConfig(config_path) except ConfigObjError as e: print('Error importing existing Mercurial config: %s\n' % config_path) for error in e.errors: print(error.message) return 1 except ParseException as e: print('Error importing existing Mercurial config: %s\n' % config_path) print('Line %d: %s' % (e.line, e.message)) return 1 self.updater.update_all() 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('') name = self._prompt('What is your name?') email = self._prompt('What is your email address?') c.set_username(name, email) print('Updated your username.') print('') if not c.have_recommended_diff_settings(): print(BAD_DIFF_SETTINGS) print('') if self._prompt_yn('Would you like me to fix this for you'): c.ensure_recommended_diff_settings() print('Fixed patch settings.') print('') # Progress is built into core and enabled by default in Mercurial 3.5. if hg_version < LooseVersion('3.5'): self.prompt_native_extension( c, 'progress', 'Would you like to see progress bars during Mercurial operations' ) self.prompt_native_extension( c, 'color', 'Would you like Mercurial to colorize output to your terminal') self.prompt_native_extension( c, 'rebase', '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, '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) 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) self.prompt_external_extension(c, 'bzexport', BZEXPORT_INFO) if hg_version >= BZPOST_MINIMUM_VERSION: self.prompt_external_extension(c, 'bzpost', BZPOST_INFO) if hg_version >= FIREFOXTREE_MINIMUM_VERSION: self.prompt_external_extension(c, 'firefoxtree', FIREFOXTREE_INFO) if hg_version >= BUNDLECLONE_MINIMUM_VERSION: self.prompt_external_extension(c, 'bundleclone', BUNDLECLONE_INFO) if hg_version >= PUSHTOTRY_MINIMUM_VERSION: self.prompt_external_extension(c, 'push-to-try', PUSHTOTRY_INFO) if 'mq' in c.extensions: self.prompt_external_extension(c, 'mqext', MQEXT_INFO) if 'mqext' in c.extensions and not c.have_mqext_autocommit_mq(): if self._prompt_yn( 'Would you like to configure mqext to ' 'automatically commit changes as you modify patches'): c.ensure_mqext_autocommit_mq() print('Configured mqext to auto-commit.\n') self.prompt_external_extension(c, 'qimportbz', QIMPORTBZ_INFO) if not c.have_qnew_currentuser_default(): print(QNEWCURRENTUSER_INFO) if self._prompt_yn( 'Would you like qnew to set patch author by ' 'default'): c.ensure_qnew_currentuser_default() print('Configured qnew to set patch author by default.') print('') if 'reviewboard' in c.extensions or 'bzpost' in c.extensions: bzuser, bzpass, bzuserid, bzcookie = c.get_bugzilla_credentials() if (not bzuser or not bzpass) and (not bzuserid or not bzcookie): print(MISSING_BUGZILLA_CREDENTIALS) # Don't prompt for username if cookie is set. if not bzuser and not bzuserid: bzuser = self._prompt( 'What is your Bugzilla email address? (optional)', allow_empty=True) if bzuser and not bzpass: bzpass = self._prompt( 'What is your Bugzilla password? (optional)', allow_empty=True) if bzuser or bzpass: c.set_bugzilla_credentials(bzuser, bzpass) # Look for and clean up old extensions. for ext in {'bzexport', 'qimportbz', 'mqext'}: path = os.path.join(self.ext_dir, ext) if os.path.exists(path): if self._prompt_yn('Would you like to remove the old and no ' 'longer referenced repository at %s' % path): print('Cleaning up old repository: %s' % path) shutil.rmtree(path) c.add_mozilla_host_fingerprints() # References to multiple version-control-tools checkouts can confuse # version-control-tools, since various Mercurial extensions resolve # dependencies via __file__ and repos could reference another copy. seen_vct = set() for k, v in c.config.get('extensions', {}).items(): if 'version-control-tools' not in v: continue i = v.index('version-control-tools') vct = v[0:i + len('version-control-tools')] seen_vct.add(os.path.realpath(os.path.expanduser(vct))) if len(seen_vct) > 1: print(MULTIPLE_VCT % c.config_path) # At this point the config should be finalized. b = StringIO() c.write(b) new_lines = [line.rstrip() for line in b.getvalue().splitlines()] old_lines = [] config_path = c.config_path if os.path.exists(config_path): with open(config_path, 'rt') as fh: old_lines = [line.rstrip() for line in fh.readlines()] diff = list( difflib.unified_diff(old_lines, new_lines, 'hgrc.old', 'hgrc.new')) if len(diff): print('Your Mercurial config file needs updating. I can do this ' 'for you if you like!') if self._prompt_yn('Would you like to see a diff of the changes ' 'first'): for line in diff: print(line) print('') if self._prompt_yn('Would you like me to update your hgrc file'): with open(config_path, 'wt') as fh: c.write(fh) print('Wrote changes to %s.' % config_path) else: print('hgrc changes not written to file. I would have ' 'written the following:\n') c.write(sys.stdout) return 1 # Config file may contain sensitive content, such as passwords. # Prompt to remove global permissions. mode = os.stat(config_path).st_mode if mode & (stat.S_IRWXG | stat.S_IRWXO): print(FILE_PERMISSIONS_WARNING) if self._prompt_yn('Remove permissions for others to read ' 'your hgrc file'): # We don't care about sticky and set UID bits because this is # a regular file. mode = mode & stat.S_IRWXU print('Changing permissions of %s' % config_path) os.chmod(config_path, mode) print(FINISHED) return 0