2013-03-02 03:51:11 +04:00
# 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 print_function , unicode_literals
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
import errno
2016-01-29 21:06:36 +03:00
import json
2013-03-02 03:51:11 +04:00
import os
import platform
2016-02-09 18:09:17 +03:00
import random
2013-03-02 03:51:11 +04:00
import sys
2013-05-21 05:07:48 +04:00
import time
2016-01-29 21:06:36 +03:00
import uuid
2015-08-05 09:43:11 +03:00
import __builtin__
from types import ModuleType
2013-05-21 05:07:48 +04:00
STATE_DIR_FIRST_RUN = '''
mach and the build system store shared state in a common directory on the
filesystem . The following directory will be created :
{ userdir }
If you would like to use a different directory , hit CTRL + c and set the
MOZBUILD_STATE_PATH environment variable to the directory you would like to
use and re - run mach . For this change to take effect forever , you ' ll likely
want to export this environment variable from your shell ' s init scripts.
2016-02-24 04:29:38 +03:00
Press ENTER / RETURN to continue or CTRL + c to abort .
2013-05-21 05:07:48 +04:00
''' .lstrip()
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
NO_MERCURIAL_SETUP = '''
* * * MERCURIAL NOT CONFIGURED * * *
2015-08-19 03:04:57 +03:00
mach has detected that you have never run ` { mach } mercurial - setup ` .
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
Running this command will ensure your Mercurial version control tool is up
to date and optimally configured for a better , more productive experience
when working on Mozilla projects .
2015-08-19 03:04:57 +03:00
Please run ` { mach } mercurial - setup ` now .
2015-07-21 20:10:22 +03:00
2015-08-19 03:04:57 +03:00
Note : ` { mach } mercurial - setup ` does not make any changes without prompting
2015-07-21 20:10:22 +03:00
you first .
2016-02-06 19:02:40 +03:00
You can disable this check by setting NO_MERCURIAL_SETUP_CHECK = 1 in your
environment .
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
''' .strip()
MERCURIAL_SETUP_FATAL_INTERVAL = 31 * 24 * 60 * 60
2013-03-02 03:51:11 +04:00
# TODO Bug 794506 Integrate with the in-tree virtualenv configuration.
SEARCH_PATHS = [
' python/mach ' ,
' python/mozboot ' ,
' python/mozbuild ' ,
2013-07-30 03:58:40 +04:00
' python/mozversioncontrol ' ,
2013-03-02 03:51:11 +04:00
' python/blessings ' ,
2015-03-18 20:47:36 +03:00
' python/compare-locales ' ,
2013-07-18 23:55:41 +04:00
' python/configobj ' ,
2013-09-12 06:54:19 +04:00
' python/jsmin ' ,
2013-03-02 03:51:11 +04:00
' python/psutil ' ,
' python/which ' ,
2014-11-26 21:11:28 +03:00
' python/pystache ' ,
' python/pyyaml/lib ' ,
2015-05-29 21:01:25 +03:00
' python/requests ' ,
2015-09-04 18:59:34 +03:00
' python/slugid ' ,
2015-05-01 19:20:55 +03:00
' build ' ,
2013-03-08 21:42:34 +04:00
' config ' ,
2013-11-15 02:34:50 +04:00
' dom/bindings ' ,
' dom/bindings/parser ' ,
2016-02-10 20:48:25 +03:00
' dom/media/test/external ' ,
2014-06-18 04:29:57 +04:00
' layout/tools/reftest ' ,
2013-03-02 03:51:11 +04:00
' other-licenses/ply ' ,
' testing ' ,
2016-01-15 18:35:51 +03:00
' testing/firefox-ui/harness ' ,
' testing/firefox-ui/tests ' ,
' testing/luciddream ' ,
2015-02-11 00:55:33 +03:00
' testing/marionette/client ' ,
2015-05-27 20:00:09 +03:00
' testing/marionette/client/marionette/runner/mixins/browsermob-proxy-py ' ,
2015-02-23 17:45:50 +03:00
' testing/marionette/driver ' ,
2013-03-27 02:00:43 +04:00
' testing/mozbase/mozcrash ' ,
2014-07-02 15:51:00 +04:00
' testing/mozbase/mozdebug ' ,
2013-04-19 16:19:54 +04:00
' testing/mozbase/mozdevice ' ,
' testing/mozbase/mozfile ' ,
2016-02-10 13:04:50 +03:00
' testing/mozbase/mozhttpd ' ,
2015-10-08 16:10:03 +03:00
' testing/mozbase/mozinfo ' ,
' testing/mozbase/mozinstall ' ,
2015-07-03 08:04:22 +03:00
' testing/mozbase/mozleak ' ,
2013-03-27 02:00:43 +04:00
' testing/mozbase/mozlog ' ,
2013-04-19 16:19:54 +04:00
' testing/mozbase/moznetwork ' ,
2013-03-02 03:51:11 +04:00
' testing/mozbase/mozprocess ' ,
2013-04-19 16:19:54 +04:00
' testing/mozbase/mozprofile ' ,
' testing/mozbase/mozrunner ' ,
2013-08-20 21:42:25 +04:00
' testing/mozbase/mozsystemmonitor ' ,
2015-07-29 18:50:16 +03:00
' testing/mozbase/mozscreenshot ' ,
2013-10-10 23:37:45 +04:00
' testing/mozbase/moztest ' ,
2014-02-20 01:42:01 +04:00
' testing/mozbase/mozversion ' ,
2014-06-10 21:20:23 +04:00
' testing/mozbase/manifestparser ' ,
2016-01-15 18:35:51 +03:00
' testing/puppeteer/firefox ' ,
' testing/taskcluster ' ,
' testing/tools/autotry ' ,
' testing/web-platform ' ,
' testing/web-platform/harness ' ,
' testing/web-platform/tests/tools/wptserve ' ,
' testing/xpcshell ' ,
2013-07-30 03:57:28 +04:00
' xpcom/idl-parser ' ,
2013-03-02 03:51:11 +04:00
]
# Individual files providing mach commands.
MACH_MODULES = [
' addon-sdk/mach_commands.py ' ,
2013-12-19 05:36:08 +04:00
' build/valgrind/mach_commands.py ' ,
2013-11-15 02:34:50 +04:00
' dom/bindings/mach_commands.py ' ,
2016-02-10 20:48:25 +03:00
' dom/media/test/external/mach_commands.py ' ,
2013-03-02 03:51:11 +04:00
' layout/tools/reftest/mach_commands.py ' ,
2013-07-03 04:33:48 +04:00
' python/mach_commands.py ' ,
2013-03-04 22:18:48 +04:00
' python/mach/mach/commands/commandinfo.py ' ,
2015-03-18 20:47:36 +03:00
' python/compare-locales/mach_commands.py ' ,
2013-03-02 03:51:11 +04:00
' python/mozboot/mozboot/mach_commands.py ' ,
' python/mozbuild/mozbuild/mach_commands.py ' ,
2014-09-04 10:08:33 +04:00
' python/mozbuild/mozbuild/backend/mach_commands.py ' ,
2015-04-24 22:12:50 +03:00
' python/mozbuild/mozbuild/compilation/codecomplete.py ' ,
2013-03-02 03:51:11 +04:00
' python/mozbuild/mozbuild/frontend/mach_commands.py ' ,
2014-07-30 23:44:13 +04:00
' services/common/tests/mach_commands.py ' ,
2016-01-15 18:35:51 +03:00
' testing/firefox-ui/mach_commands.py ' ,
2015-04-09 18:46:00 +03:00
' testing/luciddream/mach_commands.py ' ,
2013-09-09 23:37:38 +04:00
' testing/mach_commands.py ' ,
2013-04-19 16:19:54 +04:00
' testing/marionette/mach_commands.py ' ,
2013-03-02 03:51:11 +04:00
' testing/mochitest/mach_commands.py ' ,
2015-12-07 15:28:40 +03:00
' testing/mozharness/mach_commands.py ' ,
2013-07-26 19:04:31 +04:00
' testing/talos/mach_commands.py ' ,
2016-01-15 18:35:51 +03:00
' testing/taskcluster/mach_commands.py ' ,
2014-09-04 15:52:43 +04:00
' testing/web-platform/mach_commands.py ' ,
2013-07-30 03:58:40 +04:00
' testing/xpcshell/mach_commands.py ' ,
2013-11-21 00:37:22 +04:00
' tools/docs/mach_commands.py ' ,
2013-07-30 03:58:40 +04:00
' tools/mercurial/mach_commands.py ' ,
2013-03-06 21:58:40 +04:00
' tools/mach_commands.py ' ,
2015-09-15 09:23:45 +03:00
' tools/power/mach_commands.py ' ,
2014-11-21 23:40:00 +03:00
' mobile/android/mach_commands.py ' ,
2013-03-02 03:51:11 +04:00
]
2013-05-09 04:56:30 +04:00
CATEGORIES = {
' build ' : {
' short ' : ' Build Commands ' ,
' long ' : ' Interact with the build system ' ,
' priority ' : 80 ,
} ,
' post-build ' : {
' short ' : ' Post-build Commands ' ,
' long ' : ' Common actions performed after completing a build. ' ,
' priority ' : 70 ,
} ,
' testing ' : {
' short ' : ' Testing ' ,
' long ' : ' Run tests. ' ,
' priority ' : 60 ,
} ,
2014-11-26 21:11:28 +03:00
' ci ' : {
' short ' : ' CI ' ,
' long ' : ' Taskcluster commands ' ,
' priority ' : 59
} ,
2013-05-09 04:56:30 +04:00
' devenv ' : {
' short ' : ' Development Environment ' ,
' long ' : ' Set up and configure your development environment. ' ,
' priority ' : 50 ,
} ,
' build-dev ' : {
' short ' : ' Low-level Build System Interaction ' ,
' long ' : ' Interact with specific parts of the build system. ' ,
' priority ' : 20 ,
} ,
' misc ' : {
' short ' : ' Potpourri ' ,
' long ' : ' Potent potables and assorted snacks. ' ,
' priority ' : 10 ,
2013-10-11 21:41:25 +04:00
} ,
' disabled ' : {
' short ' : ' Disabled ' ,
2014-08-11 20:31:24 +04:00
' long ' : ' The disabled commands are hidden by default. Use -v to display them. These commands are unavailable for your current context, run " mach <command> " to see why. ' ,
2013-10-11 21:41:25 +04:00
' priority ' : 0 ,
2013-05-09 04:56:30 +04:00
}
}
2016-02-09 18:09:17 +03:00
# Server to which to submit telemetry data
BUILD_TELEMETRY_SERVER = ' http://52.88.27.118/build-metrics-dev '
# We submit data to telemetry approximately every this many mach invocations
TELEMETRY_SUBMISSION_FREQUENCY = 10
2015-07-14 23:44:59 +03:00
def get_state_dir ( ) :
""" Obtain the path to a directory to hold state.
Returns a tuple of the path and a bool indicating whether the value came
from an environment variable .
"""
state_user_dir = os . path . expanduser ( ' ~/.mozbuild ' )
state_env_dir = os . environ . get ( ' MOZBUILD_STATE_PATH ' , None )
if state_env_dir :
return state_env_dir , True
else :
return state_user_dir , False
2013-03-08 01:19:27 +04:00
def bootstrap ( topsrcdir , mozilla_dir = None ) :
if mozilla_dir is None :
mozilla_dir = topsrcdir
2013-03-02 03:51:11 +04:00
# Ensure we are running Python 2.7+. We put this check here so we generate a
# user-friendly error message rather than a cryptic stack trace on module
# import.
if sys . version_info [ 0 ] != 2 or sys . version_info [ 1 ] < 7 :
print ( ' Python 2.7 or above (but not Python 3) is required to run mach. ' )
print ( ' You are running Python ' , platform . python_version ( ) )
sys . exit ( 1 )
2013-05-21 05:07:48 +04:00
# Global build system and mach state is stored in a central directory. By
# default, this is ~/.mozbuild. However, it can be defined via an
# environment variable. We detect first run (by lack of this directory
# existing) and notify the user that it will be created. The logic for
# creation is much simpler for the "advanced" environment variable use
# case. For default behavior, we educate users and give them an opportunity
# to react. We always exit after creating the directory because users don't
# like surprises.
2013-03-02 03:51:11 +04:00
try :
import mach . main
except ImportError :
2013-03-08 01:19:27 +04:00
sys . path [ 0 : 0 ] = [ os . path . join ( mozilla_dir , path ) for path in SEARCH_PATHS ]
2013-03-02 03:51:11 +04:00
import mach . main
2016-01-29 21:06:36 +03:00
def telemetry_handler ( context , data ) :
# We have not opted-in to telemetry
if ' BUILD_SYSTEM_TELEMETRY ' not in os . environ :
return
telemetry_dir = os . path . join ( get_state_dir ( ) [ 0 ] , ' telemetry ' )
try :
os . mkdir ( telemetry_dir )
except OSError as e :
if e . errno != errno . EEXIST :
raise
outgoing_dir = os . path . join ( telemetry_dir , ' outgoing ' )
try :
os . mkdir ( outgoing_dir )
except OSError as e :
if e . errno != errno . EEXIST :
raise
# Add common metadata to help submit sorted data later on.
data [ ' argv ' ] = sys . argv
2016-02-02 17:32:49 +03:00
data . setdefault ( ' system ' , { } ) . update ( dict (
architecture = list ( platform . architecture ( ) ) ,
machine = platform . machine ( ) ,
python_version = platform . python_version ( ) ,
release = platform . release ( ) ,
system = platform . system ( ) ,
version = platform . version ( ) ,
) )
if platform . system ( ) == ' Linux ' :
dist = list ( platform . linux_distribution ( ) )
data [ ' system ' ] [ ' linux_distribution ' ] = dist
elif platform . system ( ) == ' Windows ' :
win32_ver = list ( ( platform . win32_ver ( ) ) ) ,
data [ ' system ' ] [ ' win32_ver ' ] = win32_ver
elif platform . system ( ) == ' Darwin ' :
# mac version is a special Cupertino snowflake
r , v , m = platform . mac_ver ( )
data [ ' system ' ] [ ' mac_ver ' ] = [ r , list ( v ) , m ]
2016-01-29 21:06:36 +03:00
2016-02-09 18:09:17 +03:00
with open ( os . path . join ( outgoing_dir , str ( uuid . uuid4 ( ) ) + ' .json ' ) ,
' w ' ) as f :
2016-01-29 21:06:36 +03:00
json . dump ( data , f , sort_keys = True )
2016-02-09 18:09:17 +03:00
def should_skip_dispatch ( context , handler ) :
# The user is performing a maintenance command.
if handler . name in ( ' bootstrap ' , ' doctor ' , ' mach-commands ' , ' mercurial-setup ' ) :
return True
# We are running in automation.
if ' MOZ_AUTOMATION ' in os . environ or ' TASK_ID ' in os . environ :
return True
# The environment is likely a machine invocation.
if sys . stdin . closed or not sys . stdin . isatty ( ) :
return True
return False
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
def pre_dispatch_handler ( context , handler , args ) :
""" Perform global checks before command dispatch.
Currently , our goal is to ensure developers periodically run
` mach mercurial - setup ` ( when applicable ) to ensure their Mercurial
tools are up to date .
"""
# Don't do anything when...
2016-02-09 18:09:17 +03:00
if should_skip_dispatch ( context , handler ) :
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
return
2016-02-06 19:02:40 +03:00
# User has disabled first run check.
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
if ' I_PREFER_A_SUBOPTIMAL_MERCURIAL_EXPERIENCE ' in os . environ :
return
2016-02-06 19:02:40 +03:00
if ' NO_MERCURIAL_SETUP_CHECK ' in os . environ :
return
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
# Mercurial isn't managing this source checkout.
if not os . path . exists ( os . path . join ( topsrcdir , ' .hg ' ) ) :
return
state_dir = get_state_dir ( ) [ 0 ]
last_check_path = os . path . join ( state_dir , ' mercurial ' ,
' setup.lastcheck ' )
mtime = None
try :
mtime = os . path . getmtime ( last_check_path )
except OSError as e :
if e . errno != errno . ENOENT :
raise
# No last run file means mercurial-setup has never completed.
if mtime is None :
2015-08-19 03:04:57 +03:00
print ( NO_MERCURIAL_SETUP . format ( mach = sys . argv [ 0 ] ) , file = sys . stderr )
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
sys . exit ( 2 )
2016-02-09 18:09:17 +03:00
def post_dispatch_handler ( context , handler , args ) :
""" Perform global operations after command dispatch.
For now , we will use this to handle build system telemetry .
"""
# Don't do anything when...
if should_skip_dispatch ( context , handler ) :
return
# We have not opted-in to telemetry
if ' BUILD_SYSTEM_TELEMETRY ' not in os . environ :
return
# Every n-th operation
if random . randint ( 1 , TELEMETRY_SUBMISSION_FREQUENCY ) != 1 :
return
# No data to work with anyway
outgoing = os . path . join ( get_state_dir ( ) [ 0 ] , ' telemetry ' , ' outgoing ' )
if not os . path . isdir ( outgoing ) :
return
# We can't import requests until after it has been added during the
# bootstrapping below.
import requests
submitted = os . path . join ( get_state_dir ( ) [ 0 ] , ' telemetry ' , ' submitted ' )
try :
os . mkdir ( submitted )
except OSError as e :
if e . errno != errno . EEXIST :
raise
session = requests . Session ( )
for filename in os . listdir ( outgoing ) :
path = os . path . join ( outgoing , filename )
if os . path . isdir ( path ) or not path . endswith ( ' .json ' ) :
continue
with open ( path , ' r ' ) as f :
data = f . read ( )
r = session . post ( BUILD_TELEMETRY_SERVER , data = data ,
headers = { ' Content-Type ' : ' application/json ' } )
# TODO: some of these errors are likely not recoverable, as
# written, we'll retry indefinitely
if r . status_code != 200 :
print ( ' Error posting to telemetry: %s %s ' %
( r . status_code , r . text ) )
continue
os . rename ( os . path . join ( outgoing , filename ) ,
os . path . join ( submitted , filename ) )
session . close ( )
# Discard submitted data that is >= 30 days old
now = time . time ( )
for filename in os . listdir ( submitted ) :
ctime = os . stat ( os . path . join ( submitted , filename ) ) . st_ctime
if now - ctime > = 60 * 60 * 24 * 30 :
os . remove ( os . path . join ( submitted , filename ) )
2014-07-03 02:15:31 +04:00
def populate_context ( context , key = None ) :
if key is None :
return
if key == ' state_dir ' :
2015-07-14 23:44:59 +03:00
state_dir , is_environ = get_state_dir ( )
if is_environ :
if not os . path . exists ( state_dir ) :
2014-07-03 02:15:31 +04:00
print ( ' Creating global state directory from environment variable: %s '
2016-02-24 04:29:38 +03:00
% state_dir )
2015-07-14 23:44:59 +03:00
os . makedirs ( state_dir , mode = 0o770 )
2014-07-03 02:15:31 +04:00
else :
2015-07-14 23:44:59 +03:00
if not os . path . exists ( state_dir ) :
print ( STATE_DIR_FIRST_RUN . format ( userdir = state_dir ) )
2014-07-03 02:15:31 +04:00
try :
2016-02-24 04:29:38 +03:00
sys . stdin . readline ( )
2014-07-03 02:15:31 +04:00
except KeyboardInterrupt :
sys . exit ( 1 )
2015-07-14 23:44:59 +03:00
print ( ' \n Creating default state directory: %s ' % state_dir )
2016-02-24 04:29:38 +03:00
os . makedirs ( state_dir , mode = 0o770 )
2014-07-03 02:15:31 +04:00
return state_dir
2015-07-14 23:44:59 +03:00
2014-07-03 02:15:31 +04:00
if key == ' topdir ' :
return topsrcdir
2015-07-14 23:44:59 +03:00
Bug 1182677 - Aggressively prompt to run `mach mercurial-setup`; r=smacleod
Having not configured or out-of-date tools benefits nobody. It slows
people down.
Version control tools are an integral part of working on Firefox. It is
important for version control tools to be configured optimally and to be
continuously updated so they stay optimal.
The `mach mercurial-setup` command exists to optimally configure
Mercurial for working on Firefox and other Mozilla projects.
This commit adds a pre-dispatch handler to mach that will verify
Mercurial is in a happy state. If `mach mercurial-setup` has never
executed, it will complain. If `mach mercurial-setup` hasn't been
executed in the past 31 days, it will complain.
Yes, aborting command execution and forcing people to context switch to
run `mach mercurial-setup` is annoying. First, we have carved out
several exceptions to this behavior, including detection for running in
automation, on the machines of curmudgeons, when Mercurial isn't being
used, and from non-interactive processes. Second, I argue that people
ignore optional notifications and that having persistently
poorly-configured tools is worse than a single context switch at most
every month. Therefore, the heavyhanded approach is justified.
In addition, if we did support a non-fatal notification, we would
introduce the problem of extra output from commands. If anyone was e.g.
parsing mach output, we could very likely break those systems. These
cases should be caught by the isatty() check or be running in a context
with MOZ_AUTOMATION set. But you never know.
--HG--
extra : commitid : 7f7JQpa953u
extra : rebase_source : 47b6304b6ac2c9d8136f2023a7d03df7d1f45e4f
extra : source : f06616ee7b2b54d63d20ee4795539514d1df8c7b
2015-07-15 00:20:03 +03:00
if key == ' pre_dispatch_handler ' :
return pre_dispatch_handler
2016-01-29 21:06:36 +03:00
if key == ' telemetry_handler ' :
return telemetry_handler
2016-02-09 18:09:17 +03:00
if key == ' post_dispatch_handler ' :
return post_dispatch_handler
2014-07-03 02:15:31 +04:00
raise AttributeError ( key )
2013-07-16 06:56:15 +04:00
2013-10-11 23:44:15 +04:00
mach = mach . main . Mach ( os . getcwd ( ) )
2013-07-16 06:56:15 +04:00
mach . populate_context_handler = populate_context
2013-05-09 04:56:30 +04:00
for category , meta in CATEGORIES . items ( ) :
mach . define_category ( category , meta [ ' short ' ] , meta [ ' long ' ] ,
meta [ ' priority ' ] )
2013-03-02 03:51:11 +04:00
for path in MACH_MODULES :
2013-03-08 01:19:27 +04:00
mach . load_commands_from_file ( os . path . join ( mozilla_dir , path ) )
2013-05-09 04:56:30 +04:00
2013-03-02 03:51:11 +04:00
return mach
2015-08-05 09:43:11 +03:00
# Hook import such that .pyc/.pyo files without a corresponding .py file in
# the source directory are essentially ignored. See further below for details
# and caveats.
# Objdirs outside the source directory are ignored because in most cases, if
# a .pyc/.pyo file exists there, a .py file will be next to it anyways.
class ImportHook ( object ) :
def __init__ ( self , original_import ) :
self . _original_import = original_import
# Assume the source directory is the parent directory of the one
# containing this file.
self . _source_dir = os . path . normcase ( os . path . abspath (
os . path . dirname ( os . path . dirname ( __file__ ) ) ) ) + os . sep
self . _modules = set ( )
def __call__ ( self , name , globals = None , locals = None , fromlist = None ,
level = - 1 ) :
# name might be a relative import. Instead of figuring out what that
# resolves to, which is complex, just rely on the real import.
# Since we don't know the full module name, we can't check sys.modules,
# so we need to keep track of which modules we've already seen to avoid
# to stat() them again when they are imported multiple times.
module = self . _original_import ( name , globals , locals , fromlist , level )
# Some tests replace modules in sys.modules with non-module instances.
if not isinstance ( module , ModuleType ) :
return module
resolved_name = module . __name__
if resolved_name in self . _modules :
return module
self . _modules . add ( resolved_name )
# Builtin modules don't have a __file__ attribute.
if not hasattr ( module , ' __file__ ' ) :
return module
# Note: module.__file__ is not always absolute.
path = os . path . normcase ( os . path . abspath ( module . __file__ ) )
# Note: we could avoid normcase and abspath above for non pyc/pyo
# files, but those are actually rare, so it doesn't really matter.
if not path . endswith ( ( ' .pyc ' , ' .pyo ' ) ) :
return module
# Ignore modules outside our source directory
if not path . startswith ( self . _source_dir ) :
return module
# If there is no .py corresponding to the .pyc/.pyo module we're
# loading, remove the .pyc/.pyo file, and reload the module.
# Since we already loaded the .pyc/.pyo module, if it had side
# effects, they will have happened already, and loading the module
# with the same name, from another directory may have the same side
# effects (or different ones). We assume it's not a problem for the
# python modules under our source directory (either because it
# doesn't happen or because it doesn't matter).
if not os . path . exists ( module . __file__ [ : - 1 ] ) :
os . remove ( module . __file__ )
del sys . modules [ module . __name__ ]
module = self ( name , globals , locals , fromlist , level )
return module
# Install our hook
__builtin__ . __import__ = ImportHook ( __builtin__ . __import__ )