Browse Source

mach code-analysis backports

Ian Neal 4 months ago
parent
commit
8d3cb04777
50 changed files with 4026 additions and 0 deletions
  1. 95 0
      mozilla-release/patches/1406309-72a1.patch
  2. 177 0
      mozilla-release/patches/1436251-3-PARTIAL-79a1.patch
  3. 349 0
      mozilla-release/patches/1527818-PARTIAL-71a1.patch
  4. 59 0
      mozilla-release/patches/1550516-71a1.patch
  5. 53 0
      mozilla-release/patches/1550517-71a1.patch
  6. 74 0
      mozilla-release/patches/1556393-0-69a1.patch
  7. 70 0
      mozilla-release/patches/1563326-69a1.patch
  8. 39 0
      mozilla-release/patches/1564824-70a1.patch
  9. 33 0
      mozilla-release/patches/1568535-70a1.patch
  10. 33 0
      mozilla-release/patches/1568558-70a1.patch
  11. 74 0
      mozilla-release/patches/1568771-70a1.patch
  12. 30 0
      mozilla-release/patches/1569880-70a1.patch
  13. 52 0
      mozilla-release/patches/1573434-5-PARTIAL-70a1.patch
  14. 37 0
      mozilla-release/patches/1575659-70a1.patch
  15. 31 0
      mozilla-release/patches/1576659-PARTIAL-71a1.patch
  16. 78 0
      mozilla-release/patches/1577726-2-fix-71a1.patch
  17. 130 0
      mozilla-release/patches/1584468-71a1.patch
  18. 52 0
      mozilla-release/patches/1587079-72a1.patch
  19. 38 0
      mozilla-release/patches/1588283-72a1.patch
  20. 34 0
      mozilla-release/patches/1590086-72a1.patch
  21. 37 0
      mozilla-release/patches/1596456-72a1.patch
  22. 94 0
      mozilla-release/patches/1600048-72a1.patch
  23. 193 0
      mozilla-release/patches/1600226-73a1.patch
  24. 31 0
      mozilla-release/patches/1600558-73a1.patch
  25. 58 0
      mozilla-release/patches/1605850-74a1.patch
  26. 31 0
      mozilla-release/patches/1605852-1-73a1.patch
  27. 59 0
      mozilla-release/patches/1605879-74a1.patch
  28. 91 0
      mozilla-release/patches/1606475-80a1.patch
  29. 322 0
      mozilla-release/patches/1606541-1-73a1.patch
  30. 31 0
      mozilla-release/patches/1606541-2-73a1.patch
  31. 32 0
      mozilla-release/patches/1619956-76a1.patch
  32. 222 0
      mozilla-release/patches/1626190-76a1.patch
  33. 68 0
      mozilla-release/patches/1626640-76a1.patch
  34. 103 0
      mozilla-release/patches/1634050-77a1.patch
  35. 215 0
      mozilla-release/patches/1635112-2-78a1.patch
  36. 51 0
      mozilla-release/patches/1635112-3-78a1.patch
  37. 36 0
      mozilla-release/patches/1635112-4-78a1.patch
  38. 32 0
      mozilla-release/patches/1635526-78a1.patch
  39. 123 0
      mozilla-release/patches/1635795-78a1.patch
  40. 174 0
      mozilla-release/patches/1638985-79a1.patch
  41. 39 0
      mozilla-release/patches/1639406-79a1.patch
  42. 44 0
      mozilla-release/patches/1640142-78a1.patch
  43. 40 0
      mozilla-release/patches/1640878-78a1.patch
  44. 95 0
      mozilla-release/patches/1645948-80a1.patch
  45. 31 0
      mozilla-release/patches/1647629-79a1.patch
  46. 94 0
      mozilla-release/patches/1650057-80a1.patch
  47. 31 0
      mozilla-release/patches/1653560-81a1.patch
  48. 31 0
      mozilla-release/patches/1654795-80a1.patch
  49. 31 0
      mozilla-release/patches/1655701-81a1.patch
  50. 49 0
      mozilla-release/patches/series

+ 95 - 0
mozilla-release/patches/1406309-72a1.patch

@@ -0,0 +1,95 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1573567306 0
+# Node ID 10992479f249f70907e688b5c5622deb042d9ba7
+# Parent  a7430a4288b9156c700d2e29600dd9222525d60b
+Bug 1406309 - add `AUTOCLOBBER` for our static-analysis targets. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D52169
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -30,16 +30,18 @@ from mozbuild.base import MachCommandBas
+ 
+ from mozbuild.build_commands import Build
+ from mozbuild.nodeutil import find_node_executable
+ 
+ import mozpack.path as mozpath
+ 
+ from mozversioncontrol import get_repository_object
+ 
++from mozbuild.controller.clobber import Clobberer
++
+ 
+ # Function used to run clang-format on a batch of files. It is a helper function
+ # in order to integrate into the futures ecosystem clang-format.
+ def run_one_clang_format_batch(args):
+     try:
+         subprocess.check_output(args)
+     except subprocess.CalledProcessError as e:
+         return e
+@@ -55,16 +57,29 @@ def map_file_to_source(abs_path, source)
+         abs_path = mozpath.realpath(abs_path)
+ 
+     # Look for abs_path in source
+     if abs_path in source:
+         return abs_path
+     return None
+ 
+ 
++def prompt_bool(prompt, limit=5):
++    ''' Prompts the user with prompt and requires a boolean value. '''
++    from distutils.util import strtobool
++
++    for _ in range(limit):
++        try:
++            return strtobool(raw_input(prompt + "[Y/N]\n"))
++        except ValueError:
++            print("ERROR! Please enter a valid option! Please use any of the following:"
++                  " Y, N, True, False, 1, 0")
++    return False
++
++
+ class StaticAnalysisSubCommand(SubCommand):
+     def __call__(self, func):
+         after = SubCommand.__call__(self, func)
+         args = [
+             CommandArgument('--verbose', '-v', action='store_true',
+                             help='Print verbose output.'),
+         ]
+         for arg in args:
+@@ -1730,17 +1745,32 @@ class StaticAnalysis(MachCommandBase):
+     def _get_config_environment(self):
+         ran_configure = False
+         config = None
+         builder = Build(self._mach_context)
+ 
+         try:
+             config = self.config_environment
+         except Exception:
+-            print('Looks like configure has not run yet, running it now...')
++            self.log(logging.WARNING, 'static-analysis', {},
++                     "Looks like configure has not run yet, running it now...")
++
++            clobber = Clobberer(self.topsrcdir, self.topobjdir)
++
++            if clobber.clobber_needed():
++                choice = prompt_bool(
++                    "Configuration has changed and Clobber is needed. "
++                    "Do you want to proceed?"
++                )
++                if not choice:
++                    self.log(logging.ERROR, 'static-analysis', {},
++                             "Without Clobber we cannot continue execution!")
++                    return (1, None, None)
++                os.environ["AUTOCLOBBER"] = "1"
++
+             rc = builder.configure()
+             if rc != 0:
+                 return (rc, config, ran_configure)
+             ran_configure = True
+             try:
+                 config = self.config_environment
+             except Exception:
+                 pass

+ 177 - 0
mozilla-release/patches/1436251-3-PARTIAL-79a1.patch

@@ -0,0 +1,177 @@
+# HG changeset patch
+# User Mitchell Hentges <mhentges@mozilla.com>
+# Date 1591911305 0
+# Node ID 7d6e0d798df277d5bc0e23ae22636d3b224534f6
+# Parent  7fc99244202e04bce1eb0ce3e7ba8d2118869d64
+Bug 1636251: Patch Sentry events to ensure a raw username isn't sent to Sentry r=rstewart
+
+To avoid sending identifying information, common absolute paths are patched with placeholder values. For example, devs
+may place their Firefox repository within their home dir, so absolute paths are doctored to be prefixed with
+"<topsrcdir"> instead.
+
+Additionally, any paths including the user's home directory are patched to instead be a relate path from "~".
+
+Differential Revision: https://phabricator.services.mozilla.com/D78962
+
+diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py
+--- a/build/mach_bootstrap.py
++++ b/build/mach_bootstrap.py
+@@ -260,17 +260,17 @@ def bootstrap(topsrcdir, mozilla_dir=Non
+     def post_dispatch_handler(context, handler, instance, result,
+                               start_time, end_time, depth, args):
+         """Perform global operations after command dispatch.
+ 
+         """
+ 
+         return
+ 
+-    def populate_context(context, key=None):
++    def populate_context(key=None):
+         if key is None:
+             return
+         if key == 'state_dir':
+             state_dir = get_state_dir()
+             if state_dir == os.environ.get('MOZBUILD_STATE_PATH'):
+                 if not os.path.exists(state_dir):
+                     print('Creating global state directory from environment variable: %s'
+                           % state_dir)
+diff --git a/python/mach/mach/main.py b/python/mach/mach/main.py
+--- a/python/mach/mach/main.py
++++ b/python/mach/mach/main.py
+@@ -146,17 +146,17 @@ class ContextWrapper(object):
+         object.__setattr__(self, '_context', context)
+         object.__setattr__(self, '_handler', handler)
+ 
+     def __getattribute__(self, key):
+         try:
+             return getattr(object.__getattribute__(self, '_context'), key)
+         except AttributeError as e:
+             try:
+-                ret = object.__getattribute__(self, '_handler')(self, key)
++                ret = object.__getattribute__(self, '_handler')(key)
+             except (AttributeError, TypeError):
+                 # TypeError is in case the handler comes from old code not
+                 # taking a key argument.
+                 raise e
+             setattr(self, key, ret)
+             return ret
+ 
+     def __setattr__(self, key, value):
+@@ -169,24 +169,21 @@ class Mach(object):
+     This type is responsible for holding global mach state and dispatching
+     a command from arguments.
+ 
+     The following attributes may be assigned to the instance to influence
+     behavior:
+ 
+         populate_context_handler -- If defined, it must be a callable. The
+             callable signature is the following:
+-                populate_context_handler(context, key=None)
++                populate_context_handler(key=None)
+             It acts as a fallback getter for the mach.base.CommandContext
+             instance.
+             This allows to augment the context instance with arbitrary data
+             for use in command handlers.
+-            For backwards compatibility, it is also called before command
+-            dispatch without a key, allowing the context handler to add
+-            attributes to the context instance.
+ 
+         require_conditions -- If True, commands that do not have any condition
+             functions applied will be skipped. Defaults to False.
+ 
+         settings_paths -- A list of files or directories in which to search
+             for settings files to load.
+ 
+     """
+@@ -393,17 +390,16 @@ To see more help for a specific command,
+             self.settings.register_provider(provider)
+         self.load_settings(self.settings_paths)
+ 
+         context = CommandContext(cwd=self.cwd,
+                                  settings=self.settings, log_manager=self.log_manager,
+                                  commands=Registrar)
+ 
+         if self.populate_context_handler:
+-            self.populate_context_handler(context)
+             context = ContextWrapper(context, self.populate_context_handler)
+ 
+         parser = self.get_argument_parser(context)
+ 
+         if not len(argv):
+             # We don't register the usage until here because if it is globally
+             # registered, argparse always prints it. This is not desired when
+             # running with --help.
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -192,18 +192,19 @@ class StaticAnalysis(MachCommandBase):
+              description='Run C++ static analysis checks')
+     def static_analysis(self):
+         # If no arguments are provided, just print a help message.
+         """Detailed documentation:
+         https://firefox-source-docs.mozilla.org/code-quality/static-analysis.html
+         """
+         mach = Mach(os.getcwd())
+ 
+-        def populate_context(context, key=None):
+-            context.topdir = self.topsrcdir
++        def populate_context(key=None):
++            if key == 'topdir':
++                return self.topsrcdir
+ 
+         mach.populate_context_handler = populate_context
+         mach.run(['static-analysis', '--help'])
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'check',
+                               'Run the checks using the helper tool')
+     @CommandArgument('source', nargs='*', default=['.*'],
+                      help='Source files to be analyzed (regex on path). '
+diff --git a/testing/tools/mach_test_package_bootstrap.py b/testing/tools/mach_test_package_bootstrap.py
+--- a/testing/tools/mach_test_package_bootstrap.py
++++ b/testing/tools/mach_test_package_bootstrap.py
+@@ -183,27 +183,35 @@ def bootstrap(test_package_root):
+         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)
+ 
+     sys.path[0:0] = [os.path.join(test_package_root, path) for path in SEARCH_PATHS]
+     import mach.main
+ 
+     def populate_context(context, key=None):
+-        if key is None:
+-            context.package_root = test_package_root
+-            context.bin_dir = os.path.join(test_package_root, 'bin')
+-            context.certs_dir = os.path.join(test_package_root, 'certs')
+-            context.module_dir = os.path.join(test_package_root, 'modules')
+-            context.ancestors = ancestors
+-            context.normalize_test_path = normalize_test_path
+-            return
++        # These values will be set lazily, and cached after first being invoked.
++        if key == "package_root":
++            return test_package_root
++
++        if key == "bin_dir":
++            return os.path.join(test_package_root, 'bin')
++
++        if key == "certs_dir":
++            return os.path.join(test_package_root, 'certs')
+ 
+-        # The values for the following 'key's will be set lazily, and cached
+-        # after first being invoked.
++        if key == "module_dir":
++            return os.path.join(test_package_root, 'modules')
++
++        if key == "ancestors":
++            return ancestors
++
++        if key == "normalize_test_path":
++            return normalize_test_path
++
+         if key == 'firefox_bin':
+             return find_firefox(context)
+ 
+         if key == 'hostutils':
+             return find_hostutils(context)
+ 
+         if key == 'mozharness_config':
+             for dir_path in ancestors(context.package_root):

+ 349 - 0
mozilla-release/patches/1527818-PARTIAL-71a1.patch

@@ -0,0 +1,349 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1569237023 0
+# Node ID de2c00f37a4ab8327776285ac53b6a554adbf4ec
+# Parent  62768df130c387a74a604153f23795038d7f431e
+Bug 1527818 - Add Coverity analysis for full build on try. r=marco,bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D46477
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -286,109 +286,191 @@ class StaticAnalysis(MachCommandBase):
+     @CommandArgument('--output', '-o', default=None,
+                      help='Write coverity output translated to json output in a file')
+     @CommandArgument('--coverity_output_path', '-co', default=None,
+                      help='Path where to write coverity results as cov-results.json. '
+                      'If no path is specified the default path from the coverity working '
+                      'directory, ~./mozbuild/coverity is used.')
+     @CommandArgument('--outgoing', default=False, action='store_true',
+                      help='Run coverity on outgoing files from mercurial or git repository')
++    @CommandArgument('--full-build', default=False, action='store_true',
++                     help='Run a full build for coverity analisys.')
+     def check_coverity(self, source=[], output=None, coverity_output_path=None,
+-                       outgoing=False, verbose=False):
++                       outgoing=False, full_build=False, verbose=False):
+         self._set_log_level(verbose)
+         self.log_manager.enable_all_structured_loggers()
+ 
+         if 'MOZ_AUTOMATION' not in os.environ:
+             self.log(logging.INFO, 'static-analysis', {},
+                      'Coverity based static-analysis cannot be ran outside automation.')
+             return
+ 
++        if full_build and outgoing:
++            self.log(logging.INFO, 'static-analysis', {},
++                     'Coverity full build cannot be associated with outgoing.')
++            return
++
+         # Use outgoing files instead of source files
+         if outgoing:
+             repo = get_repository_object(self.topsrcdir)
+             files = repo.get_outgoing_files()
+             source = map(os.path.abspath, files)
+ 
+-        if len(source) == 0:
++        # Verify that we have source files or we are dealing with a full-build
++        if len(source) == 0 and not full_build:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'There are no files that coverity can use to scan.')
+             return 0
+ 
++        # Load the configuration file for coverity static-analysis
++        # For the moment we store only the reliability index for each checker
++        # as the rest is managed on the https://github.com/mozilla/release-services side.
++        self._cov_config = self._get_cov_config()
++
++        rc = self.setup_coverity()
++        if rc != 0:
++            return rc
++
++        # First run cov-run-desktop --setup in order to setup the analysis env
++        # We need this in both cases, per patch analysis or full tree build
++        cmd = [self.cov_run_desktop, '--setup']
++        if self.run_cov_command(cmd, self.cov_path):
++            return 1
++
++        # Run cov-configure for clang, javascript and python
++        langs = ["clang", "javascript", "python"]
++        for lang in langs:
++            cmd = [self.cov_configure, '--{}'.format(lang)]
++
++            if self.run_cov_command(cmd):
++                return 1
++
++        if full_build:
++            # 1. Build the model file that is going to be used for analysis
++            model_path = mozpath.join("tools", "coverity", "model.cpp")
++            cmd = [self.cov_make_library, "-sf", self.cov_lic_path, model_path]
++
++            if self.run_cov_command(cmd):
++                return 1
++
++            # 2. Run cov-build
++
++            # Add cov_build command
++            cmd = [
++                self.cov_build,
++                '--dir',
++                'cov-int'
++            ]
++            # Add fs capture search paths for languages that are not nuilt
++            cmd += [
++                "--fs-capture-search={}".format(path)
++                for path in self.cov_capture_search
++            ]
++
++            # Add the exclude criteria for test cases
++            cmd += [
++                '--fs-capture-search-exclude-regex',
++                '.*/test',
++                './mach', '--log-no-times', 'build'
++            ]
++            if self.run_cov_command(cmd):
++                return 1
++
++            # 3. Run cov-analyze and exclude disabled checkers
++            cmd = [
++                self.cov_analyze,
++                '--dir',
++                'cov-int',
++                '--all',
++                '--enable-virtual',
++                '--strip-path={}'.format(self.topsrcdir),
++                '-sf',
++                self.cov_lic_path
++            ]
++
++            cmd += [
++                "--disable={}".format(key)
++                for key, checker in self._cov_config['coverity_checkers'].items()
++                if checker.get("publish", True) is False
++            ]
++
++            if self.run_cov_command(cmd):
++                return 1
++
++            # 4. Run cov-commit-defects
++            protocol = "https" if self.cov_server_ssl else "http"
++            server_url = "{0}://{1}:{2}".format(protocol, self.cov_url, self.cov_port)
++            cmd = [
++                self.cov_commit_defects,
++                "--auth-key-file",
++                self.cov_auth_path,
++                "--stream",
++                self.cov_stream,
++                "--dir",
++                "cov-int",
++                "--url",
++                server_url,
++                "-sf",
++                self.cov_lic_path
++            ]
++
++            if self.run_cov_command(cmd):
++                return 1
++
++            return 0
++
+         rc = self._build_compile_db(verbose=verbose)
+         rc = rc or self._build_export(jobs=2, verbose=verbose)
+ 
+         if rc != 0:
+             return rc
+ 
+         commands_list = self.get_files_with_commands(source)
+         if len(commands_list) == 0:
+             self.log(logging.INFO, 'static-analysis', {},
+                      'There are no files that need to be analyzed.')
+             return 0
+ 
+-        # Load the configuration file for coverity static-analysis
+-        # For the moment we store only the reliability index for each checker
+-        # as the rest is managed on the https://github.com/mozilla/release-services side.
+-        self._cov_config = self._get_cov_config()
+-
+-        rc = self.setup_coverity()
+-        if rc != 0:
+-            return rc
+-
+-        # First run cov-run-desktop --setup in order to setup the analysis env
+-        cmd = [self.cov_run_desktop, '--setup']
+-        self.log(logging.INFO, 'static-analysis', {},
+-                 'Running {} --setup'.format(self.cov_run_desktop))
+-
+-        rc = self.run_process(args=cmd, cwd=self.cov_path, pass_thru=True)
+-
+-        if rc != 0:
+-            self.log(logging.ERROR, 'static-analysis', {},
+-                     'Running {} --setup failed!'.format(self.cov_run_desktop))
+-            return rc
+-
+-        # Run cov-configure for clang
+-        cmd = [self.cov_configure, '--clang']
+-        self.log(logging.INFO, 'static-analysis', {},
+-                 'Running {} --clang'.format(self.cov_configure))
+-
+-        rc = self.run_process(args=cmd, cwd=self.cov_path, pass_thru=True)
+-
+-        if rc != 0:
+-            self.log(logging.ERROR, 'static-analysis', {},
+-                     'Running {} --clang failed!'.format(self.cov_configure))
+-            return rc
+-
+         # For each element in commands_list run `cov-translate`
+         for element in commands_list:
+-            cmd = [self.cov_translate, '--dir', self.cov_idir_path] + element['command'].split(' ')
+-            self.log(logging.INFO, 'static-analysis', {},
+-                     'Running Coverity Tranlate for {}'.format(cmd))
+-            rc = self.run_process(args=cmd, cwd=element['directory'], pass_thru=True)
+-            if rc != 0:
+-                self.log(logging.ERROR, 'static-analysis', {},
+-                         'Running Coverity Tranlate failed for {}'.format(cmd))
+-                return cmd
++            cmd = [self.cov_translate, '--dir', self.cov_idir_path] + \
++                element['command'].split(' ')
++
++            if self.run_cov_command(cmd, element['directory']):
++                return 1
+ 
+         if coverity_output_path is None:
+             cov_result = mozpath.join(self.cov_state_path, 'cov-results.json')
+         else:
+             cov_result = mozpath.join(coverity_output_path, 'cov-results.json')
+ 
+         # Once the capture is performed we need to do the actual Coverity Desktop analysis
+-        cmd = [self.cov_run_desktop, '--json-output-v6', cov_result, '--analyze-captured-source']
+-        self.log(logging.INFO, 'static-analysis', {},
+-                 'Running Coverity Analysis for {}'.format(cmd))
+-        rc = self.run_process(cmd, cwd=self.cov_state_path, pass_thru=True)
+-        if rc != 0:
+-            self.log(logging.ERROR, 'static-analysis', {}, 'Coverity Analysis failed!')
++        cmd = [self.cov_run_desktop, '--json-output-v6',
++               cov_result, '--analyze-captured-source']
++
++        if self.run_cov_command(cmd, self.cov_state_path):
++            return 1
+ 
+         if output is not None:
+             self.dump_cov_artifact(cov_result, source, output)
+ 
++    def run_cov_command(self, cmd, path=None):
++        if path is None:
++            # We want to run it in topsrcdir
++            path = self.topsrcdir
++
++        self.log(logging.INFO, 'static-analysis', {}, 'Running '+' '.join(cmd))
++
++        rc = self.run_process(args=cmd, cwd=path, pass_thru=True)
++
++        if rc != 0:
++            self.log(logging.ERROR, 'static-analysis', {}, 'Running ' + ' '.join(cmd) + ' failed!')
++            return rc
++        return 0
++
+     def get_reliability_index_for_cov_checker(self, checker_name):
+         if self._cov_config is None:
+             self.log(logging.INFO, 'static-analysis', {}, 'Coverity config file not found, '
+                      'using default-value \'reliablity\' = medium. for checker {}'.format(
+                         checker_name))
+             return 'medium'
+ 
+         checkers = self._cov_config['coverity_checkers']
+@@ -495,22 +577,26 @@ class StaticAnalysis(MachCommandBase):
+         if cov_config is None:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'Ill formatted secret for Coverity. Aborting analysis.')
+             return 1
+ 
+         self.cov_analysis_url = cov_config.get('package_url')
+         self.cov_package_name = cov_config.get('package_name')
+         self.cov_url = cov_config.get('server_url')
++        self.cov_server_ssl = cov_config.get('server_ssl', True)
+         # In case we don't have a port in the secret we use the default one,
+         # for a default coverity deployment.
+         self.cov_port = cov_config.get('server_port', 8443)
+         self.cov_auth = cov_config.get('auth_key')
+         self.cov_package_ver = cov_config.get('package_ver')
++        self.cov_lic_name = cov_config.get('lic_name')
++        self.cov_capture_search = cov_config.get('fs_capture_search', None)
+         self.cov_full_stack = cov_config.get('full_stack', False)
++        self.cov_stream = cov_config.get('stream', False)
+ 
+         return 0
+ 
+     def download_coverity(self):
+         if self.cov_url is None or self.cov_port is None or \
+                 self.cov_analysis_url is None or \
+                 self.cov_auth is None:
+             self.log(logging.ERROR, 'static-analysis', {}, 'Missing Coverity secret on try job!')
+@@ -532,36 +618,36 @@ class StaticAnalysis(MachCommandBase):
+             "cov_run_desktop": {
+                 "build_cmd": [],
+                 "clean_cmd": []
+             }
+             }
+         }
+         '''
+         # Generate the coverity.conf and auth files
+-        cov_auth_path = mozpath.join(self.cov_state_path, 'auth')
++        self.cov_auth_path = mozpath.join(self.cov_state_path, 'auth')
+         cov_setup_path = mozpath.join(self.cov_state_path, 'coverity.conf')
+-        cov_conf = COVERITY_CONFIG % (self.cov_url, self.cov_port, cov_auth_path)
++        cov_conf = COVERITY_CONFIG % (self.cov_url, self.cov_port, self.cov_auth_path)
+ 
+         def download(artifact_url, target):
+             import requests
+             resp = requests.get(artifact_url, verify=False, stream=True)
+             resp.raise_for_status()
+ 
+             # Extract archive into destination
+             with tarfile.open(fileobj=io.BytesIO(resp.content)) as tar:
+                 tar.extractall(target)
+ 
+         download(self.cov_analysis_url, self.cov_state_path)
+ 
+-        with open(cov_auth_path, 'w') as f:
++        with open(self.cov_auth_path, 'w') as f:
+             f.write(self.cov_auth)
+ 
+         # Modify it's permission to 600
+-        os.chmod(cov_auth_path, 0o600)
++        os.chmod(self.cov_auth_path, 0o600)
+ 
+         with open(cov_setup_path, 'a') as f:
+             f.write(cov_conf)
+ 
+     def setup_coverity(self, force_download=True):
+         rc, config, _ = self._get_config_environment()
+         rc = rc or self.get_coverity_secrets()
+ 
+@@ -576,20 +662,27 @@ class StaticAnalysis(MachCommandBase):
+ 
+         os.mkdir(self.cov_state_path)
+ 
+         # Download everything that we need for Coverity from out private instance
+         self.download_coverity()
+ 
+         self.cov_path = mozpath.join(self.cov_state_path, self.cov_package_name)
+         self.cov_run_desktop = mozpath.join(self.cov_path, 'bin', 'cov-run-desktop')
++        self.cov_configure = mozpath.join(self.cov_path, 'bin', 'cov-configure')
++        self.cov_make_library = mozpath.join(self.cov_path, 'bin', 'cov-make-library')
++        self.cov_build = mozpath.join(self.cov_path, 'bin', 'cov-build')
++        self.cov_analyze = mozpath.join(self.cov_path, 'bin', 'cov-analyze')
++        self.cov_commit_defects = mozpath.join(self.cov_path, 'bin', 'cov-commit-defects')
+         self.cov_translate = mozpath.join(self.cov_path, 'bin', 'cov-translate')
+         self.cov_configure = mozpath.join(self.cov_path, 'bin', 'cov-configure')
+         self.cov_work_path = mozpath.join(self.cov_state_path, 'data-coverity')
+         self.cov_idir_path = mozpath.join(self.cov_work_path, self.cov_package_ver, 'idir')
++        self.cov_lic_path = mozpath.join(
++            self.cov_work_path, self.cov_package_ver, 'lic', self.cov_lic_name)
+ 
+         if not os.path.exists(self.cov_path):
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'Missing Coverity in {}'.format(self.cov_path))
+             return 1
+ 
+         return 0
+ 

+ 59 - 0
mozilla-release/patches/1550516-71a1.patch

@@ -0,0 +1,59 @@
+# HG changeset patch
+# User Bastien Abadie <bastien@mozilla.com>
+# Date 1568361023 0
+# Node ID 7e3d9c747e6e3b97080ea2ce72b25d00927a6e87
+# Parent  09463399904321e8f17fe5beb7d054196455cf8d
+Bug 1550516 - Export clang-tidy check configuration in static-analysis json output, r=sylvestre.
+
+Differential Revision: https://phabricator.services.mozilla.com/D45652
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -115,33 +115,32 @@ class StaticAnalysisMonitor(object):
+             filename = line.split(' ')[-1]
+             if os.path.isfile(filename):
+                 self._current = os.path.relpath(filename, self._srcdir)
+             else:
+                 self._current = None
+             self._processed = self._processed + 1
+             return (warning, False)
+         if warning is not None:
+-            def get_reliability(checker_name):
++            def get_check_config(checker_name):
+                 # get the matcher from self._clang_tidy_config that is the 'name' field
+-                reliability = None
+                 for item in self._clang_tidy_config:
+                     if item['name'] == checker_name:
+-                        reliability = item.get('reliability', 'low')
+-                        break
+-                    else:
+-                        # We are using a regex in order to also match 'mozilla-.* like checkers'
+-                        matcher = re.match(item['name'], checker_name)
+-                        if matcher is not None and matcher.group(0) == checker_name:
+-                            reliability = item.get('reliability', 'low')
+-                            break
+-                return reliability
+-            reliability = get_reliability(warning['flag'])
+-            if reliability is not None:
+-                warning['reliability'] = reliability
++                        return item
++
++                    # We are using a regex in order to also match 'mozilla-.* like checkers'
++                    matcher = re.match(item['name'], checker_name)
++                    if matcher is not None and matcher.group(0) == checker_name:
++                        return item
++
++            check_config = get_check_config(warning['flag'])
++            if check_config is not None:
++                warning['reliability'] = check_config.get('reliability', 'low')
++                warning['reason'] = check_config.get('reason')
++                warning['publish'] = check_config.get('publish', True)
+         return (warning, True)
+ 
+ 
+ @CommandProvider
+ class StaticAnalysis(MachCommandBase):
+     """Utilities for running C++ static analysis checks and format."""
+ 
+     # List of file extension to consider (should start with dot)

+ 53 - 0
mozilla-release/patches/1550517-71a1.patch

@@ -0,0 +1,53 @@
+# HG changeset patch
+# User Bastien Abadie <bastien@mozilla.com>
+# Date 1568278180 0
+# Node ID 62b744c40e6d494fc394b72c95b4ff1fdde22508
+# Parent  b503169bb4abcf81f44a834fe0f6f2716b69a174
+Bug 1550517 - Exclude 3rd party files on static-analysis check, r=sylvestre.
+
+Differential Revision: https://phabricator.services.mozilla.com/D45630
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -232,17 +232,20 @@ class StaticAnalysis(MachCommandBase):
+         chunk_size = 50
+         for offset in range(0, len(source), chunk_size):
+             source_chunks = source[offset:offset + chunk_size]
+             name_re = re.compile('(' + ')|('.join(source_chunks) + ')')
+             for f in compile_db:
+                 if name_re.search(f['file']):
+                     total = total + 1
+ 
+-        if not total:
++        # Filter source to remove excluded files
++        source = self._generate_path_list(source, verbose=verbose)
++
++        if not total or not source:
+             self.log(logging.INFO, 'static-analysis', {},
+                      "There are no files eligible for analysis. Please note that 'header' files "
+                      "cannot be used for analysis since they do not consist compilation units.")
+             return 0
+ 
+         cwd = self.topobjdir
+         self._compilation_commands_path = self.topobjdir
+         if self._clang_tidy_config is None:
+@@ -1904,17 +1907,17 @@ class StaticAnalysis(MachCommandBase):
+         ignored_dir_re = '(%s)' % '|'.join(ignored_dir)
+         extensions = self._format_include_extensions
+ 
+         path_list = []
+         for f in paths:
+             if self._is_ignored_path(ignored_dir_re, f):
+                 # Early exit if we have provided an ignored directory
+                 if verbose:
+-                    print("clang-format: Ignored third party code '{0}'".format(f))
++                    print("static-analysis: Ignored third party code '{0}'".format(f))
+                 continue
+ 
+             if os.path.isdir(f):
+                 # Processing a directory, generate the file list
+                 for folder, subs, files in os.walk(f):
+                     subs.sort()
+                     for filename in sorted(files):
+                         f_in_dir = os.path.join(folder, filename)

+ 74 - 0
mozilla-release/patches/1556393-0-69a1.patch

@@ -0,0 +1,74 @@
+# HG changeset patch
+# User Victor Porof <vporof@mozilla.com>
+# Date 1562244620 -7200
+# Node ID 60169d9efd0d99bd6c9d891288c0b740f65a4571
+# Parent  e93723159f4787e021292297ce44e4c51504a691
+Bug 1556393 - Pre 0 (m-c): Create a simple Prettier command for running format-source, r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D36720
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -24,16 +24,17 @@ from mach.decorators import (
+     SubCommand,
+ )
+ 
+ from mach.main import Mach
+ 
+ from mozbuild.base import MachCommandBase
+ 
+ from mozbuild.build_commands import Build
++from mozbuild.nodeutil import find_node_executable
+ 
+ import mozpack.path as mozpath
+ 
+ from mozversioncontrol import get_repository_object
+ 
+ 
+ # Function used to run clang-format on a batch of files. It is a helper function
+ # in order to integrate into the futures ecosystem clang-format.
+@@ -1322,16 +1323,43 @@ class StaticAnalysis(MachCommandBase):
+         if rc != 0:
+             return rc
+         checkers, _ = self._get_infer_config()
+         print('Infer checks:')
+         for checker in checkers:
+             print(' '*4 + checker)
+         return 0
+ 
++    @Command('prettier-format',  category='misc', description='Run prettier on current changes')
++    @CommandArgument('--path', '-p', nargs=1, required=True,
++                     help='Specify the path to reformat to stdout.')
++    @CommandArgument('--assume-filename', '-a', nargs=1, required=True,
++                     help='This option is usually used in the context of hg-formatsource.'
++                          'When reading from stdin, Prettier assumes this '
++                          'filename to decide which style and parser to use.')
++    def prettier_format(self, path, assume_filename):
++        # With assume_filename we want to have stdout clean since the result of the
++        # format will be redirected to stdout.
++
++        binary, _ = find_node_executable()
++        prettier = os.path.join(self.topsrcdir, "node_modules", "prettier", "bin-prettier.js")
++        path = os.path.join(self.topsrcdir, path[0])
++
++        # We use --stdin-filepath in order to better determine the path for
++        # the prettier formatter when it is ran outside of the repo, for example
++        # by the extension hg-formatsource.
++        args = [binary, prettier, '--stdin-filepath', assume_filename[0]]
++
++        process = subprocess.Popen(args, stdin=subprocess.PIPE)
++        with open(path, 'r') as fin:
++            process.stdin.write(fin.read())
++            process.stdin.close()
++            process.wait()
++            return process.returncode
++
+     @Command('clang-format',  category='misc', description='Run clang-format on current changes')
+     @CommandArgument('--show', '-s', action='store_const', const='stdout', dest='output_path',
+                      help='Show diff output on stdout instead of applying changes')
+     @CommandArgument('--assume-filename', '-a', nargs=1, default=None,
+                      help='This option is usually used in the context of hg-formatsource.'
+                           'When reading from stdin, clang-format assumes this '
+                           'filename to look for a style config file (with '
+                           '-style=file) and to determine the language. When '

+ 70 - 0
mozilla-release/patches/1563326-69a1.patch

@@ -0,0 +1,70 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1562240536 0
+# Node ID d5f0b13c7d71806ed6c5df8a5a2f8d00ab272518
+# Parent  3d39a2f7d7dacae6214192aad6910a4ca02cbf09
+Bug 1563326 - for code-analysis target do not globally import PackageFrontend. r=sylvestre
+
+By globally importing PackageFrontend from the globe-analysis module we break the logger for
+the PackageFrontend package.
+
+Differential Revision: https://phabricator.services.mozilla.com/D36887
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -24,17 +24,16 @@ from mach.decorators import (
+     SubCommand,
+ )
+ 
+ from mach.main import Mach
+ 
+ from mozbuild.base import MachCommandBase
+ 
+ from mozbuild.build_commands import Build
+-from mozbuild.artifact_commands import PackageFrontend
+ 
+ import mozpack.path as mozpath
+ 
+ from mozversioncontrol import get_repository_object
+ 
+ 
+ # Function used to run clang-format on a batch of files. It is a helper function
+ # in order to integrate into the futures ecosystem clang-format.
+@@ -1671,16 +1670,18 @@ class StaticAnalysis(MachCommandBase):
+                                          download_if_needed=download_if_needed)
+ 
+         # Create base directory where we store clang binary
+         os.mkdir(self._clang_tools_path)
+ 
+         if source:
+             return self._get_clang_tools_from_source(source)
+ 
++        from mozbuild.artifact_commands import PackageFrontend
++
+         self._artifact_manager = PackageFrontend(self._mach_context)
+ 
+         if not download_if_needed:
+             return 0
+ 
+         job, _ = self.platform
+ 
+         if job is None:
+@@ -1778,16 +1779,17 @@ class StaticAnalysis(MachCommandBase):
+         if os.path.isdir(infer_path) and download_if_needed:
+             # The directory exists, perhaps it's corrupted?  Delete it
+             # and start from scratch.
+             shutil.rmtree(infer_path)
+             return self._get_infer(force=force, skip_cache=skip_cache,
+                                    verbose=verbose,
+                                    download_if_needed=download_if_needed)
+         os.mkdir(infer_path)
++        from mozbuild.artifact_commands import PackageFrontend
+         self._artifact_manager = PackageFrontend(self._mach_context)
+         if not download_if_needed:
+             return 0
+         job, _ = self.platform
+         if job != 'linux64':
+             return -1
+         else:
+             job += '-infer'

+ 39 - 0
mozilla-release/patches/1564824-70a1.patch

@@ -0,0 +1,39 @@
+# HG changeset patch
+# User Victor Porof <vporof@mozilla.com>
+# Date 1562757318 0
+# Node ID ec2818ee17f73621d39f6e52a4cbaaef76ce2b54
+# Parent  48096ea4e485aa45bba0342ae8859a4923b68ba1
+Bug 1564824 - Format source fails with Prettier on patches with moved files where the original directory also does not exist, r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D37537
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1338,20 +1338,25 @@ class StaticAnalysis(MachCommandBase):
+     def prettier_format(self, path, assume_filename):
+         # With assume_filename we want to have stdout clean since the result of the
+         # format will be redirected to stdout.
+ 
+         binary, _ = find_node_executable()
+         prettier = os.path.join(self.topsrcdir, "node_modules", "prettier", "bin-prettier.js")
+         path = os.path.join(self.topsrcdir, path[0])
+ 
++        # Bug 1564824. Prettier fails on patches with moved files where the
++        # original directory also does not exist.
++        assume_dir = os.path.dirname(os.path.join(self.topsrcdir, assume_filename[0]))
++        assume_filename = assume_filename[0] if os.path.isdir(assume_dir) else path
++
+         # We use --stdin-filepath in order to better determine the path for
+         # the prettier formatter when it is ran outside of the repo, for example
+         # by the extension hg-formatsource.
+-        args = [binary, prettier, '--stdin-filepath', assume_filename[0]]
++        args = [binary, prettier, '--stdin-filepath', assume_filename]
+ 
+         process = subprocess.Popen(args, stdin=subprocess.PIPE)
+         with open(path, 'r') as fin:
+             process.stdin.write(fin.read())
+             process.stdin.close()
+             process.wait()
+             return process.returncode
+ 

+ 33 - 0
mozilla-release/patches/1568535-70a1.patch

@@ -0,0 +1,33 @@
+# HG changeset patch
+# User Bastien Abadie <bastien@mozilla.com>
+# Date 1564044650 0
+# Node ID 3717ce1a6d03eac33e0f4b533b354a3a9d38b6a6
+# Parent  d379c86f833bfcd7955fa2839b5fcc2661fdf479
+Bug 1568535 - Output relative paths in mach static-analysis check, r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D39197
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -74,16 +74,20 @@ class StaticAnalysisMonitor(object):
+         from mozbuild.compilation.warnings import (
+             WarningsCollector,
+             WarningsDatabase,
+         )
+ 
+         self._warnings_database = WarningsDatabase()
+ 
+         def on_warning(warning):
++
++            # Output paths relative to repository root
++            warning['filename'] = os.path.relpath(warning['filename'], srcdir)
++
+             self._warnings_database.insert(warning)
+ 
+         self._warnings_collector = WarningsCollector(on_warning, objdir=objdir)
+ 
+     @property
+     def num_files(self):
+         return self._total
+ 

+ 33 - 0
mozilla-release/patches/1568558-70a1.patch

@@ -0,0 +1,33 @@
+# HG changeset patch
+# User Bastien Abadie <bastien@mozilla.com>
+# Date 1564044633 0
+# Node ID dded2f82e555e5c3b1ba7893ab6d61fde76df046
+# Parent  403a754b5d26408b623f0d4187c74e5123a7d67b
+Bug 1568558 - Output paths relative to repository in ./mach clang-format, r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D39211
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1966,17 +1966,19 @@ class StaticAnalysis(MachCommandBase):
+                     os.makedirs(faketmpdir)
+                 shutil.copy(l[0], faketmpdir)
+                 l[0] = target_file
+ 
+                 # Run clang-format on the list
+                 try:
+                     output = check_output(args + l)
+                     if output and output_format == 'json':
+-                        patches[original_path] = self._parse_xml_output(original_path, output)
++                        # Output a relative path in json patch list
++                        relative_path = os.path.relpath(original_path, self.topsrcdir)
++                        patches[relative_path] = self._parse_xml_output(original_path, output)
+                 except CalledProcessError as e:
+                     # Something wrong happend
+                     print("clang-format: An error occured while running clang-format.")
+                     return e.returncode
+ 
+                 # show the diff
+                 if output_format == 'diff':
+                     diff_command = ["diff", "-u", original_path, target_file]

+ 74 - 0
mozilla-release/patches/1568771-70a1.patch

@@ -0,0 +1,74 @@
+# HG changeset patch
+# User Bastien Abadie <bastien@mozilla.com>
+# Date 1564469092 0
+# Node ID 4b4988e99e7687fbd8a5d5b2d6391cf2e42d3421
+# Parent  639f502ded6b1d8db390b625b65692622a3c943f
+Bug 1568771 - Output paths relative to repository in ./mach static-analysis check-coverity, r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D39306
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -400,16 +400,23 @@ class StaticAnalysis(MachCommandBase):
+                      'For the moment we shall use the default \'reliablity\' = medium.'.format(
+                         checker_name))
+             return 'medium'
+ 
+         return checkers[checker_name]['reliability']
+ 
+     def dump_cov_artifact(self, cov_results, source, output):
+         # Parse Coverity json into structured issues
++
++        def relpath(path):
++            '''Build path relative to repository root'''
++            if path.startswith(self.topsrcdir):
++                return os.path.relpath(path, self.topsrcdir)
++            return path
++
+         with open(cov_results) as f:
+             result = json.load(f)
+ 
+             # Parse the issues to a standard json format
+             issues_dict = {'files': {}}
+ 
+             files_list = issues_dict['files']
+ 
+@@ -430,17 +437,17 @@ class StaticAnalysis(MachCommandBase):
+                         'stateOnServer': issue['stateOnServer'],
+                         'stack': []
+                     }
+                 }
+ 
+                 # Embed all events into extra message
+                 for event in issue['events']:
+                     dict_issue['extra']['stack'].append(
+-                        {'file_path': event['strippedFilePathname'],
++                        {'file_path': relpath(event['strippedFilePathname']),
+                          'line_number': event['lineNumber'],
+                          'path_type': event['eventTag'],
+                          'description': event['eventDescription']})
+ 
+                 return dict_issue
+ 
+             for issue in result['issues']:
+                 path = self.cov_is_file_in_source(issue['strippedMainEventFilePathname'], source)
+@@ -448,16 +455,17 @@ class StaticAnalysis(MachCommandBase):
+                     # Since we skip a result we should log it
+                     self.log(logging.INFO, 'static-analysis', {},
+                              'Skipping CID: {0} from file: {1} since it\'s not related '
+                              'with the current patch.'.format(
+                                 issue['stateOnServer']['cid'],
+                                 issue['strippedMainEventFilePathname'])
+                              )
+                     continue
++                path = relpath(path)
+                 if path in files_list:
+                     files_list[path]['warnings'].append(build_element(issue))
+                 else:
+                     files_list[path] = {'warnings': [build_element(issue)]}
+ 
+             with open(output, 'w') as f:
+                 json.dump(issues_dict, f)
+ 
+

+ 30 - 0
mozilla-release/patches/1569880-70a1.patch

@@ -0,0 +1,30 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1564472538 0
+# Node ID 4e1abd6fed42de1b4a25ad47d1df39d096f7c2ff
+# Parent  77185e0f81f7fe43e636057f605b357b9411c4cd
+Bug 1569880 - Report build errors during review-phase for C/C++ code. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D39843
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -423,16 +423,17 @@ class StaticAnalysis(MachCommandBase):
+             def build_element(issue):
+                 # We look only for main event
+                 event_path = next(
+                     (event for event in issue['events'] if event['main'] is True), None)
+ 
+                 dict_issue = {
+                     'line': issue['mainEventLineNumber'],
+                     'flag': issue['checkerName'],
++                    'build_error': issue['checkerName'].startswith('RW.CLANG'),
+                     'message': event_path['eventDescription'],
+                     'reliability': self.get_reliability_index_for_cov_checker(
+                         issue['checkerName']
+                         ),
+                     'extra': {
+                         'category': issue['checkerProperties']['category'],
+                         'stateOnServer': issue['stateOnServer'],
+                         'stack': []

+ 52 - 0
mozilla-release/patches/1573434-5-PARTIAL-70a1.patch

@@ -0,0 +1,52 @@
+# HG changeset patch
+# User Mike Hommey <mh+mozilla@glandium.org>
+# Date 1565748406 -32400
+# Node ID 3103e4be4bb4d63926e309af68ed23074207b064
+# Parent  be7eb9a1518f53bd9d5dff0028ab0404f2663f4a
+Bug 1573435 - Use toolchain fetches for source-test builds. r=nalexander
+
+While here, use GECKO_PATH instead of $HOME/checkouts/gecko.
+
+Differential Revision: https://phabricator.services.mozilla.com/D41889
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -925,17 +925,17 @@ class StaticAnalysis(MachCommandBase):
+         self.TOOLS_CHECKER_NOT_FOUND = 7
+         self.TOOLS_CHECKER_FAILED_FILE = 8
+         self.TOOLS_CHECKER_LIST_EMPTY = 9
+         self.TOOLS_GRADLE_FAILED = 10
+ 
+         # Configure the tree or download clang-tidy package, depending on the option that we choose
+         if intree_tool:
+             _, config, _ = self._get_config_environment()
+-            clang_tools_path = self.topsrcdir
++            clang_tools_path = os.environ['MOZ_FETCHES_DIR']
+             self._clang_tidy_path = mozpath.join(
+                 clang_tools_path, "clang-tidy", "bin",
+                 "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
+             self._clang_format_path = mozpath.join(
+                 clang_tools_path, "clang-tidy", "bin",
+                 "clang-format" + config.substs.get('BIN_SUFFIX', ''))
+             self._clang_apply_replacements = mozpath.join(
+                 clang_tools_path, "clang-tidy", "bin",
+@@ -1808,17 +1808,17 @@ class StaticAnalysis(MachCommandBase):
+                     args += [':({0}){1}'.format(','.join(magics), pattern)]
+         return args
+ 
+     def _get_infer(self, force=False, skip_cache=False, download_if_needed=True,
+                    verbose=False, intree_tool=False):
+         rc, config, _ = self._get_config_environment()
+         if rc != 0:
+             return rc
+-        infer_path = self.topsrcdir if intree_tool else \
++        infer_path = os.environ['MOZ_FETCHES_DIR'] if intree_tool else \
+             mozpath.join(self._mach_context.state_dir, 'infer')
+         self._infer_path = mozpath.join(infer_path, 'infer', 'bin', 'infer' +
+                                         config.substs.get('BIN_SUFFIX', ''))
+         if intree_tool:
+             return not os.path.exists(self._infer_path)
+         if os.path.exists(self._infer_path) and not force:
+             return 0
+ 

+ 37 - 0
mozilla-release/patches/1575659-70a1.patch

@@ -0,0 +1,37 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1566809869 0
+# Node ID b17808d15bde956bee50f4837fa985aa7855b282
+# Parent  c0d795a4f9185b4752418a939960e5346f0c04d2
+Bug 1575659 - Fixed crashing of `mach static-analisys` when no arguments where passed. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D43393
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -150,18 +150,23 @@ class StaticAnalysis(MachCommandBase):
+     _format_ignore_file = '.clang-format-ignore'
+ 
+     _clang_tidy_config = None
+     _cov_config = None
+ 
+     @Command('static-analysis', category='testing',
+              description='Run C++ static analysis checks')
+     def static_analysis(self):
+-        # If not arguments are provided, just print a help message.
++        # If no arguments are provided, just print a help message.
+         mach = Mach(os.getcwd())
++
++        def populate_context(context, key=None):
++            context.topdir = self.topsrcdir
++
++        mach.populate_context_handler = populate_context
+         mach.run(['static-analysis', '--help'])
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'check',
+                               'Run the checks using the helper tool')
+     @CommandArgument('source', nargs='*', default=['.*'],
+                      help='Source files to be analyzed (regex on path). '
+                           'Can be omitted, in which case the entire code base '
+                           'is analyzed.  The source argument is ignored if '

+ 31 - 0
mozilla-release/patches/1576659-PARTIAL-71a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1568384732 0
+# Node ID b76411ee5a2d4ae3d11c0ba9cb0b2d21d44db53b
+# Parent  df08271068b7a03c746de5d6465bc58c1f5b1d15
+Bug 1576659 - Update infer to 0.17.0. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D43471
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1256,17 +1256,17 @@ class StaticAnalysis(MachCommandBase):
+         if not issues:
+             self.log(
+                 logging.ERROR, 'static-analysis', {},
+                 "ERROR: infer check {0} did not find any issues in its associated test suite."
+                 .format(check)
+             )
+             return self.TOOLS_CHECKER_RETURNED_NO_ISSUES
+         if self._dump_results:
+-            self._build_autotest_result(test_file_path_json, issues)
++            self._build_autotest_result(test_file_path_json, json.dumps(issues))
+         else:
+             if not os.path.exists(test_file_path_json):
+                 # Result file for test not found maybe regenerate it?
+                 self.log(
+                     logging.ERROR, 'static-analysis', {},
+                     "ERROR: infer result file not found for check {0}".format(check)
+                 )
+                 return self.TOOLS_CHECKER_RESULT_FILE_NOT_FOUND

+ 78 - 0
mozilla-release/patches/1577726-2-fix-71a1.patch

@@ -0,0 +1,78 @@
+# HG changeset patch
+# User Sylvestre Ledru <sledru@mozilla.com>
+# Date 1567693461 0
+# Node ID df7da1b22c2f259242adb42b4ea271b8d7a5a828
+# Parent  d935413c47f961490807244543ce9854a431faa2
+Bug 1577726 - Move generated directories into a dedicated file (Generated.txt) from ThirdPartyPaths.txt r=ahal
+
+Differential Revision: https://phabricator.services.mozilla.com/D44147
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -687,20 +687,21 @@ class StaticAnalysis(MachCommandBase):
+             if rc != 0:
+                 return rc
+         rc = self._get_infer(verbose=verbose)
+         if rc != 0:
+             self.log(logging.WARNING, 'static-analysis', {},
+                      'This command is only available for linux64!')
+             return rc
+         # which checkers to use, and which folders to exclude
+-        all_checkers, third_party_path = self._get_infer_config()
++        all_checkers, third_party_path, generated_path = self._get_infer_config()
+         checkers, excludes = self._get_infer_args(
+             checks=checks or all_checkers,
+-            third_party_path=third_party_path
++            third_party_path=third_party_path,
++            generated_path=generated_path
+         )
+         rc = rc or self._gradle(['clean'])  # clean so that we can recompile
+         # infer capture command
+         capture_cmd = [self._infer_path, 'capture'] + excludes + ['--']
+         rc = rc or self._gradle([task], infer_args=capture_cmd, verbose=verbose)
+         tmp_file, args = self._get_infer_source_args(java_sources)
+         # infer analyze command
+         analysis_cmd = [self._infer_path, 'analyze', '--keep-going'] +  \
+@@ -751,33 +752,35 @@ class StaticAnalysis(MachCommandBase):
+         with open(mozpath.join(self.topsrcdir, 'tools',
+                                'infer', 'config.yaml')) as f:
+             try:
+                 config = yaml.safe_load(f)
+                 for item in config['infer_checkers']:
+                     if item['publish']:
+                         checkers.append(item['name'])
+                 tp_path = mozpath.join(self.topsrcdir, config['third_party'])
++                generated_path = mozpath.join(self.topsrcdir, config['generated'])
+             except Exception:
+                 print('Looks like config.yaml is not valid, so we are unable '
+                       'to determine default checkers, and which folder to '
+                       'exclude, using defaults provided by infer')
+-        return checkers, tp_path
++        return checkers, tp_path, generated_path
+ 
+-    def _get_infer_args(self, checks, third_party_path):
++    def _get_infer_args(self, checks, *input_paths):
+         '''Return the arguments which include the checkers <checks>, and
+         excludes all folder in <third_party_path>.'''
+         checkers = ['-a', 'checkers']
+         excludes = []
+         for checker in checks:
+             checkers.append('--' + checker)
+-        with open(third_party_path) as f:
+-            for line in f:
+-                excludes.append('--skip-analysis-in-path')
+-                excludes.append(line.strip('\n'))
++        for path in input_paths:
++            with open(path) as f:
++                for line in f:
++                    excludes.append('--skip-analysis-in-path')
++                    excludes.append(line.strip('\n'))
+         return checkers, excludes
+ 
+     def _get_clang_tidy_config(self):
+         try:
+             file_handler = open(mozpath.join(self.topsrcdir, "tools", "clang-tidy", "config.yaml"))
+             config = yaml.safe_load(file_handler)
+         except Exception:
+             self.log(logging.ERROR, 'static-analysis', {},

+ 130 - 0
mozilla-release/patches/1584468-71a1.patch

@@ -0,0 +1,130 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1571139372 0
+# Node ID cc291fb152956bdb824560cde53c6535c781f80b
+# Parent  982fd5fca408db52a1e628b38050e8842a132b49
+Bug 1584468 - for review-time static analysis try to match files from the obj directory to files from the repo. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D48702
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -40,16 +40,31 @@ from mozversioncontrol import get_reposi
+ # in order to integrate into the futures ecosystem clang-format.
+ def run_one_clang_format_batch(args):
+     try:
+         subprocess.check_output(args)
+     except subprocess.CalledProcessError as e:
+         return e
+ 
+ 
++def map_file_to_source(abs_path, source):
++    # We have as an input an absolute path for whom we verify if it's a symlink,
++    # if so, we follow that symlink and we match it with elements from source,
++    # If the match is done we return abs_path, otherwise None.
++    assert isinstance(source, (list, tuple))
++
++    if os.path.islink(abs_path):
++        abs_path = mozpath.realpath(abs_path)
++
++    # Look for abs_path in source
++    if abs_path in source:
++        return abs_path
++    return None
++
++
+ class StaticAnalysisSubCommand(SubCommand):
+     def __call__(self, func):
+         after = SubCommand.__call__(self, func)
+         args = [
+             CommandArgument('--verbose', '-v', action='store_true',
+                             help='Print verbose output.'),
+         ]
+         for arg in args:
+@@ -76,17 +91,18 @@ class StaticAnalysisMonitor(object):
+             WarningsDatabase,
+         )
+ 
+         self._warnings_database = WarningsDatabase()
+ 
+         def on_warning(warning):
+ 
+             # Output paths relative to repository root
+-            warning['filename'] = os.path.relpath(warning['filename'], srcdir)
++            warning['filename'] = mozpath.relpath(
++                map_file_to_source(warning['filename']), self._srcdir)
+ 
+             self._warnings_database.insert(warning)
+ 
+         self._warnings_collector = WarningsCollector(on_warning, objdir=objdir)
+ 
+     @property
+     def num_files(self):
+         return self._total
+@@ -109,17 +125,17 @@ class StaticAnalysisMonitor(object):
+         try:
+             warning = self._warnings_collector.process_line(line)
+         except Exception:
+             pass
+ 
+         if line.find('clang-tidy') != -1:
+             filename = line.split(' ')[-1]
+             if os.path.isfile(filename):
+-                self._current = os.path.relpath(filename, self._srcdir)
++                self._current = mozpath.relpath(map_file_to_source(filename), self._srcdir)
+             else:
+                 self._current = None
+             self._processed = self._processed + 1
+             return (warning, False)
+         if warning is not None:
+             def get_check_config(checker_name):
+                 # get the matcher from self._clang_tidy_config that is the 'name' field
+                 for item in self._clang_tidy_config:
+@@ -535,17 +551,17 @@ class StaticAnalysis(MachCommandBase):
+                         {'file_path': relpath(event['strippedFilePathname']),
+                          'line_number': event['lineNumber'],
+                          'path_type': event['eventTag'],
+                          'description': event['eventDescription']})
+ 
+                 return dict_issue
+ 
+             for issue in result['issues']:
+-                path = self.cov_is_file_in_source(issue['strippedMainEventFilePathname'], source)
++                path = map_file_to_source(issue['strippedMainEventFilePathname'], source)
+                 if path is None:
+                     # Since we skip a result we should log it
+                     self.log(logging.INFO, 'static-analysis', {},
+                              'Skipping CID: {0} from file: {1} since it\'s not related '
+                              'with the current patch.'.format(
+                                 issue['stateOnServer']['cid'],
+                                 issue['strippedMainEventFilePathname'])
+                              )
+@@ -681,27 +697,16 @@ class StaticAnalysis(MachCommandBase):
+ 
+         if not os.path.exists(self.cov_path):
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'Missing Coverity in {}'.format(self.cov_path))
+             return 1
+ 
+         return 0
+ 
+-    def cov_is_file_in_source(self, abs_path, source):
+-        # We have as an input an absolute path for whom we verify if it's a symlink,
+-        # if so, we follow that symlink and we match it with elements from source.
+-        # If the match is done we return abs_path, otherwise None
+-        assert isinstance(source, list)
+-        if os.path.islink(abs_path):
+-            abs_path = os.path.realpath(abs_path)
+-        if abs_path in source:
+-            return abs_path
+-        return None
+-
+     def get_files_with_commands(self, source):
+         '''
+         Returns an array of dictionaries having file_path with build command
+         '''
+ 
+         compile_db = json.load(open(self._compile_db, 'r'))
+ 
+         commands_list = []

+ 52 - 0
mozilla-release/patches/1587079-72a1.patch

@@ -0,0 +1,52 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1572340989 0
+# Node ID fcf6bfc1c10d478b13802cebb1a74b001248c8d6
+# Parent  4d4a13d9004b3088f71215f5becdb496e8b6c967
+Bug 1587079 - disable structured log when using requests.get(...) for Coverity analysis. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D50442
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -583,17 +583,19 @@ class StaticAnalysis(MachCommandBase):
+ 
+         secret_name = 'project/relman/coverity'
+         secrets_url = '{}/secrets/v1/secret/{}'.format(get_root_url(True), secret_name)
+ 
+         self.log(logging.INFO, 'static-analysis', {},
+                  'Using symbol upload token from the secrets service: "{}"'.format(secrets_url))
+ 
+         import requests
++        self.log_manager.enable_unstructured()
+         res = requests.get(secrets_url)
++        self.log_manager.disable_unstructured()
+         res.raise_for_status()
+         secret = res.json()
+         cov_config = secret['secret'] if 'secret' in secret else None
+ 
+         if cov_config is None:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'Ill formatted secret for Coverity. Aborting analysis.')
+             return 1
+@@ -643,17 +645,19 @@ class StaticAnalysis(MachCommandBase):
+         '''
+         # Generate the coverity.conf and auth files
+         self.cov_auth_path = mozpath.join(self.cov_state_path, 'auth')
+         cov_setup_path = mozpath.join(self.cov_state_path, 'coverity.conf')
+         cov_conf = COVERITY_CONFIG % (self.cov_url, self.cov_port, self.cov_auth_path)
+ 
+         def download(artifact_url, target):
+             import requests
++            self.log_manager.enable_unstructured()
+             resp = requests.get(artifact_url, verify=False, stream=True)
++            self.log_manager.disable_unstructured()
+             resp.raise_for_status()
+ 
+             # Extract archive into destination
+             with tarfile.open(fileobj=io.BytesIO(resp.content)) as tar:
+                 tar.extractall(target)
+ 
+         download(self.cov_analysis_url, self.cov_state_path)
+ 

+ 38 - 0
mozilla-release/patches/1588283-72a1.patch

@@ -0,0 +1,38 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1572372928 0
+# Node ID 1ee997d2152a41b57da721821a6119b15f11c147
+# Parent  cfe88f7c9322c38fe65e2fdd52cfa862ca4b93e3
+Bug 1588283 - Incorrect build failure reported by coverity when using inline definitions. r=bastien
+
+Differential Revision: https://phabricator.services.mozilla.com/D50961
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -445,18 +445,24 @@ class StaticAnalysis(MachCommandBase):
+         commands_list = self.get_files_with_commands(source)
+         if len(commands_list) == 0:
+             self.log(logging.INFO, 'static-analysis', {},
+                      'There are no files that need to be analyzed.')
+             return 0
+ 
+         # For each element in commands_list run `cov-translate`
+         for element in commands_list:
++
++            def transform_cmd(cmd):
++                # Coverity Analysis has a problem translating definitions passed as:
++                # '-DSOME_DEF="ValueOfAString"', please see Bug 1588283.
++                return [re.sub(r'\'-D(.*)="(.*)"\'', r'-D\1="\2"', arg) for arg in cmd]
++
+             cmd = [self.cov_translate, '--dir', self.cov_idir_path] + \
+-                element['command'].split(' ')
++                transform_cmd(element['command'].split(' '))
+ 
+             if self.run_cov_command(cmd, element['directory']):
+                 return 1
+ 
+         if coverity_output_path is None:
+             cov_result = mozpath.join(self.cov_state_path, 'cov-results.json')
+         else:
+             cov_result = mozpath.join(coverity_output_path, 'cov-results.json')

+ 34 - 0
mozilla-release/patches/1590086-72a1.patch

@@ -0,0 +1,34 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1571666516 0
+# Node ID 562a3883426b733283d6d2094b10c0d0c2981a64
+# Parent  7546ad956bf9d7bf59dbe3d36c22279d82588a9b
+Bug 1590086 - Continue full Coverity analysis even if cov-run-desktop fails. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D49934
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -344,17 +344,20 @@ class StaticAnalysis(MachCommandBase):
+         rc = self.setup_coverity()
+         if rc != 0:
+             return rc
+ 
+         # First run cov-run-desktop --setup in order to setup the analysis env
+         # We need this in both cases, per patch analysis or full tree build
+         cmd = [self.cov_run_desktop, '--setup']
+         if self.run_cov_command(cmd, self.cov_path):
+-            return 1
++            # Avoiding a bug in Coverity where snapshot is not identified
++            # as beeing built with the current analysis binary.
++            if not full_build:
++                return 1
+ 
+         # Run cov-configure for clang, javascript and python
+         langs = ["clang", "javascript", "python"]
+         for lang in langs:
+             cmd = [self.cov_configure, '--{}'.format(lang)]
+ 
+             if self.run_cov_command(cmd):
+                 return 1

+ 37 - 0
mozilla-release/patches/1596456-72a1.patch

@@ -0,0 +1,37 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1574078728 0
+# Node ID a0e0c81e36237ce624a44897278ea842bb04ed0a
+# Parent  ce1b32236689a46bed461fe3ca79df58414394bc
+Bug 1596456 - unpack arguments as list to `_get_infer_args`. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D53398
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -816,21 +816,18 @@ class StaticAnalysis(MachCommandBase):
+                 return rc
+         rc = self._get_infer(verbose=verbose)
+         if rc != 0:
+             self.log(logging.WARNING, 'static-analysis', {},
+                      'This command is only available for linux64!')
+             return rc
+         # which checkers to use, and which folders to exclude
+         all_checkers, third_party_path, generated_path = self._get_infer_config()
+-        checkers, excludes = self._get_infer_args(
+-            checks=checks or all_checkers,
+-            third_party_path=third_party_path,
+-            generated_path=generated_path
+-        )
++        checkers, excludes = self._get_infer_args(checks or all_checkers, third_party_path,
++                                                  generated_path)
+         rc = rc or self._gradle(['clean'])  # clean so that we can recompile
+         # infer capture command
+         capture_cmd = [self._infer_path, 'capture'] + excludes + ['--']
+         rc = rc or self._gradle([task], infer_args=capture_cmd, verbose=verbose)
+         tmp_file, args = self._get_infer_source_args(java_sources)
+         # infer analyze command
+         analysis_cmd = [self._infer_path, 'analyze', '--keep-going'] +  \
+             checkers + args
+

+ 94 - 0
mozilla-release/patches/1600048-72a1.patch

@@ -0,0 +1,94 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1574954422 0
+# Node ID 51b7b6ca0a42409c0d6bd54a5dc0c88e206bc15d
+# Parent  709466b538c8a3913703b41019869666a3aa00e6
+Bug 1600048 - fix the call to `map_file_to_source` that prevented the json export for `clang-tidy` to work. r=bastien,marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D55110
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -83,21 +83,22 @@ class StaticAnalysisSubCommand(SubComman
+                             help='Print verbose output.'),
+         ]
+         for arg in args:
+             after = arg(after)
+         return after
+ 
+ 
+ class StaticAnalysisMonitor(object):
+-    def __init__(self, srcdir, objdir, clang_tidy_config, total):
++    def __init__(self, srcdir, objdir, clang_tidy_config, source, total):
+         self._total = total
+         self._processed = 0
+         self._current = None
+         self._srcdir = srcdir
++        self._source = source
+ 
+         self._clang_tidy_config = clang_tidy_config['clang_checkers']
+         # Transform the configuration to support Regex
+         for item in self._clang_tidy_config:
+             if item['name'] == '-*':
+                 continue
+             item['name'].replace('*', '.*')
+ 
+@@ -107,17 +108,17 @@ class StaticAnalysisMonitor(object):
+         )
+ 
+         self._warnings_database = WarningsDatabase()
+ 
+         def on_warning(warning):
+ 
+             # Output paths relative to repository root
+             warning['filename'] = mozpath.relpath(
+-                map_file_to_source(warning['filename']), self._srcdir)
++                map_file_to_source(warning['filename'], self._source), self._srcdir)
+ 
+             self._warnings_database.insert(warning)
+ 
+         self._warnings_collector = WarningsCollector(on_warning, objdir=objdir)
+ 
+     @property
+     def num_files(self):
+         return self._total
+@@ -140,17 +141,18 @@ class StaticAnalysisMonitor(object):
+         try:
+             warning = self._warnings_collector.process_line(line)
+         except Exception:
+             pass
+ 
+         if line.find('clang-tidy') != -1:
+             filename = line.split(' ')[-1]
+             if os.path.isfile(filename):
+-                self._current = mozpath.relpath(map_file_to_source(filename), self._srcdir)
++                self._current = mozpath.relpath(
++                    map_file_to_source(filename, self._source), self._srcdir)
+             else:
+                 self._current = None
+             self._processed = self._processed + 1
+             return (warning, False)
+         if warning is not None:
+             def get_check_config(checker_name):
+                 # get the matcher from self._clang_tidy_config that is the 'name' field
+                 for item in self._clang_tidy_config:
+@@ -279,17 +281,17 @@ class StaticAnalysis(MachCommandBase):
+         cwd = self.topobjdir
+         self._compilation_commands_path = self.topobjdir
+         if self._clang_tidy_config is None:
+             self._clang_tidy_config = self._get_clang_tidy_config()
+         args = self._get_clang_tidy_command(
+             checks=checks, header_filter=header_filter, sources=source, jobs=jobs, fix=fix)
+ 
+         monitor = StaticAnalysisMonitor(
+-            self.topsrcdir, self.topobjdir, self._clang_tidy_config, total)
++            self.topsrcdir, self.topobjdir, self._clang_tidy_config, source, total)
+ 
+         footer = StaticAnalysisFooter(self.log_manager.terminal, monitor)
+         with StaticAnalysisOutputManager(self.log_manager, monitor, footer) as output_manager:
+             rc = self.run_process(args=args, ensure_exit_code=False,
+                                   line_handler=output_manager.on_line, cwd=cwd)
+ 
+             self.log(logging.WARNING, 'warning_summary',
+                      {'count': len(monitor.warnings_db)},

+ 193 - 0
mozilla-release/patches/1600226-73a1.patch

@@ -0,0 +1,193 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1575296656 0
+# Node ID 57e49ba78675f01c8934e3384b4bddcf786b3114
+# Parent  496af84ff41d34caff18c426c0c0abd696fb1718
+Bug 1600226 - Optimize the way how we follow symlinks for static-analysis check. r=bastien,marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D55237
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -42,29 +42,23 @@ from mozbuild.controller.clobber import 
+ # in order to integrate into the futures ecosystem clang-format.
+ def run_one_clang_format_batch(args):
+     try:
+         subprocess.check_output(args)
+     except subprocess.CalledProcessError as e:
+         return e
+ 
+ 
+-def map_file_to_source(abs_path, source):
+-    # We have as an input an absolute path for whom we verify if it's a symlink,
+-    # if so, we follow that symlink and we match it with elements from source,
+-    # If the match is done we return abs_path, otherwise None.
+-    assert isinstance(source, (list, tuple))
++def build_repo_relative_path(abs_path, repo_path):
++    '''Build path relative to repository root'''
+ 
+     if os.path.islink(abs_path):
+         abs_path = mozpath.realpath(abs_path)
+ 
+-    # Look for abs_path in source
+-    if abs_path in source:
+-        return abs_path
+-    return None
++    return mozpath.relpath(abs_path, repo_path)
+ 
+ 
+ def prompt_bool(prompt, limit=5):
+     ''' Prompts the user with prompt and requires a boolean value. '''
+     from distutils.util import strtobool
+ 
+     for _ in range(limit):
+         try:
+@@ -83,22 +77,21 @@ class StaticAnalysisSubCommand(SubComman
+                             help='Print verbose output.'),
+         ]
+         for arg in args:
+             after = arg(after)
+         return after
+ 
+ 
+ class StaticAnalysisMonitor(object):
+-    def __init__(self, srcdir, objdir, clang_tidy_config, source, total):
++    def __init__(self, srcdir, objdir, clang_tidy_config, total):
+         self._total = total
+         self._processed = 0
+         self._current = None
+         self._srcdir = srcdir
+-        self._source = source
+ 
+         self._clang_tidy_config = clang_tidy_config['clang_checkers']
+         # Transform the configuration to support Regex
+         for item in self._clang_tidy_config:
+             if item['name'] == '-*':
+                 continue
+             item['name'].replace('*', '.*')
+ 
+@@ -106,19 +99,18 @@ class StaticAnalysisMonitor(object):
+             WarningsCollector,
+             WarningsDatabase,
+         )
+ 
+         self._warnings_database = WarningsDatabase()
+ 
+         def on_warning(warning):
+ 
+-            # Output paths relative to repository root
+-            warning['filename'] = mozpath.relpath(
+-                map_file_to_source(warning['filename'], self._source), self._srcdir)
++            # Output paths relative to repository root if the paths are under repo tree
++            warning['filename'] = build_repo_relative_path(warning['filename'], self._srcdir)
+ 
+             self._warnings_database.insert(warning)
+ 
+         self._warnings_collector = WarningsCollector(on_warning, objdir=objdir)
+ 
+     @property
+     def num_files(self):
+         return self._total
+@@ -141,18 +133,17 @@ class StaticAnalysisMonitor(object):
+         try:
+             warning = self._warnings_collector.process_line(line)
+         except Exception:
+             pass
+ 
+         if line.find('clang-tidy') != -1:
+             filename = line.split(' ')[-1]
+             if os.path.isfile(filename):
+-                self._current = mozpath.relpath(
+-                    map_file_to_source(filename, self._source), self._srcdir)
++                self._current = build_repo_relative_path(filename, self._srcdir)
+             else:
+                 self._current = None
+             self._processed = self._processed + 1
+             return (warning, False)
+         if warning is not None:
+             def get_check_config(checker_name):
+                 # get the matcher from self._clang_tidy_config that is the 'name' field
+                 for item in self._clang_tidy_config:
+@@ -281,17 +272,17 @@ class StaticAnalysis(MachCommandBase):
+         cwd = self.topobjdir
+         self._compilation_commands_path = self.topobjdir
+         if self._clang_tidy_config is None:
+             self._clang_tidy_config = self._get_clang_tidy_config()
+         args = self._get_clang_tidy_command(
+             checks=checks, header_filter=header_filter, sources=source, jobs=jobs, fix=fix)
+ 
+         monitor = StaticAnalysisMonitor(
+-            self.topsrcdir, self.topobjdir, self._clang_tidy_config, source, total)
++            self.topsrcdir, self.topobjdir, self._clang_tidy_config, total)
+ 
+         footer = StaticAnalysisFooter(self.log_manager.terminal, monitor)
+         with StaticAnalysisOutputManager(self.log_manager, monitor, footer) as output_manager:
+             rc = self.run_process(args=args, ensure_exit_code=False,
+                                   line_handler=output_manager.on_line, cwd=cwd)
+ 
+             self.log(logging.WARNING, 'warning_summary',
+                      {'count': len(monitor.warnings_db)},
+@@ -532,22 +523,16 @@ class StaticAnalysis(MachCommandBase):
+                         checker_name))
+             return 'medium'
+ 
+         return checkers[checker_name]['reliability']
+ 
+     def dump_cov_artifact(self, cov_results, source, output):
+         # Parse Coverity json into structured issues
+ 
+-        def relpath(path):
+-            '''Build path relative to repository root'''
+-            if path.startswith(self.topsrcdir):
+-                return os.path.relpath(path, self.topsrcdir)
+-            return path
+-
+         with open(cov_results) as f:
+             result = json.load(f)
+ 
+             # Parse the issues to a standard json format
+             issues_dict = {'files': {}}
+ 
+             files_list = issues_dict['files']
+ 
+@@ -569,35 +554,36 @@ class StaticAnalysis(MachCommandBase):
+                         'stateOnServer': issue['stateOnServer'],
+                         'stack': []
+                     }
+                 }
+ 
+                 # Embed all events into extra message
+                 for event in issue['events']:
+                     dict_issue['extra']['stack'].append(
+-                        {'file_path': relpath(event['strippedFilePathname']),
++                        {'file_path': build_repo_relative_path(event['strippedFilePathname'],
++                                                               self.topsrcdir),
+                          'line_number': event['lineNumber'],
+                          'path_type': event['eventTag'],
+                          'description': event['eventDescription']})
+ 
+                 return dict_issue
+ 
+             for issue in result['issues']:
+-                path = map_file_to_source(issue['strippedMainEventFilePathname'], source)
++                path = build_repo_relative_path(issue['strippedMainEventFilePathname'],
++                                                self.topsrcdir)
+                 if path is None:
+                     # Since we skip a result we should log it
+                     self.log(logging.INFO, 'static-analysis', {},
+                              'Skipping CID: {0} from file: {1} since it\'s not related '
+                              'with the current patch.'.format(
+                                 issue['stateOnServer']['cid'],
+                                 issue['strippedMainEventFilePathname'])
+                              )
+                     continue
+-                path = relpath(path)
+                 if path in files_list:
+                     files_list[path]['warnings'].append(build_element(issue))
+                 else:
+                     files_list[path] = {'warnings': [build_element(issue)]}
+ 
+             with open(output, 'w') as f:
+                 json.dump(issues_dict, f)
+ 

+ 31 - 0
mozilla-release/patches/1600558-73a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1575296703 0
+# Node ID 8c3e1cebc383dae1d7a1a89ae18a3b87a41be58c
+# Parent  835de1f7dbed47613a1b7f55d2baf0a781c7ca52
+Bug 1600558 - for `static-analysis` mutate the proper wildcards from clang-tidy to python. r=bastien,marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D55423
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -88,17 +88,17 @@ class StaticAnalysisMonitor(object):
+         self._current = None
+         self._srcdir = srcdir
+ 
+         self._clang_tidy_config = clang_tidy_config['clang_checkers']
+         # Transform the configuration to support Regex
+         for item in self._clang_tidy_config:
+             if item['name'] == '-*':
+                 continue
+-            item['name'].replace('*', '.*')
++            item['name'] = item['name'].replace('*', '.*')
+ 
+         from mozbuild.compilation.warnings import (
+             WarningsCollector,
+             WarningsDatabase,
+         )
+ 
+         self._warnings_database = WarningsDatabase()
+ 

+ 58 - 0
mozilla-release/patches/1605850-74a1.patch

@@ -0,0 +1,58 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1579688286 0
+# Node ID db6834b4020ad9c2515c0836d3ada2fd89e25da9
+# Parent  49c1f1232054a4504fe967e76bd82dc873a220d3
+Bug 1605850 - for `static-analysis autotest` don't allow running `--intree-tool` outside of automation. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D60646
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1031,17 +1031,18 @@ class StaticAnalysis(MachCommandBase):
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'autotest',
+                               'Run the auto-test suite in order to determine that'
+                               ' the analysis did not regress.')
+     @CommandArgument('--dump-results', '-d', default=False, action='store_true',
+                      help='Generate the baseline for the regression test. Based on'
+                      ' this baseline we will test future results.')
+     @CommandArgument('--intree-tool', '-i', default=False, action='store_true',
+-                     help='Use a pre-aquired in-tree clang-tidy package.')
++                     help='Use a pre-aquired in-tree clang-tidy package from the automation env.'
++                     ' This option is only valid on automation environments.')
+     @CommandArgument('checker_names', nargs='*', default=[],
+                      help='Checkers that are going to be auto-tested.')
+     def autotest(self, verbose=False, dump_results=False, intree_tool=False, checker_names=[]):
+         # If 'dump_results' is True than we just want to generate the issues files for each
+         # checker in particulat and thus 'force_download' becomes 'False' since we want to
+         # do this on a local trusted clang-tidy package.
+         self._set_log_level(verbose)
+         self._dump_results = dump_results
+@@ -1058,16 +1059,25 @@ class StaticAnalysis(MachCommandBase):
+         self.TOOLS_CHECKER_DIFF_FAILED = 6
+         self.TOOLS_CHECKER_NOT_FOUND = 7
+         self.TOOLS_CHECKER_FAILED_FILE = 8
+         self.TOOLS_CHECKER_LIST_EMPTY = 9
+         self.TOOLS_GRADLE_FAILED = 10
+ 
+         # Configure the tree or download clang-tidy package, depending on the option that we choose
+         if intree_tool:
++            if 'MOZ_AUTOMATION' not in os.environ:
++                self.log(logging.INFO, 'static-analysis', {},
++                         'The `autotest` with `--intree-tool` can only be ran in automation.')
++                return 1
++            if 'MOZ_FETCHES_DIR' not in os.environ:
++                self.log(logging.INFO, 'static-analysis', {},
++                         '`MOZ_FETCHES_DIR` is missing from the environment variables.')
++                return 1
++
+             _, config, _ = self._get_config_environment()
+             clang_tools_path = os.environ['MOZ_FETCHES_DIR']
+             self._clang_tidy_path = mozpath.join(
+                 clang_tools_path, "clang-tidy", "bin",
+                 "clang-tidy" + config.substs.get('BIN_SUFFIX', ''))
+             self._clang_format_path = mozpath.join(
+                 clang_tools_path, "clang-tidy", "bin",
+                 "clang-format" + config.substs.get('BIN_SUFFIX', ''))

+ 31 - 0
mozilla-release/patches/1605852-1-73a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Sylvestre Ledru <sledru@mozilla.com>
+# Date 1577973391 0
+# Node ID 4c33257156a2ee43c8880065b3dde1d2cf4294d6
+# Parent  5502afac25fb58a15d690ce4bfafc07d5f4d367e
+Bug 1605852 - Run clang-tidy with C++17 support r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D58190
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -947,17 +947,17 @@ class StaticAnalysis(MachCommandBase):
+     def _get_clang_tidy_command(self, checks, header_filter, sources, jobs, fix):
+ 
+         if checks == '-*':
+             checks = self._get_checks()
+ 
+         common_args = ['-clang-tidy-binary', self._clang_tidy_path,
+                        '-clang-apply-replacements-binary', self._clang_apply_replacements,
+                        '-checks=%s' % checks,
+-                       '-extra-arg=-DMOZ_CLANG_PLUGIN']
++                       '-extra-arg=-std=c++17', '-extra-arg=-DMOZ_CLANG_PLUGIN']
+ 
+         # Flag header-filter is passed in order to limit the diagnostic messages only
+         # to the specified header files. When no value is specified the default value
+         # is considered to be the source in order to limit the diagnostic message to
+         # the source files or folders.
+         common_args += ['-header-filter=%s' % (header_filter
+                                                if len(header_filter) else '|'.join(sources))]
+ 

+ 59 - 0
mozilla-release/patches/1605879-74a1.patch

@@ -0,0 +1,59 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1578565700 0
+# Node ID ca5a75b0c9dfd50762b011655b12f4dcba7051bc
+# Parent  69e940bccb4283fa19366aa6c860eebd9cad44a3
+Bug 1605879 - for `clang-tidy` based static-analysis pass the files for analysis in chuncks. r=sylvestre
+
+Since we have a limit of the number of arguments length that the shell can support we have to
+pass the files for the analysis to `run-clang-tidy.py` in chuncks, calculated in proportion
+to the number or logical cpu cores.
+
+Differential Revision: https://phabricator.services.mozilla.com/D58971
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -268,26 +268,38 @@ class StaticAnalysis(MachCommandBase):
+                      "There are no files eligible for analysis. Please note that 'header' files "
+                      "cannot be used for analysis since they do not consist compilation units.")
+             return 0
+ 
+         cwd = self.topobjdir
+         self._compilation_commands_path = self.topobjdir
+         if self._clang_tidy_config is None:
+             self._clang_tidy_config = self._get_clang_tidy_config()
+-        args = self._get_clang_tidy_command(
+-            checks=checks, header_filter=header_filter, sources=source, jobs=jobs, fix=fix)
+ 
+         monitor = StaticAnalysisMonitor(
+             self.topsrcdir, self.topobjdir, self._clang_tidy_config, total)
+ 
+         footer = StaticAnalysisFooter(self.log_manager.terminal, monitor)
++
+         with StaticAnalysisOutputManager(self.log_manager, monitor, footer) as output_manager:
+-            rc = self.run_process(args=args, ensure_exit_code=False,
+-                                  line_handler=output_manager.on_line, cwd=cwd)
++            import math
++            import multiprocessing
++            batch_size = int(math.ceil(float(len(source)) / multiprocessing.cpu_count()))
++            for i in range(0, len(source), batch_size):
++                args = self._get_clang_tidy_command(
++                    checks=checks,
++                    header_filter=header_filter,
++                    sources=source[i:(i + batch_size)],
++                    jobs=jobs,
++                    fix=fix)
++                rc = self.run_process(
++                    args=args,
++                    ensure_exit_code=False,
++                    line_handler=output_manager.on_line,
++                    cwd=cwd)
+ 
+             self.log(logging.WARNING, 'warning_summary',
+                      {'count': len(monitor.warnings_db)},
+                      '{count} warnings present.')
+ 
+             # Write output file
+             if output is not None:
+                 output_manager.write(output, format)

+ 91 - 0
mozilla-release/patches/1606475-80a1.patch

@@ -0,0 +1,91 @@
+# HG changeset patch
+# User Hamzah <hamzah18051@iiitd.ac.in>
+# Date 1595247148 0
+# Node ID c43b0e4eb0dbd6f09a5d24b1000ce3439e573b8b
+# Parent  86ccf356d3601bc92fc638855f0af37a3b38c696
+Bug 1606475 - Move mach clang-format to Python 3 r=andi
+
+Manually tested various combination of commands for `./mach clang-format`. It works fine on both py2 as well as py3
+
+Differential Revision: https://phabricator.services.mozilla.com/D79330
+
+diff --git a/mach b/mach
+--- a/mach
++++ b/mach
+@@ -10,17 +10,16 @@
+ # Embeds a shell script inside a Python triple quote. This pattern is valid
+ # shell because `''':'`, `':'` and `:` are all equivalent, and `:` is a no-op.
+ ''':'
+ py2commands="
+     android
+     awsy-test
+     browsertime
+     check-spidermonkey
+-    clang-format
+     cramtest
+     crashtest
+     devtools-css-db
+     firefox-ui-functional
+     geckodriver
+     geckodriver-test
+     geckoview-junit
+     gradle
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -14,16 +14,18 @@ import re
+ import sys
+ import subprocess
+ import shutil
+ import tarfile
+ import tempfile
+ import xml.etree.ElementTree as ET
+ import yaml
+ 
++import six
++
+ from mach.decorators import (
+     CommandArgument,
+     CommandProvider,
+     Command,
+     SubCommand,
+ )
+ 
+ from mach.main import Mach
+@@ -2330,16 +2332,17 @@ class StaticAnalysis(MachCommandBase):
+                         if e.output:
+                             # Replace the temp path by the path relative to the repository to
+                             # display a valid patch
+                             relative_path = os.path.relpath(original_path, self.topsrcdir)
+                             # We must modify the paths in order to be compatible with the
+                             # `diff` format.
+                             original_path_diff = os.path.join("a", relative_path)
+                             target_path_diff = os.path.join("b", relative_path)
++                            e.output = e.output.decode('utf-8')
+                             patch = e.output.replace("+++ {}".format(target_file),
+                                                      "+++ {}".format(target_path_diff)).replace(
+                                                          "-- {}".format(original_path),
+                                                          "-- {}".format(original_path_diff))
+                             patches[original_path] = patch
+ 
+             if output_format == 'json':
+                 output = json.dumps(patches, indent=4)
+@@ -2393,17 +2396,17 @@ class StaticAnalysis(MachCommandBase):
+         return 0
+ 
+     def _parse_xml_output(self, path, clang_output):
+         '''
+         Parse the clang-format XML output to convert it in a JSON compatible
+         list of patches, and calculates line level informations from the
+         character level provided changes.
+         '''
+-        content = open(path, 'r').read().decode('utf-8')
++        content = six.ensure_str(open(path, 'r').read())
+ 
+         def _nb_of_lines(start, end):
+             return len(content[start:end].splitlines())
+ 
+         def _build(replacement):
+             offset = int(replacement.attrib['offset'])
+             length = int(replacement.attrib['length'])
+             last_line = content.rfind('\n', 0, offset)

+ 322 - 0
mozilla-release/patches/1606541-1-73a1.patch

@@ -0,0 +1,322 @@
+# HG changeset patch
+# User Sylvestre Ledru <sledru@mozilla.com>
+# Date 1577890670 0
+# Node ID c55854a9e510ff1d58582aa9f6dbd4a6191b6be1
+# Parent  1741c76377f8c47adf3d38123be6842eb651a387
+Bug 1606541 - Add "error:" in case of error to facilitate the search and be more consistent r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D58484
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -58,17 +58,17 @@ def build_repo_relative_path(abs_path, r
+ 
+ def prompt_bool(prompt, limit=5):
+     ''' Prompts the user with prompt and requires a boolean value. '''
+     from distutils.util import strtobool
+ 
+     for _ in range(limit):
+         try:
+             return strtobool(raw_input(prompt + "[Y/N]\n"))
+-        except ValueError:
++        except ValueERROR:
+             print("ERROR! Please enter a valid option! Please use any of the following:"
+                   " Y, N, True, False, 1, 0")
+     return False
+ 
+ 
+ class StaticAnalysisSubCommand(SubCommand):
+     def __call__(self, func):
+         after = SubCommand.__call__(self, func)
+@@ -228,17 +228,17 @@ class StaticAnalysis(MachCommandBase):
+         self.log_manager.enable_all_structured_loggers()
+ 
+         rc = self._get_clang_tools(verbose=verbose)
+         if rc != 0:
+             return rc
+ 
+         if self._is_version_eligible() is False:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     "You're using an old version of clang-format binary."
++                     "ERROR: You're using an old version of clang-format binary."
+                      " Please update to a more recent one by running: './mach bootstrap'")
+             return 1
+ 
+         rc = self._build_compile_db(verbose=verbose)
+         rc = rc or self._build_export(jobs=jobs, verbose=verbose)
+         if rc != 0:
+             return rc
+ 
+@@ -336,17 +336,17 @@ class StaticAnalysis(MachCommandBase):
+         if outgoing:
+             repo = get_repository_object(self.topsrcdir)
+             files = repo.get_outgoing_files()
+             source = map(os.path.abspath, files)
+ 
+         # Verify that we have source files or we are dealing with a full-build
+         if len(source) == 0 and not full_build:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     'There are no files that coverity can use to scan.')
++                     'ERROR: There are no files that coverity can use to scan.')
+             return 0
+ 
+         # Load the configuration file for coverity static-analysis
+         # For the moment we store only the reliability index for each checker
+         # as the rest is managed on the https://github.com/mozilla/release-services side.
+         self._cov_config = self._get_cov_config()
+ 
+         rc = self.setup_coverity()
+@@ -490,17 +490,18 @@ class StaticAnalysis(MachCommandBase):
+             # We want to run it in topsrcdir
+             path = self.topsrcdir
+ 
+         self.log(logging.INFO, 'static-analysis', {}, 'Running '+' '.join(cmd))
+ 
+         rc = self.run_process(args=cmd, cwd=path, pass_thru=True)
+ 
+         if rc != 0:
+-            self.log(logging.ERROR, 'static-analysis', {}, 'Running ' + ' '.join(cmd) + ' failed!')
++            self.log(logging.ERROR, 'static-analysis', {},
++                     'ERROR: Running ' + ' '.join(cmd) + ' failed!')
+             return rc
+         return 0
+ 
+     def get_reliability_index_for_cov_checker(self, checker_name):
+         if self._cov_config is None:
+             self.log(logging.INFO, 'static-analysis', {}, 'Coverity config file not found, '
+                      'using default-value \'reliablity\' = medium. for checker {}'.format(
+                         checker_name))
+@@ -601,17 +602,17 @@ class StaticAnalysis(MachCommandBase):
+         res = requests.get(secrets_url)
+         self.log_manager.disable_unstructured()
+         res.raise_for_status()
+         secret = res.json()
+         cov_config = secret['secret'] if 'secret' in secret else None
+ 
+         if cov_config is None:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     'Ill formatted secret for Coverity. Aborting analysis.')
++                     'ERROR: Ill formatted secret for Coverity. Aborting analysis.')
+             return 1
+ 
+         self.cov_analysis_url = cov_config.get('package_url')
+         self.cov_package_name = cov_config.get('package_name')
+         self.cov_url = cov_config.get('server_url')
+         self.cov_server_ssl = cov_config.get('server_ssl', True)
+         # In case we don't have a port in the secret we use the default one,
+         # for a default coverity deployment.
+@@ -624,17 +625,18 @@ class StaticAnalysis(MachCommandBase):
+         self.cov_stream = cov_config.get('stream', False)
+ 
+         return 0
+ 
+     def download_coverity(self):
+         if self.cov_url is None or self.cov_port is None or \
+                 self.cov_analysis_url is None or \
+                 self.cov_auth is None:
+-            self.log(logging.ERROR, 'static-analysis', {}, 'Missing Coverity secret on try job!')
++            self.log(logging.ERROR, 'static-analysis', {},
++                     'ERROR: Missing Coverity secret on try job!')
+             return 1
+ 
+         COVERITY_CONFIG = '''
+         {
+             "type": "Coverity configuration",
+             "format_version": 1,
+             "settings": {
+             "server": {
+@@ -708,17 +710,17 @@ class StaticAnalysis(MachCommandBase):
+         self.cov_configure = mozpath.join(self.cov_path, 'bin', 'cov-configure')
+         self.cov_work_path = mozpath.join(self.cov_state_path, 'data-coverity')
+         self.cov_idir_path = mozpath.join(self.cov_work_path, self.cov_package_ver, 'idir')
+         self.cov_lic_path = mozpath.join(
+             self.cov_work_path, self.cov_package_ver, 'lic', self.cov_lic_name)
+ 
+         if not os.path.exists(self.cov_path):
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     'Missing Coverity in {}'.format(self.cov_path))
++                     'ERROR: Missing Coverity in {}'.format(self.cov_path))
+             return 1
+ 
+         return 0
+ 
+     def get_files_with_commands(self, source):
+         '''
+         Returns an array of dictionaries having file_path with build command
+         '''
+@@ -892,60 +894,59 @@ class StaticAnalysis(MachCommandBase):
+         return checkers, excludes
+ 
+     def _get_clang_tidy_config(self):
+         try:
+             file_handler = open(mozpath.join(self.topsrcdir, "tools", "clang-tidy", "config.yaml"))
+             config = yaml.safe_load(file_handler)
+         except Exception:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     'Looks like config.yaml is not valid, we are going to use default'
++                     'ERROR: Looks like config.yaml is not valid, we are going to use default'
+                      ' values for the rest of the analysis for clang-tidy.')
+             return None
+         return config
+ 
+     def _get_cov_config(self):
+         try:
+             file_handler = open(mozpath.join(self.topsrcdir, "tools", "coverity", "config.yaml"))
+             config = yaml.safe_load(file_handler)
+         except Exception:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     'Looks like config.yaml is not valid, we are going to use default'
++                     'ERROR: Looks like config.yaml is not valid, we are going to use default'
+                      ' values for the rest of the analysis for coverity.')
+             return None
+         return config
+ 
+     def _is_version_eligible(self):
+         # make sure that we've cached self._clang_tidy_config
+         if self._clang_tidy_config is None:
+             self._clang_tidy_config = self._get_clang_tidy_config()
+ 
+         version = None
+         if 'package_version' in self._clang_tidy_config:
+             version = self._clang_tidy_config['package_version']
+         else:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     "Unable to find 'package_version' in the config.yml")
++                     "ERROR: Unable to find 'package_version' in the config.yml")
+             return False
+ 
+         # Because the fact that we ship together clang-tidy and clang-format
+         # we are sure that these two will always share the same version.
+         # Thus in order to determine that the version is compatible we only
+         # need to check one of them, going with clang-format
+         cmd = [self._clang_format_path, '--version']
+         try:
+             output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode('utf-8')
+             version_string = 'clang-format version ' + version
+             if output.startswith(version_string):
+                 return True
+         except subprocess.CalledProcessError as e:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     "Error determining the version clang-tidy/format binary, please see the "
+-                     "attached exception: \n{}".format(e.output))
+-
++                     "ERROR: Error determining the version clang-tidy/format binary, "
++                     "please see the attached exception: \n{}".format(e.output))
+         return False
+ 
+     def _get_clang_tidy_command(self, checks, header_filter, sources, jobs, fix):
+ 
+         if checks == '-*':
+             checks = self._get_checks()
+ 
+         common_args = ['-clang-tidy-binary', self._clang_tidy_path,
+@@ -1068,29 +1069,29 @@ class StaticAnalysis(MachCommandBase):
+ 
+             # Ensure that clang-tidy is present
+             rc = not os.path.exists(self._clang_tidy_path)
+         else:
+             rc = self._get_clang_tools(force=force_download, verbose=verbose)
+ 
+         if rc != 0:
+             self.log(logging.ERROR, 'ERROR: static-analysis', {},
+-                     'clang-tidy unable to locate package.')
++                     'ERROR: clang-tidy unable to locate package.')
+             return self.TOOLS_FAILED_DOWNLOAD
+ 
+         self._clang_tidy_base_path = mozpath.join(self.topsrcdir, "tools", "clang-tidy")
+ 
+         # For each checker run it
+         self._clang_tidy_config = self._get_clang_tidy_config()
+         platform, _ = self.platform
+ 
+         if platform not in self._clang_tidy_config['platforms']:
+             self.log(
+                 logging.ERROR, 'static-analysis', {},
+-                "RUNNING: clang-tidy autotest for platform {} not supported.".format(
++                "ERROR: RUNNING: clang-tidy autotest for platform {} not supported.".format(
+                     platform)
+                 )
+             return self.TOOLS_UNSUPORTED_PLATFORM
+ 
+         import concurrent.futures
+         import multiprocessing
+ 
+         max_workers = multiprocessing.cpu_count()
+@@ -1243,17 +1244,18 @@ class StaticAnalysis(MachCommandBase):
+             found = all([element_base in issues for element_base in baseline_issues])
+ 
+             if not found:
+                 failed_checks.append(checker)
+                 failed_checks_baseline.append(baseline_issues)
+ 
+         if len(failed_checks) > 0:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     'The following check(s) failed for bulk analysis: ' + ' '.join(failed_checks))
++                     'ERROR: The following check(s) failed for bulk analysis: ' +
++                     ' '.join(failed_checks))
+ 
+             for failed_check, baseline_issue in zip(failed_checks, failed_checks_baseline):
+                 print('\tChecker {0} expect following results: \n\t\t{1}'.format(
+                     failed_check, baseline_issue))
+ 
+             print('This is the output generated by clang-tidy for the bulk build:\n{}'.format(
+                 clang_output))
+             return self.TOOLS_CHECKER_DIFF_FAILED
+@@ -1285,17 +1287,17 @@ class StaticAnalysis(MachCommandBase):
+         # it being installed
+         if self.platform[0] == 'linux64':
+             rc = self._check_for_java()
+             if rc != 0:
+                 return 1
+             rc = self._get_infer(force=force_download, verbose=verbose, intree_tool=intree_tool)
+             if rc != 0:
+                 self.log(logging.ERROR, 'ERROR: static-analysis', {},
+-                         'infer unable to locate package.')
++                         'ERROR: infer unable to locate package.')
+                 return self.TOOLS_FAILED_DOWNLOAD
+             self.__infer_tool = mozpath.join(self.topsrcdir, 'tools', 'infer')
+             self.__infer_test_folder = mozpath.join(self.__infer_tool, 'test')
+ 
+             import concurrent.futures
+             import multiprocessing
+             max_workers = multiprocessing.cpu_count()
+             self.log(logging.INFO, 'static-analysis', {},
+@@ -1560,17 +1562,17 @@ class StaticAnalysis(MachCommandBase):
+                 return 1
+         else:
+             rc = self._get_clang_tools(verbose=verbose)
+             if rc != 0:
+                 return rc
+ 
+         if self._is_version_eligible() is False:
+             self.log(logging.ERROR, 'static-analysis', {},
+-                     "You're using an old version of clang-format binary."
++                     "ERROR: You're using an old version of clang-format binary."
+                      " Please update to a more recent one by running: './mach bootstrap'")
+             return 1
+ 
+         if path is None:
+             return self._run_clang_format_diff(self._clang_format_diff,
+                                                self._clang_format_path, commit, output)
+ 
+         if assume_filename:
+@@ -1742,17 +1744,17 @@ class StaticAnalysis(MachCommandBase):
+ 
+             if clobber.clobber_needed():
+                 choice = prompt_bool(
+                     "Configuration has changed and Clobber is needed. "
+                     "Do you want to proceed?"
+                 )
+                 if not choice:
+                     self.log(logging.ERROR, 'static-analysis', {},
+-                             "Without Clobber we cannot continue execution!")
++                             "ERROR: Without Clobber we cannot continue execution!")
+                     return (1, None, None)
+                 os.environ["AUTOCLOBBER"] = "1"
+ 
+             rc = builder.configure()
+             if rc != 0:
+                 return (rc, config, ran_configure)
+             ran_configure = True
+             try:

+ 31 - 0
mozilla-release/patches/1606541-2-73a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Sylvestre Ledru <sledru@mozilla.com>
+# Date 1577905574 0
+# Node ID a6f5922d1fa81f77897c0089da1ec5403971fb04
+# Parent  09ea07aeca2d536866eefe3da34c1b7ef482b28a
+Bug 1606541 - Fix a too agressive replace r=emilio
+
+Differential Revision: https://phabricator.services.mozilla.com/D58490
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -58,17 +58,17 @@ def build_repo_relative_path(abs_path, r
+ 
+ def prompt_bool(prompt, limit=5):
+     ''' Prompts the user with prompt and requires a boolean value. '''
+     from distutils.util import strtobool
+ 
+     for _ in range(limit):
+         try:
+             return strtobool(raw_input(prompt + "[Y/N]\n"))
+-        except ValueERROR:
++        except ValueError:
+             print("ERROR! Please enter a valid option! Please use any of the following:"
+                   " Y, N, True, False, 1, 0")
+     return False
+ 
+ 
+ class StaticAnalysisSubCommand(SubCommand):
+     def __call__(self, func):
+         after = SubCommand.__call__(self, func)

+ 32 - 0
mozilla-release/patches/1619956-76a1.patch

@@ -0,0 +1,32 @@
+# HG changeset patch
+# User nemesisBR <bobyrobert3@gmail.com>
+# Date 1583835978 0
+# Node ID d9225cc36d335e201d7a41a1e57e8a7db79f63ad
+# Parent  e76fcbeabe615a38674e04d1e7e5ff8808a9bd1e
+Bug 1619956 : Added link to documentation without adding a new command. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D65934
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -174,16 +174,19 @@ class StaticAnalysis(MachCommandBase):
+ 
+     _clang_tidy_config = None
+     _cov_config = None
+ 
+     @Command('static-analysis', category='testing',
+              description='Run C++ static analysis checks')
+     def static_analysis(self):
+         # If no arguments are provided, just print a help message.
++        """Detailed documentation:
++        https://firefox-source-docs.mozilla.org/code-quality/static-analysis.html
++        """
+         mach = Mach(os.getcwd())
+ 
+         def populate_context(context, key=None):
+             context.topdir = self.topsrcdir
+ 
+         mach.populate_context_handler = populate_context
+         mach.run(['static-analysis', '--help'])
+ 

+ 222 - 0
mozilla-release/patches/1626190-76a1.patch

@@ -0,0 +1,222 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1585666921 0
+# Node ID b97ac83353354c812be558f8fbe2674f215f2d8b
+# Parent  421c5a30a5dbaa620d056e5bfc75bc51e63580e7
+Bug 1626190 - Add `mach` command that checks syntax for C/C++ files. r=bastien
+
+This was designed to be used outside of the `unified build system` in order to keep
+individual files syntax sane and to use the `compile_commands.json` outside of the
+`unified build` environment.
+
+Differential Revision: https://phabricator.services.mozilla.com/D68968
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1,16 +1,18 @@
+ # 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 absolute_import, print_function, unicode_literals
+ 
++import concurrent.futures
+ import io
+ import logging
+ import json
++import multiprocessing
+ import ntpath
+ import os
+ import re
+ import sys
+ import subprocess
+ import shutil
+ import tarfile
+ import tempfile
+@@ -167,16 +169,19 @@ class StaticAnalysisMonitor(object):
+ class StaticAnalysis(MachCommandBase):
+     """Utilities for running C++ static analysis checks and format."""
+ 
+     # List of file extension to consider (should start with dot)
+     _format_include_extensions = ('.cpp', '.c', '.cc', '.h', '.m', '.mm')
+     # File contaning all paths to exclude from formatting
+     _format_ignore_file = '.clang-format-ignore'
+ 
++    # List of file extension to consider (should start with dot)
++    _check_syntax_include_extensions = ('.cpp', '.c', '.cc', '.cxx')
++
+     _clang_tidy_config = None
+     _cov_config = None
+ 
+     @Command('static-analysis', category='testing',
+              description='Run C++ static analysis checks')
+     def static_analysis(self):
+         # If no arguments are provided, just print a help message.
+         """Detailed documentation:
+@@ -279,17 +284,16 @@ class StaticAnalysis(MachCommandBase):
+ 
+         monitor = StaticAnalysisMonitor(
+             self.topsrcdir, self.topobjdir, self._clang_tidy_config, total)
+ 
+         footer = StaticAnalysisFooter(self.log_manager.terminal, monitor)
+ 
+         with StaticAnalysisOutputManager(self.log_manager, monitor, footer) as output_manager:
+             import math
+-            import multiprocessing
+             batch_size = int(math.ceil(float(len(source)) / multiprocessing.cpu_count()))
+             for i in range(0, len(source), batch_size):
+                 args = self._get_clang_tidy_command(
+                     checks=checks,
+                     header_filter=header_filter,
+                     sources=source[i:(i + batch_size)],
+                     jobs=jobs,
+                     fix=fix)
+@@ -1111,19 +1115,16 @@ class StaticAnalysis(MachCommandBase):
+         if platform not in self._clang_tidy_config['platforms']:
+             self.log(
+                 logging.ERROR, 'static-analysis', {},
+                 "ERROR: RUNNING: clang-tidy autotest for platform {} not supported.".format(
+                     platform)
+                 )
+             return self.TOOLS_UNSUPORTED_PLATFORM
+ 
+-        import concurrent.futures
+-        import multiprocessing
+-
+         max_workers = multiprocessing.cpu_count()
+ 
+         self.log(logging.INFO, 'static-analysis', {},
+                  "RUNNING: clang-tidy autotest for platform {0} with {1} workers.".format(
+                      platform, max_workers))
+ 
+         # List all available checkers
+         cmd = [self._clang_tidy_path, '-list-checks', '-checks=*']
+@@ -1317,18 +1318,16 @@ class StaticAnalysis(MachCommandBase):
+             rc = self._get_infer(force=force_download, verbose=verbose, intree_tool=intree_tool)
+             if rc != 0:
+                 self.log(logging.ERROR, 'ERROR: static-analysis', {},
+                          'ERROR: infer unable to locate package.')
+                 return self.TOOLS_FAILED_DOWNLOAD
+             self.__infer_tool = mozpath.join(self.topsrcdir, 'tools', 'infer')
+             self.__infer_test_folder = mozpath.join(self.__infer_tool, 'test')
+ 
+-            import concurrent.futures
+-            import multiprocessing
+             max_workers = multiprocessing.cpu_count()
+             self.log(logging.INFO, 'static-analysis', {},
+                      "RUNNING: infer autotest for platform {0} with {1} workers.".format(
+                          self.platform[0], max_workers))
+             # clean previous autotest if it exists
+             rc = self._gradle(['autotest:clean'], autotest=True)
+             if rc != 0:
+                 return rc
+@@ -1516,16 +1515,90 @@ class StaticAnalysis(MachCommandBase):
+ 
+         process = subprocess.Popen(args, stdin=subprocess.PIPE)
+         with open(path, 'r') as fin:
+             process.stdin.write(fin.read())
+             process.stdin.close()
+             process.wait()
+             return process.returncode
+ 
++    @StaticAnalysisSubCommand('static-analysis', 'check-syntax',
++                              'Run the check-syntax for C/C++ files based on '
++                              '`compile_commands.json`')
++    @CommandArgument('source', nargs='*',
++                     help='Source files to be compiled checked (regex on path).')
++    def check_syntax(self, source, verbose=False):
++        # Verify that we have a valid `source`
++        if len(source) == 0:
++            self.log(logging.ERROR, 'static-analysis', {},
++                     'ERROR: Specify files that need to be syntax checked.')
++            return
++
++        self._set_log_level(verbose)
++        self.log_manager.enable_all_structured_loggers()
++
++        rc = self._build_compile_db(verbose=verbose)
++        if rc != 0:
++            self.log(logging.ERROR, 'static-analysis', {},
++                     'ERROR: Unable to build the `compile_commands.json`.')
++            return rc
++        rc = self._build_export(jobs=2, verbose=verbose)
++
++        if rc != 0:
++            self.log(logging.ERROR, 'static-analysis', {},
++                     'ERROR: Unable to build export.')
++            return rc
++
++        # Build the list with all files from source
++        path_list = self._generate_path_list(source)
++
++        compile_db = json.load(open(self._compile_db, 'r'))
++
++        if compile_db is None:
++            self.log(logging.ERROR, 'static-analysis', {},
++                     'ERROR: Loading {}'.format(self._compile_db))
++            return 1
++
++        commands = []
++
++        compile_dict = {entry['file']: entry['command']
++                        for entry in compile_db}
++        # Begin the compile check for each file
++        for file in path_list:
++            # It must be a C/C++ file
++            ext = mozpath.splitext(file)[-1]
++
++            if ext.lower() not in self._check_syntax_include_extensions:
++                self.log(logging.INFO, 'static-analysis',
++                         {}, 'Skipping {}'.format(file))
++                continue
++            file_with_abspath = mozpath.join(self.topsrcdir, file)
++            # Found for a file that we are looking
++
++            entry = compile_dict.get(file_with_abspath, None)
++            if entry:
++                command = entry.split(' ')
++                # Verify to see if we are dealing with an unified build
++                if 'Unified_' in command[-1]:
++                    # Translate the unified `TU` to per file basis TU
++                    command[-1] = file_with_abspath
++
++                # We want syntax-only
++                command.append('-fsyntax-only')
++                commands.append(command)
++
++        max_workers = multiprocessing.cpu_count()
++
++        with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
++            futures = []
++            for command in commands:
++                futures.append(executor.submit(self.run_process, args=command,
++                                               cwd=self.topsrcdir, pass_thru=True,
++                                               ensure_exit_code=False))
++
+     @Command('clang-format',  category='misc', description='Run clang-format on current changes')
+     @CommandArgument('--show', '-s', action='store_const', const='stdout', dest='output_path',
+                      help='Show diff output on stdout instead of applying changes')
+     @CommandArgument('--assume-filename', '-a', nargs=1, default=None,
+                      help='This option is usually used in the context of hg-formatsource.'
+                           'When reading from stdin, clang-format assumes this '
+                           'filename to look for a style config file (with '
+                           '-style=file) and to determine the language. When '
+@@ -2180,18 +2253,16 @@ class StaticAnalysis(MachCommandBase):
+ 
+             # Output to specified file or stdout
+             print(output, file=output_file)
+ 
+             shutil.rmtree(tmpdir)
+             return 0
+ 
+         # Run clang-format in parallel trying to saturate all of the available cores.
+-        import concurrent.futures
+-        import multiprocessing
+         import math
+ 
+         max_workers = multiprocessing.cpu_count()
+ 
+         # To maximize CPU usage when there are few items to handle,
+         # underestimate the number of items per batch, then dispatch
+         # outstanding items across workers. Per definition, each worker will
+         # handle at most one outstanding item.

+ 68 - 0
mozilla-release/patches/1626640-76a1.patch

@@ -0,0 +1,68 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1585759568 0
+# Node ID 39875369fe764785aeebec11e07aa393deb7dca3
+# Parent  fc06c972d836bffea3b608883641c5b50f736ac3
+Bug 1626640 - For modules that are compatible with the non unified build environment stop using the unified files for Coverity Analysis. r=marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D69211
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -470,26 +470,36 @@ class StaticAnalysis(MachCommandBase):
+             return rc
+ 
+         commands_list = self.get_files_with_commands(source)
+         if len(commands_list) == 0:
+             self.log(logging.INFO, 'static-analysis', {},
+                      'There are no files that need to be analyzed.')
+             return 0
+ 
++        if len(self.cov_non_unified_paths):
++            self.cov_non_unified_paths = [mozpath.join(
++                self.topsrcdir, path) for path in self.cov_non_unified_paths]
++
+         # For each element in commands_list run `cov-translate`
+         for element in commands_list:
+ 
+             def transform_cmd(cmd):
+                 # Coverity Analysis has a problem translating definitions passed as:
+                 # '-DSOME_DEF="ValueOfAString"', please see Bug 1588283.
+                 return [re.sub(r'\'-D(.*)="(.*)"\'', r'-D\1="\2"', arg) for arg in cmd]
+ 
++            build_command = element['command'].split(' ')
++            # For modules that are compatible with the non unified build environment
++            # use the the implicit file for analysis in the detriment of the unified
++            if any(element['file'].startswith(path) for path in self.cov_non_unified_paths):
++                build_command[-1] = element['file']
++
+             cmd = [self.cov_translate, '--dir', self.cov_idir_path] + \
+-                transform_cmd(element['command'].split(' '))
++                transform_cmd(build_command)
+ 
+             if self.run_cov_command(cmd, element['directory']):
+                 return 1
+ 
+         if coverity_output_path is None:
+             cov_result = mozpath.join(self.cov_state_path, 'cov-results.json')
+         else:
+             cov_result = mozpath.join(coverity_output_path, 'cov-results.json')
+@@ -637,16 +647,17 @@ class StaticAnalysis(MachCommandBase):
+         # for a default coverity deployment.
+         self.cov_port = cov_config.get('server_port', 8443)
+         self.cov_auth = cov_config.get('auth_key')
+         self.cov_package_ver = cov_config.get('package_ver')
+         self.cov_lic_name = cov_config.get('lic_name')
+         self.cov_capture_search = cov_config.get('fs_capture_search', None)
+         self.cov_full_stack = cov_config.get('full_stack', False)
+         self.cov_stream = cov_config.get('stream', False)
++        self.cov_non_unified_paths = cov_config.get('non_unified', [])
+ 
+         return 0
+ 
+     def download_coverity(self):
+         if self.cov_url is None or self.cov_port is None or \
+                 self.cov_analysis_url is None or \
+                 self.cov_auth is None:
+             self.log(logging.ERROR, 'static-analysis', {},

+ 103 - 0
mozilla-release/patches/1634050-77a1.patch

@@ -0,0 +1,103 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1588265186 0
+# Node ID 8e4a846c1c5bdb6f5c1d871b4d0e826a2a09b79e
+# Parent  1e7451bc8d3e7da32dc32f5b5b2cea707792cd0b
+Bug 1634050 - [clang-format] When analyzing files outside of the tree take along the appropriate `.clang-format` file as well. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D73053
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -2181,16 +2181,50 @@ class StaticAnalysis(MachCommandBase):
+ 
+         process = subprocess.Popen(args, stdin=subprocess.PIPE)
+         with open(paths[0], 'r') as fin:
+             process.stdin.write(fin.read())
+             process.stdin.close()
+             process.wait()
+             return process.returncode
+ 
++    def _get_clang_format_cfg(self, current_dir):
++        clang_format_cfg_path = mozpath.join(current_dir, '.clang-format')
++
++        if os.path.exists(clang_format_cfg_path):
++            # Return found path for .clang-format
++            return clang_format_cfg_path
++
++        if current_dir != self.topsrcdir:
++            # Go to parent directory
++            return self._get_clang_format_cfg(os.path.split(current_dir)[0])
++        # We have reached self.topsrcdir so return None
++        return None
++
++    def _copy_clang_format_for_show_diff(self, current_dir, cached_clang_format_cfg, tmpdir):
++        # Lookup for .clang-format first in cache
++        clang_format_cfg = cached_clang_format_cfg.get(current_dir, None)
++
++        if clang_format_cfg is None:
++            # Go through top directories
++            clang_format_cfg = self._get_clang_format_cfg(current_dir)
++
++            # This is unlikely to happen since we must have .clang-format from
++            # self.topsrcdir but in any case we should handle a potential error
++            if clang_format_cfg is None:
++                print("Cannot find corresponding .clang-format.")
++                return 1
++
++            # Cache clang_format_cfg for potential later usage
++            cached_clang_format_cfg[current_dir] = clang_format_cfg
++
++        # Copy .clang-format to the tmp dir where the formatted file is copied
++        shutil.copy(clang_format_cfg, tmpdir)
++        return 0
++
+     def _run_clang_format_path(self, clang_format, paths, output_file, output_format):
+ 
+         # Run clang-format on files or directories directly
+         from subprocess import check_output, CalledProcessError
+ 
+         if output_format == 'json':
+             # Get replacements in xml, then process to json
+             args = [clang_format, '-output-replacements-xml']
+@@ -2207,31 +2241,39 @@ class StaticAnalysis(MachCommandBase):
+ 
+         if path_list == []:
+             return
+ 
+         print("Processing %d file(s)..." % len(path_list))
+ 
+         if output_file:
+             patches = {}
++            cached_clang_format_cfg = {}
+             for i in range(0, len(path_list)):
+                 l = path_list[i: (i + 1)]
+ 
+                 # Copy the files into a temp directory
+                 # and run clang-format on the temp directory
+                 # and show the diff
+                 original_path = l[0]
+                 local_path = ntpath.basename(original_path)
++                current_dir = ntpath.dirname(original_path)
+                 target_file = os.path.join(tmpdir, local_path)
+                 faketmpdir = os.path.dirname(target_file)
+                 if not os.path.isdir(faketmpdir):
+                     os.makedirs(faketmpdir)
+                 shutil.copy(l[0], faketmpdir)
+                 l[0] = target_file
+ 
++                ret = self._copy_clang_format_for_show_diff(current_dir,
++                                                            cached_clang_format_cfg,
++                                                            faketmpdir)
++                if ret != 0:
++                    return ret
++
+                 # Run clang-format on the list
+                 try:
+                     output = check_output(args + l)
+                     if output and output_format == 'json':
+                         # Output a relative path in json patch list
+                         relative_path = os.path.relpath(original_path, self.topsrcdir)
+                         patches[relative_path] = self._parse_xml_output(original_path, output)
+                 except CalledProcessError as e:

+ 215 - 0
mozilla-release/patches/1635112-2-78a1.patch

@@ -0,0 +1,215 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1588922363 0
+# Node ID 8ade9f1318ba08fed3e91ce3df7e8b28fc11131b
+# Parent  8c473e56035e8be39c79d9c92c396203638bbe00
+Bug 1635112 - Use `clang-tidy` as warning build error detector for our `static-analysis` targets. r=glandium
+
+Differential Revision: https://phabricator.services.mozilla.com/D73692
+
+diff --git a/python/mozbuild/mozbuild/compilation/warnings.py b/python/mozbuild/mozbuild/compilation/warnings.py
+--- a/python/mozbuild/mozbuild/compilation/warnings.py
++++ b/python/mozbuild/mozbuild/compilation/warnings.py
+@@ -18,42 +18,42 @@ import mozpack.path as mozpath
+ 
+ 
+ # Regular expression to strip ANSI color sequences from a string. This is
+ # needed to properly analyze Clang compiler output, which may be colorized.
+ # It assumes ANSI escape sequences.
+ RE_STRIP_COLORS = re.compile(r'\x1b\[[\d;]+m')
+ 
+ # This captures Clang diagnostics with the standard formatting.
+-RE_CLANG_WARNING = re.compile(r"""
++RE_CLANG_WARNING_AND_ERROR = re.compile(r"""
+     (?P<file>[^:]+)
+     :
+     (?P<line>\d+)
+     :
+     (?P<column>\d+)
+     :
+-    \swarning:\s
++    \s(?P<type>warning|error):\s
+     (?P<message>.+)
+     \[(?P<flag>[^\]]+)
+     """, re.X)
+ 
+ # This captures Clang-cl warning format.
+-RE_CLANG_CL_WARNING = re.compile(r"""
++RE_CLANG_CL_WARNING_AND_ERROR = re.compile(r"""
+     (?P<file>.*)
+     \((?P<line>\d+),(?P<column>\d+)\)
+-    \s?:\s+warning:\s
++    \s?:\s+(?P<type>warning|error):\s
+     (?P<message>.*)
+     \[(?P<flag>[^\]]+)
+     """, re.X)
+ 
+ # This captures Visual Studio's warning format.
+-RE_MSVC_WARNING = re.compile(r"""
++RE_MSVC_WARNING_AND_ERROR = re.compile(r"""
+     (?P<file>.*)
+     \((?P<line>\d+)\)
+-    \s?:\swarning\s
++    \s?:\s(?P<type>warning|error)\s
+     (?P<flag>[^:]+)
+     :\s
+     (?P<message>.*)
+     """, re.X)
+ 
+ IN_FILE_INCLUDED_FROM = 'In file included from '
+ 
+ 
+@@ -332,41 +332,44 @@ class WarningsCollector(object):
+             self.included_from.append(parts[0])
+ 
+             return
+ 
+         warning = CompilerWarning()
+         filename = None
+ 
+         # TODO make more efficient so we run minimal regexp matches.
+-        match_clang = RE_CLANG_WARNING.match(filtered)
+-        match_clang_cl = RE_CLANG_CL_WARNING.match(filtered)
+-        match_msvc = RE_MSVC_WARNING.match(filtered)
++        match_clang = RE_CLANG_WARNING_AND_ERROR.match(filtered)
++        match_clang_cl = RE_CLANG_CL_WARNING_AND_ERROR.match(filtered)
++        match_msvc = RE_MSVC_WARNING_AND_ERROR.match(filtered)
+         if match_clang:
+             d = match_clang.groupdict()
+ 
+             filename = d['file']
++            warning['type'] = d['type']
+             warning['line'] = int(d['line'])
+             warning['column'] = int(d['column'])
+             warning['flag'] = d['flag']
+             warning['message'] = d['message'].rstrip()
+ 
+         elif match_clang_cl:
+             d = match_clang_cl.groupdict()
+ 
+             filename = d['file']
++            warning['type'] = d['type']
+             warning['line'] = int(d['line'])
+             warning['column'] = int(d['column'])
+             warning['flag'] = d['flag']
+             warning['message'] = d['message'].rstrip()
+ 
+         elif match_msvc:
+             d = match_msvc.groupdict()
+ 
+             filename = d['file']
++            warning['type'] = d['type']
+             warning['line'] = int(d['line'])
+             warning['flag'] = d['flag']
+             warning['message'] = d['message'].rstrip()
+         else:
+             self.included_from = []
+             return None
+ 
+         filename = os.path.normpath(filename)
+diff --git a/python/mozbuild/mozbuild/controller/building.py b/python/mozbuild/mozbuild/controller/building.py
+--- a/python/mozbuild/mozbuild/controller/building.py
++++ b/python/mozbuild/mozbuild/controller/building.py
+@@ -220,16 +220,20 @@ class BuildMonitor(MozbuildObject):
+             except ValueError:
+                 os.remove(warnings_path)
+ 
+         # Contains warnings unique to this invocation. Not populated with old
+         # warnings.
+         self.instance_warnings = WarningsDatabase()
+ 
+         def on_warning(warning):
++            # Skip `errors`
++            if warning['type'] == 'error':
++                return
++
+             filename = warning['filename']
+ 
+             if not os.path.exists(filename):
+                 raise Exception('Could not find file containing warning: %s' %
+                                 filename)
+ 
+             self.warnings_database.insert(warning)
+             # Make a copy so mutations don't impact other database.
+diff --git a/python/mozbuild/mozbuild/test/compilation/test_warnings.py b/python/mozbuild/mozbuild/test/compilation/test_warnings.py
+--- a/python/mozbuild/mozbuild/test/compilation/test_warnings.py
++++ b/python/mozbuild/mozbuild/test/compilation/test_warnings.py
+@@ -12,27 +12,27 @@ from mozfile.mozfile import NamedTempora
+ from mozbuild.compilation.warnings import CompilerWarning
+ from mozbuild.compilation.warnings import WarningsCollector
+ from mozbuild.compilation.warnings import WarningsDatabase
+ 
+ from mozunit import main
+ 
+ CLANG_TESTS = [
+     ('foobar.cpp:123:10: warning: you messed up [-Wfoo]',
+-     'foobar.cpp', 123, 10, 'you messed up', '-Wfoo'),
+-    ("c_locale_dummy.c:457:1: warning: (near initialization for "
+-     "'full_wmonthname[0]') [-Wpointer-sign]",
+-     'c_locale_dummy.c', 457, 1,
+-     "(near initialization for 'full_wmonthname[0]')", '-Wpointer-sign')
++     'foobar.cpp', 123, 10, 'warning', 'you messed up', '-Wfoo'),
++    ("c_locale_dummy.c:457:1: error: (near initialization for "
++     "'full_wmonthname[0]') [clang-diagnostic-error]",
++     'c_locale_dummy.c', 457, 1, 'error',
++     "(near initialization for 'full_wmonthname[0]')", 'clang-diagnostic-error')
+ ]
+ 
+ MSVC_TESTS = [
+     ("C:/mozilla-central/test/foo.cpp(793) : warning C4244: 'return' : "
+      "conversion from 'double' to 'uint32_t', possible loss of data",
+-     'C:/mozilla-central/test/foo.cpp', 793, 'C4244',
++     'C:/mozilla-central/test/foo.cpp', 793, 'warning', 'C4244',
+      "'return' : conversion from 'double' to 'uint32_t', possible loss of "
+      'data')
+ ]
+ 
+ CURRENT_LINE = 1
+ 
+ 
+ def get_warning():
+@@ -122,39 +122,41 @@ class TestCompilerWarning(unittest.TestC
+         w2['column'] = 5
+ 
+         self.assertLessEqual(w1, w2)
+         self.assertLessEqual(w2, w1)
+         self.assertGreaterEqual(w2, w1)
+         self.assertGreaterEqual(w1, w2)
+ 
+ 
+-class TestWarningsParsing(unittest.TestCase):
++class TestWarningsAndErrorsParsing(unittest.TestCase):
+     def test_clang_parsing(self):
+-        for source, filename, line, column, message, flag in CLANG_TESTS:
++        for source, filename, line, column, diag_type, message, flag in CLANG_TESTS:
+             collector = WarningsCollector(lambda w: None)
+             warning = collector.process_line(source)
+ 
+             self.assertIsNotNone(warning)
+ 
+             self.assertEqual(warning['filename'], filename)
+             self.assertEqual(warning['line'], line)
+             self.assertEqual(warning['column'], column)
++            self.assertEqual(warning['type'], diag_type)
+             self.assertEqual(warning['message'], message)
+             self.assertEqual(warning['flag'], flag)
+ 
+     def test_msvc_parsing(self):
+-        for source, filename, line, flag, message in MSVC_TESTS:
++        for source, filename, line, diag_type, flag, message in MSVC_TESTS:
+             collector = WarningsCollector(lambda w: None)
+             warning = collector.process_line(source)
+ 
+             self.assertIsNotNone(warning)
+ 
+             self.assertEqual(warning['filename'], os.path.normpath(filename))
+             self.assertEqual(warning['line'], line)
++            self.assertEqual(warning['type'], diag_type)
+             self.assertEqual(warning['flag'], flag)
+             self.assertEqual(warning['message'], message)
+ 
+ 
+ class TestWarningsDatabase(unittest.TestCase):
+     def test_basic(self):
+         db = WarningsDatabase()
+ 

+ 51 - 0
mozilla-release/patches/1635112-3-78a1.patch

@@ -0,0 +1,51 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1588930202 0
+# Node ID a9d5c0620a5b1bd46e2dfbc3b5c159d8f917ecfa
+# Parent  40cc4318e61a185425a3906c88205c89b50d1043
+Bug 1635112 - Disable the build error reporting at review-phase using `Coverity`. r=sylvestre,marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D74003
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -571,17 +571,16 @@ class StaticAnalysis(MachCommandBase):
+             def build_element(issue):
+                 # We look only for main event
+                 event_path = next(
+                     (event for event in issue['events'] if event['main'] is True), None)
+ 
+                 dict_issue = {
+                     'line': issue['mainEventLineNumber'],
+                     'flag': issue['checkerName'],
+-                    'build_error': issue['checkerName'].startswith('RW.CLANG'),
+                     'message': event_path['eventDescription'],
+                     'reliability': self.get_reliability_index_for_cov_checker(
+                         issue['checkerName']
+                         ),
+                     'extra': {
+                         'category': issue['checkerProperties']['category'],
+                         'stateOnServer': issue['stateOnServer'],
+                         'stack': []
+@@ -597,16 +596,20 @@ class StaticAnalysis(MachCommandBase):
+                          'path_type': event['eventTag'],
+                          'description': event['eventDescription']})
+ 
+                 return dict_issue
+ 
+             for issue in result['issues']:
+                 path = build_repo_relative_path(issue['strippedMainEventFilePathname'],
+                                                 self.topsrcdir)
++                # Skip clang diagnostic messages
++                if issue['checkerName'].startswith('RW.CLANG'):
++                    continue
++
+                 if path is None:
+                     # Since we skip a result we should log it
+                     self.log(logging.INFO, 'static-analysis', {},
+                              'Skipping CID: {0} from file: {1} since it\'s not related '
+                              'with the current patch.'.format(
+                                 issue['stateOnServer']['cid'],
+                                 issue['strippedMainEventFilePathname'])
+                              )

+ 36 - 0
mozilla-release/patches/1635112-4-78a1.patch

@@ -0,0 +1,36 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1588922391 0
+# Node ID dfe30a8355621a3a866359bfe4b4f827ccfb3cf7
+# Parent  dbd5c70853c1c78cea7f7adc0edc201380bee6c5
+Bug 1635112 - Mark `clang-diagnostic-error` as `publishable` in the `clang-tidy` artifact. r=marco
+
+For `clang-tidy` static-analysis mark all diagnostic-messages that are `clang-diagnostic-error` as publishable.
+
+Differential Revision: https://phabricator.services.mozilla.com/D74229
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -157,16 +157,21 @@ class StaticAnalysisMonitor(object):
+                     if matcher is not None and matcher.group(0) == checker_name:
+                         return item
+ 
+             check_config = get_check_config(warning['flag'])
+             if check_config is not None:
+                 warning['reliability'] = check_config.get('reliability', 'low')
+                 warning['reason'] = check_config.get('reason')
+                 warning['publish'] = check_config.get('publish', True)
++            elif warning["flag"] == "clang-diagnostic-error":
++                # For a "warning" that is flagged as "clang-diagnostic-error"
++                # set it as "publish"
++                warning['publish'] = True
++
+         return (warning, True)
+ 
+ 
+ @CommandProvider
+ class StaticAnalysis(MachCommandBase):
+     """Utilities for running C++ static analysis checks and format."""
+ 
+     # List of file extension to consider (should start with dot)

+ 32 - 0
mozilla-release/patches/1635526-78a1.patch

@@ -0,0 +1,32 @@
+# HG changeset patch
+# User Ricky Stewart <rstewart@mozilla.com>
+# Date 1588703494 0
+# Node ID 74a0e506a87799dd5c553d615e41fed1c6a576b6
+# Parent  639b65dfe69741516c438ec197e5302292b97fa9
+Bug 1635526 - Activate virtualenv in `mach static-analysis autotest` r=andi
+
+After bug 1633039, we won't be guaranteed to have the `init` virtualenv already created after running a build, so `static-analysis autotest` needs to make sure it's created all by itself. This results in failures like [this](https://treeherder.mozilla.org/#/jobs?repo=autoland&selectedTaskRun=WDRF1EzDRA6jPqPb60X5Pw-0&revision=332ce0963b4e92d68b0de25860debb7694dc38d5).
+
+Differential Revision: https://phabricator.services.mozilla.com/D73924
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1058,16 +1058,17 @@ class StaticAnalysis(MachCommandBase):
+                      ' This option is only valid on automation environments.')
+     @CommandArgument('checker_names', nargs='*', default=[],
+                      help='Checkers that are going to be auto-tested.')
+     def autotest(self, verbose=False, dump_results=False, intree_tool=False, checker_names=[]):
+         # If 'dump_results' is True than we just want to generate the issues files for each
+         # checker in particulat and thus 'force_download' becomes 'False' since we want to
+         # do this on a local trusted clang-tidy package.
+         self._set_log_level(verbose)
++        self._activate_virtualenv()
+         self._dump_results = dump_results
+ 
+         force_download = not self._dump_results
+ 
+         # Function return codes
+         self.TOOLS_SUCCESS = 0
+         self.TOOLS_FAILED_DOWNLOAD = 1
+         self.TOOLS_UNSUPORTED_PLATFORM = 2

+ 123 - 0
mozilla-release/patches/1635795-78a1.patch

@@ -0,0 +1,123 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1588783635 0
+# Node ID 0fbb154d098abe5ad69c9e165862d449d0a92812
+# Parent  1dee2c6e7a60f74a2498ed6cf450627391b48829
+Bug 1635795 - Activate virtualenv for `mach static-analysis`. r=rstewart,marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D74058
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -228,17 +228,18 @@ class StaticAnalysis(MachCommandBase):
+     def check(self, source=None, jobs=2, strip=1, verbose=False, checks='-*',
+               fix=False, header_filter='', output=None, format='text', outgoing=False):
+         from mozbuild.controller.building import (
+             StaticAnalysisFooter,
+             StaticAnalysisOutputManager,
+         )
+ 
+         self._set_log_level(verbose)
+-        self.log_manager.enable_all_structured_loggers()
++        self._activate_virtualenv()
++        self.log_manager.enable_unstructured()
+ 
+         rc = self._get_clang_tools(verbose=verbose)
+         if rc != 0:
+             return rc
+ 
+         if self._is_version_eligible() is False:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      "ERROR: You're using an old version of clang-format binary."
+@@ -334,17 +335,18 @@ class StaticAnalysis(MachCommandBase):
+                      'directory, ~./mozbuild/coverity is used.')
+     @CommandArgument('--outgoing', default=False, action='store_true',
+                      help='Run coverity on outgoing files from mercurial or git repository')
+     @CommandArgument('--full-build', default=False, action='store_true',
+                      help='Run a full build for coverity analisys.')
+     def check_coverity(self, source=[], output=None, coverity_output_path=None,
+                        outgoing=False, full_build=False, verbose=False):
+         self._set_log_level(verbose)
+-        self.log_manager.enable_all_structured_loggers()
++        self._activate_virtualenv()
++        self.log_manager.enable_unstructured()
+ 
+         if 'MOZ_AUTOMATION' not in os.environ:
+             self.log(logging.INFO, 'static-analysis', {},
+                      'Coverity based static-analysis cannot be ran outside automation.')
+             return
+ 
+         if full_build and outgoing:
+             self.log(logging.INFO, 'static-analysis', {},
+@@ -622,19 +624,17 @@ class StaticAnalysis(MachCommandBase):
+ 
+         secret_name = 'project/relman/coverity'
+         secrets_url = '{}/secrets/v1/secret/{}'.format(get_root_url(True), secret_name)
+ 
+         self.log(logging.INFO, 'static-analysis', {},
+                  'Using symbol upload token from the secrets service: "{}"'.format(secrets_url))
+ 
+         import requests
+-        self.log_manager.enable_unstructured()
+         res = requests.get(secrets_url)
+-        self.log_manager.disable_unstructured()
+         res.raise_for_status()
+         secret = res.json()
+         cov_config = secret['secret'] if 'secret' in secret else None
+ 
+         if cov_config is None:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'ERROR: Ill formatted secret for Coverity. Aborting analysis.')
+             return 1
+@@ -795,17 +795,19 @@ class StaticAnalysis(MachCommandBase):
+     @CommandArgument('--outgoing', default=False, action='store_true',
+                      help='Run infer checks on outgoing files from repository')
+     @CommandArgument('--output', default=None,
+                      help='Write infer json output in a file')
+     def check_java(self, source=['mobile'], jobs=2, strip=1, verbose=False, checks=[],
+                    task='compileWithGeckoBinariesDebugSources',
+                    skip_export=False, outgoing=False, output=None):
+         self._set_log_level(verbose)
+-        self.log_manager.enable_all_structured_loggers()
++        self._activate_virtualenv()
++        self.log_manager.enable_unstructured()
++
+         if self.substs['MOZ_BUILD_APP'] != 'mobile/android':
+             self.log(logging.WARNING, 'static-analysis', {},
+                      'Cannot check java source code unless you are building for android!')
+             return 1
+         rc = self._check_for_java()
+         if rc != 0:
+             return 1
+         if output is not None:
+@@ -1533,25 +1535,26 @@ class StaticAnalysis(MachCommandBase):
+             return process.returncode
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'check-syntax',
+                               'Run the check-syntax for C/C++ files based on '
+                               '`compile_commands.json`')
+     @CommandArgument('source', nargs='*',
+                      help='Source files to be compiled checked (regex on path).')
+     def check_syntax(self, source, verbose=False):
++        self._set_log_level(verbose)
++        self._activate_virtualenv()
++        self.log_manager.enable_unstructured()
++
+         # Verify that we have a valid `source`
+         if len(source) == 0:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'ERROR: Specify files that need to be syntax checked.')
+             return
+ 
+-        self._set_log_level(verbose)
+-        self.log_manager.enable_all_structured_loggers()
+-
+         rc = self._build_compile_db(verbose=verbose)
+         if rc != 0:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'ERROR: Unable to build the `compile_commands.json`.')
+             return rc
+         rc = self._build_export(jobs=2, verbose=verbose)
+ 
+         if rc != 0:

+ 174 - 0
mozilla-release/patches/1638985-79a1.patch

@@ -0,0 +1,174 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1591890869 0
+# Node ID b793e08a5e8b02550385affd0480175b6873a18f
+# Parent  3fea7730839ff8de76e8621bc19c5ff36fae9b58
+Bug 1638985 - Convert 'mach static-analysis' to run with Python 3. r=rstewart
+
+Differential Revision: https://phabricator.services.mozilla.com/D79306
+
+diff --git a/mach b/mach
+--- a/mach
++++ b/mach
+@@ -35,17 +35,16 @@ py2commands="
+     mozharness
+     pastebin
+     prettier-format
+     raptor
+     raptor-test
+     reftest
+     release
+     rusttests
+-    static-analysis
+     talos-test
+     taskcluster-build-image
+     taskcluster-load-image
+     taskgraph
+     telemetry-tests-client
+     test
+     tps-build
+     visualmetrics
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -258,17 +258,17 @@ class StaticAnalysis(MachCommandBase):
+         rc = rc or self._build_export(jobs=jobs, verbose=verbose)
+         if rc != 0:
+             return rc
+ 
+         # Use outgoing files instead of source files
+         if outgoing:
+             repo = get_repository_object(self.topsrcdir)
+             files = repo.get_outgoing_files()
+-            source = map(os.path.abspath, files)
++            source = [os.path.abspath(f) for f in files]
+ 
+         # Split in several chunks to avoid hitting Python's limit of 100 groups in re
+         compile_db = json.loads(open(self._compile_db, 'r').read())
+         total = 0
+         import re
+         chunk_size = 50
+         for offset in range(0, len(source), chunk_size):
+             source_chunks = source[offset:offset + chunk_size]
+@@ -360,17 +360,17 @@ class StaticAnalysis(MachCommandBase):
+             self.log(logging.INFO, 'static-analysis', {},
+                      'Coverity full build cannot be associated with outgoing.')
+             return
+ 
+         # Use outgoing files instead of source files
+         if outgoing:
+             repo = get_repository_object(self.topsrcdir)
+             files = repo.get_outgoing_files()
+-            source = map(os.path.abspath, files)
++            source = [os.path.abspath(f) for f in files]
+ 
+         # Verify that we have source files or we are dealing with a full-build
+         if len(source) == 0 and not full_build:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'ERROR: There are no files that coverity can use to scan.')
+             return 0
+ 
+         # Load the configuration file for coverity static-analysis
+@@ -1310,17 +1310,17 @@ class StaticAnalysis(MachCommandBase):
+             print('This is the output generated by clang-tidy for the bulk build:\n{}'.format(
+                 clang_output))
+             return self.TOOLS_CHECKER_DIFF_FAILED
+ 
+         return self.TOOLS_SUCCESS
+ 
+     def _create_temp_compilation_db(self, config):
+         directory = tempfile.mkdtemp(prefix='cc')
+-        with open(mozpath.join(directory, "compile_commands.json"), "wb") as file_handler:
++        with open(mozpath.join(directory, "compile_commands.json"), "w") as file_handler:
+             compile_commands = []
+             director = mozpath.join(self.topsrcdir, 'tools', 'clang-tidy', 'test')
+             for item in config['clang_checkers']:
+                 if item['name'] in ['-*', 'mozilla-*']:
+                     continue
+                 file = item['name'] + '.cpp'
+                 element = {}
+                 element["directory"] = director
+@@ -1480,38 +1480,57 @@ class StaticAnalysis(MachCommandBase):
+             # not mandatory, but clang-tidy is
+             self._get_infer(force=force, skip_cache=skip_cache, verbose=verbose)
+         return rc
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'clear-cache',
+                               'Delete local helpers and reset static analysis helper tool cache')
+     def clear_cache(self, verbose=False):
+         self._set_log_level(verbose)
+-        rc = self._get_clang_tools(force=True, download_if_needed=True, skip_cache=True,
+-                                   verbose=verbose)
+-        if rc == 0:
+-            self._get_infer(force=True, download_if_needed=True, skip_cache=True,
+-                            verbose=verbose)
++        rc = self._get_clang_tools(
++            force=True, download_if_needed=True, skip_cache=True, verbose=verbose)
++
+         if rc != 0:
+             return rc
++
++        job, _ = self.platform
++        if job == 'linux64':
++            rc = self._get_infer(
++                force=True, download_if_needed=True, skip_cache=True, verbose=verbose)
++            if rc != 0:
++                return rc
++
+         return self._artifact_manager.artifact_clear_cache()
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'print-checks',
+                               'Print a list of the static analysis checks performed by default')
+     def print_checks(self, verbose=False):
+         self._set_log_level(verbose)
+         rc = self._get_clang_tools(verbose=verbose)
+-        if rc == 0:
+-            rc = self._get_infer(verbose=verbose)
++
+         if rc != 0:
+             return rc
++
++        if self._clang_tidy_config is None:
++            self._clang_tidy_config = self._get_clang_tidy_config()
++
+         args = [self._clang_tidy_path, '-list-checks', '-checks=%s' % self._get_checks()]
+-        rc = self._run_command_in_objdir(args=args, pass_thru=True)
++
++        rc = self.run_process(args=args, pass_thru=True)
+         if rc != 0:
+             return rc
++
++        job, _ = self.platform
++        if job != 'linux64':
++            return 0
++
++        rc = self._get_infer(verbose=verbose)
++        if rc != 0:
++            return rc
++
+         checkers, _ = self._get_infer_config()
+         print('Infer checks:')
+         for checker in checkers:
+             print(' '*4 + checker)
+         return 0
+ 
+     @Command('prettier-format',  category='misc', description='Run prettier on current changes')
+     @CommandArgument('--path', '-p', nargs=1, required=True,
+@@ -1547,17 +1566,16 @@ class StaticAnalysis(MachCommandBase):
+ 
+     @StaticAnalysisSubCommand('static-analysis', 'check-syntax',
+                               'Run the check-syntax for C/C++ files based on '
+                               '`compile_commands.json`')
+     @CommandArgument('source', nargs='*',
+                      help='Source files to be compiled checked (regex on path).')
+     def check_syntax(self, source, verbose=False):
+         self._set_log_level(verbose)
+-        self._activate_virtualenv()
+         self.log_manager.enable_unstructured()
+ 
+         # Verify that we have a valid `source`
+         if len(source) == 0:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'ERROR: Specify files that need to be syntax checked.')
+             return
+ 

+ 39 - 0
mozilla-release/patches/1639406-79a1.patch

@@ -0,0 +1,39 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1591260782 0
+# Node ID 3ecc718f88e08583f2fdb1d04299cd50a37b14cd
+# Parent  166787e071bea0550287bdd20355a59183f648e7
+Bug 1639406 - for `code-review` generate the propper patch when dealing with `clang-format` issues. r=marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D78060
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -2304,18 +2304,24 @@ class StaticAnalysis(MachCommandBase):
+                     except CalledProcessError as e:
+                         # diff -u returns 0 when no change
+                         # here, we expect changes. if we are here, this means that
+                         # there is a diff to show
+                         if e.output:
+                             # Replace the temp path by the path relative to the repository to
+                             # display a valid patch
+                             relative_path = os.path.relpath(original_path, self.topsrcdir)
+-                            patch = e.output.replace(target_file, relative_path)
+-                            patch = patch.replace(original_path, relative_path)
++                            # We must modify the paths in order to be compatible with the
++                            # `diff` format.
++                            original_path_diff = os.path.join("a", relative_path)
++                            target_path_diff = os.path.join("b", relative_path)
++                            patch = e.output.replace("+++ {}".format(target_file),
++                                                     "+++ {}".format(target_path_diff)).replace(
++                                                         "-- {}".format(original_path),
++                                                         "-- {}".format(original_path_diff))
+                             patches[original_path] = patch
+ 
+             if output_format == 'json':
+                 output = json.dumps(patches, indent=4)
+             else:
+                 # Display all the patches at once
+                 output = '\n'.join(patches.values())
+ 

+ 44 - 0
mozilla-release/patches/1640142-78a1.patch

@@ -0,0 +1,44 @@
+# HG changeset patch
+# User Tilden Windsor <a.neun@outlook.com>
+# Date 1590148428 0
+# Node ID f4da1835858c0db71e18276baea926f75c710fe4
+# Parent  2f22a028585942043f0b8275e666c266a673a8ab
+Bug 1640142 - Added spaces to "mach clang-format" help message. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D76467
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1628,28 +1628,28 @@ class StaticAnalysis(MachCommandBase):
+                           'specifying this option only one file should be used '
+                           'as an input and the output will be forwarded to stdin. '
+                           'This option also impairs the download of the clang-tools '
+                           'and assumes the package is already located in it\'s default '
+                           'location')
+     @CommandArgument('--path', '-p', nargs='+', default=None,
+                      help='Specify the path(s) to reformat')
+     @CommandArgument('--commit', '-c', default=None,
+-                     help='Specify a commit to reformat from.'
+-                          'For git you can also pass a range of commits (foo..bar)'
++                     help='Specify a commit to reformat from. '
++                          'For git you can also pass a range of commits (foo..bar) '
+                           'to format all of them at the same time.')
+     @CommandArgument('--output', '-o', default=None, dest='output_path',
+                      help='Specify a file handle to write clang-format raw output instead of '
+                           'applying changes. This can be stdout or a file path.')
+     @CommandArgument('--format', '-f', choices=('diff', 'json'), default='diff',
+                      dest='output_format',
+                      help='Specify the output format used: diff is the raw patch provided by '
+                      'clang-format, json is a list of atomic changes to process.')
+     @CommandArgument('--outgoing', default=False, action='store_true',
+-                     help='Run clang-format on outgoing files from mercurial repository')
++                     help='Run clang-format on outgoing files from mercurial repository.')
+     def clang_format(self, assume_filename, path, commit, output_path=None, output_format='diff',
+                      verbose=False, outgoing=False):
+         # Run clang-format or clang-format-diff on the local changes
+         # or files/directories
+         if path is None and outgoing:
+             repo = get_repository_object(self.topsrcdir)
+             path = repo.get_outgoing_files()
+ 

+ 40 - 0
mozilla-release/patches/1640878-78a1.patch

@@ -0,0 +1,40 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1590513818 0
+# Node ID 0403812954413c969915a1a69042dc3cbd6043d5
+# Parent  b0002883d11fcc7f5ade69ab7e52ebf1d057b3e1
+Bug 1640878 - for `clang-tidy` static-analysis keep a deep copy of the checks. r=froydnj
+
+`StaticAnalysisMonitor` uses `clang-tidy` config dictionary in order to
+match different options for the checkers that are being used. For this `StaticAnalysisMonitor`
+modifies this dictionary. The dictionary not being a deep copy of the original one, the
+modifications are echoed in the initial dictionary thus having the potential to lead to
+unexpected behavior from `clang-tidy` when generating the checkers list.
+
+Differential Revision: https://phabricator.services.mozilla.com/D76834
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -85,17 +85,20 @@ class StaticAnalysisSubCommand(SubComman
+ 
+ class StaticAnalysisMonitor(object):
+     def __init__(self, srcdir, objdir, clang_tidy_config, total):
+         self._total = total
+         self._processed = 0
+         self._current = None
+         self._srcdir = srcdir
+ 
+-        self._clang_tidy_config = clang_tidy_config['clang_checkers']
++        import copy
++
++        self._clang_tidy_config = copy.deepcopy(clang_tidy_config['clang_checkers'])
++
+         # Transform the configuration to support Regex
+         for item in self._clang_tidy_config:
+             if item['name'] == '-*':
+                 continue
+             item['name'] = item['name'].replace('*', '.*')
+ 
+         from mozbuild.compilation.warnings import (
+             WarningsCollector,

+ 95 - 0
mozilla-release/patches/1645948-80a1.patch

@@ -0,0 +1,95 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1593267020 0
+# Node ID c4ee600c6d9e16e0b95c776d87a9e589e5740020
+# Parent  20433dd9f706337f6246cd9340b1564d8d48192a
+Bug 1645948 - for `clang-tidy` static-analysis escape some paths that have special chars. r=sylvestre
+
+The patch that has been applied to our `clang-tidy` artifact has also been pushed upstead https://reviews.llvm.org/D81917
+
+Differential Revision: https://phabricator.services.mozilla.com/D79799
+
+diff --git a/build/build-clang/clang-tidy-linux64.json b/build/build-clang/clang-tidy-linux64.json
+--- a/build/build-clang/clang-tidy-linux64.json
++++ b/build/build-clang/clang-tidy-linux64.json
+@@ -11,10 +11,11 @@
+     "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final/",
+     "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final/",
+     "python_path": "/usr/bin/python2.7",
+     "gcc_dir": "/builds/worker/workspace/build/src/gcc",
+     "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
+     "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
+     "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
+     "patches": [
++        "run-clang-tidy-escape.patch"
+     ]
+ }
+diff --git a/build/build-clang/clang-tidy-macosx64.json b/build/build-clang/clang-tidy-macosx64.json
+--- a/build/build-clang/clang-tidy-macosx64.json
++++ b/build/build-clang/clang-tidy-macosx64.json
+@@ -16,10 +16,11 @@
+     "cc": "/builds/worker/workspace/build/src/clang/bin/clang",
+     "cxx": "/builds/worker/workspace/build/src/clang/bin/clang++",
+     "as": "/builds/worker/workspace/build/src/clang/bin/clang",
+     "ar": "/builds/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin-ar",
+     "ranlib": "/builds/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin-ranlib",
+     "libtool": "/builds/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin-libtool",
+     "ld": "/builds/worker/workspace/build/src/clang/bin/clang",
+     "patches": [
++      "run-clang-tidy-escape.patch"
+     ]
+ }
+diff --git a/build/build-clang/clang-tidy-win64.json b/build/build-clang/clang-tidy-win64.json
+--- a/build/build-clang/clang-tidy-win64.json
++++ b/build/build-clang/clang-tidy-win64.json
+@@ -10,10 +10,11 @@
+     "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_701/final",
+     "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_701/final",
+     "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final",
+     "python_path": "c:/mozilla-build/python/python.exe",
+     "cc": "cl.exe",
+     "cxx": "cl.exe",
+     "ml": "ml64.exe",
+     "patches": [
++        "run-clang-tidy-escape.patch"
+     ]
+ }
+diff --git a/build/build-clang/run-clang-tidy-escape.patch b/build/build-clang/run-clang-tidy-escape.patch
+new file mode 100644
+--- /dev/null
++++ b/build/build-clang/run-clang-tidy-escape.patch
+@@ -0,0 +1,12 @@
++diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
++index 1eb13529575..2ac02b66dd9 100755
++--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
++@@ -267,6 +267,7 @@ def main():
++     tmpdir = tempfile.mkdtemp()
++ 
++   # Build up a big regexy filter from all command line arguments.
+++  args.files = [re.escape(f) for f in args.files]
++   file_name_re = re.compile('|'.join(args.files))
++ 
++   return_code = 0
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -267,17 +267,17 @@ class StaticAnalysis(MachCommandBase):
+             source = [os.path.abspath(f) for f in files]
+ 
+         # Split in several chunks to avoid hitting Python's limit of 100 groups in re
+         compile_db = json.loads(open(self._compile_db, 'r').read())
+         total = 0
+         import re
+         chunk_size = 50
+         for offset in range(0, len(source), chunk_size):
+-            source_chunks = source[offset:offset + chunk_size]
++            source_chunks = [re.escape(f) for f in source[offset:offset + chunk_size].copy()]
+             name_re = re.compile('(' + ')|('.join(source_chunks) + ')')
+             for f in compile_db:
+                 if name_re.search(f['file']):
+                     total = total + 1
+ 
+         # Filter source to remove excluded files
+         source = self._generate_path_list(source, verbose=verbose)
+ 

+ 31 - 0
mozilla-release/patches/1647629-79a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1592912571 0
+# Node ID 18727b87e5091ceb4ac2894228e641c3fa8d41fb
+# Parent  66d10f643ce5e0d44fc1a2da02696155a13fb2c8
+Bug 1647629 - Make infer static-analysis compatible with python3. r=sylvestre
+
+Differential Revision: https://phabricator.services.mozilla.com/D80633
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -893,17 +893,17 @@ class StaticAnalysis(MachCommandBase):
+         return java_sources
+ 
+     def _get_infer_source_args(self, sources):
+         '''Return the arguments to only analyze <sources>'''
+         if not sources:
+             return (None, [])
+         # create a temporary file in which we place all sources
+         # this is used by the analysis command to only analyze certain files
+-        f = tempfile.NamedTemporaryFile()
++        f = tempfile.NamedTemporaryFile(mode="wt")
+         for source in sources:
+             f.write(source+'\n')
+         f.flush()
+         return (f, ['--changed-files-index', f.name])
+ 
+     def _get_infer_config(self):
+         '''Load the infer config file.'''
+         checkers = []

+ 94 - 0
mozilla-release/patches/1650057-80a1.patch

@@ -0,0 +1,94 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1593699079 0
+# Node ID 1f13f2f9149f197294fb8dca0316efbefca6c54f
+# Parent  d8bdbd63e0ff1736c756d2d3d22dfe2c5e20fbb2
+Bug 1650057 - Avoid using external clang-tidy patches when dealing with paths that need to be escaped. r=marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D82002
+
+diff --git a/build/build-clang/clang-tidy-linux64.json b/build/build-clang/clang-tidy-linux64.json
+--- a/build/build-clang/clang-tidy-linux64.json
++++ b/build/build-clang/clang-tidy-linux64.json
+@@ -11,11 +11,10 @@
+     "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final/",
+     "libcxxabi_repo": "https://llvm.org/svn/llvm-project/libcxxabi/tags/RELEASE_701/final/",
+     "python_path": "/usr/bin/python2.7",
+     "gcc_dir": "/builds/worker/workspace/build/src/gcc",
+     "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
+     "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
+     "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
+     "patches": [
+-        "run-clang-tidy-escape.patch"
+     ]
+ }
+diff --git a/build/build-clang/clang-tidy-macosx64.json b/build/build-clang/clang-tidy-macosx64.json
+--- a/build/build-clang/clang-tidy-macosx64.json
++++ b/build/build-clang/clang-tidy-macosx64.json
+@@ -16,11 +16,10 @@
+     "cc": "/builds/worker/workspace/build/src/clang/bin/clang",
+     "cxx": "/builds/worker/workspace/build/src/clang/bin/clang++",
+     "as": "/builds/worker/workspace/build/src/clang/bin/clang",
+     "ar": "/builds/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin-ar",
+     "ranlib": "/builds/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin-ranlib",
+     "libtool": "/builds/worker/workspace/build/src/cctools/bin/x86_64-apple-darwin-libtool",
+     "ld": "/builds/worker/workspace/build/src/clang/bin/clang",
+     "patches": [
+-      "run-clang-tidy-escape.patch"
+     ]
+ }
+diff --git a/build/build-clang/clang-tidy-win64.json b/build/build-clang/clang-tidy-win64.json
+--- a/build/build-clang/clang-tidy-win64.json
++++ b/build/build-clang/clang-tidy-win64.json
+@@ -10,11 +10,10 @@
+     "extra_repo": "https://llvm.org/svn/llvm-project/clang-tools-extra/tags/RELEASE_701/final",
+     "compiler_repo": "https://llvm.org/svn/llvm-project/compiler-rt/tags/RELEASE_701/final",
+     "libcxx_repo": "https://llvm.org/svn/llvm-project/libcxx/tags/RELEASE_701/final",
+     "python_path": "c:/mozilla-build/python/python.exe",
+     "cc": "cl.exe",
+     "cxx": "cl.exe",
+     "ml": "ml64.exe",
+     "patches": [
+-        "run-clang-tidy-escape.patch"
+     ]
+ }
+diff --git a/build/build-clang/run-clang-tidy-escape.patch b/build/build-clang/run-clang-tidy-escape.patch
+deleted file mode 100644
+--- a/build/build-clang/run-clang-tidy-escape.patch
++++ /dev/null
+@@ -1,12 +0,0 @@
+-diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+-index 1eb13529575..2ac02b66dd9 100755
+---- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+-+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+-@@ -267,6 +267,7 @@ def main():
+-     tmpdir = tempfile.mkdtemp()
+- 
+-   # Build up a big regexy filter from all command line arguments.
+-+  args.files = [re.escape(f) for f in args.files]
+-   file_name_re = re.compile('|'.join(args.files))
+- 
+-   return_code = 0
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -282,16 +282,19 @@ class StaticAnalysis(MachCommandBase):
+         source = self._generate_path_list(source, verbose=verbose)
+ 
+         if not total or not source:
+             self.log(logging.INFO, 'static-analysis', {},
+                      "There are no files eligible for analysis. Please note that 'header' files "
+                      "cannot be used for analysis since they do not consist compilation units.")
+             return 0
+ 
++        # Escape the files from source
++        source = [re.escape(f) for f in source]
++
+         cwd = self.topobjdir
+         self._compilation_commands_path = self.topobjdir
+         if self._clang_tidy_config is None:
+             self._clang_tidy_config = self._get_clang_tidy_config()
+ 
+         monitor = StaticAnalysisMonitor(
+             self.topsrcdir, self.topobjdir, self._clang_tidy_config, total)
+ 

+ 31 - 0
mozilla-release/patches/1653560-81a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Philip Chimento <philip.chimento@gmail.com>
+# Date 1595948072 0
+# Node ID d3a8681b255b959bfab18edbb7d6760a8c7dfe50
+# Parent  569da24e172e0efbdcb469513efd8ca6e9eb6914
+Bug 1653560 - Fix distutils.spawn import. r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D84023
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -1022,17 +1022,17 @@ class StaticAnalysis(MachCommandBase):
+ 
+         return [
+             self.virtualenv_manager.python_path, self._run_clang_tidy_path, '-j',
+             str(jobs), '-p', self._compilation_commands_path
+         ] + common_args + sources
+ 
+     def _check_for_java(self):
+         '''Check if javac can be found.'''
+-        import distutils
++        import distutils.spawn
+         java = self.substs.get('JAVA')
+         java = java or os.getenv('JAVA_HOME')
+         java = java or distutils.spawn.find_executable('javac')
+         error = 'javac was not found! Please install javac and either add it to your PATH, '
+         error += 'set JAVA_HOME, or add the following to your mozconfig:\n'
+         error += '  --with-java-bin-path=/path/to/java/bin/'
+         if not java:
+             self.log(logging.ERROR, 'ERROR: static-analysis', {}, error)

+ 31 - 0
mozilla-release/patches/1654795-80a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Emilio Cobos Álvarez <emilio@crisal.io>
+# Date 1595513174 0
+# Node ID 04c1d72c0353a2dd371d49aead7eafbbf5d50502
+# Parent  bb4a290d55ffd41cc22dc5c2e93dfca6ba7c1f51
+Bug 1654795 - Fix mach clang-format python3 error. r=andi
+
+Differential Revision: https://phabricator.services.mozilla.com/D84691
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -2078,17 +2078,17 @@ class StaticAnalysis(MachCommandBase):
+             args = ["git", "diff", "--no-color", "-U0", commit_range, "--"]
+             for dot_extension in self._format_include_extensions:
+                 args += ['*{0}'.format(dot_extension)]
+             # git-diff doesn't support an 'exclude-from-files' param, but
+             # allow to add individual exclude pattern since v1.9, see
+             # https://git-scm.com/docs/gitglossary#gitglossary-aiddefpathspecapathspec
+             with open(self._format_ignore_file, 'rb') as exclude_pattern_file:
+                 for pattern in exclude_pattern_file.readlines():
+-                    pattern = pattern.rstrip()
++                    pattern = six.ensure_str(pattern.rstrip())
+                     pattern = pattern.replace('.*', '**')
+                     if not pattern or pattern.startswith('#'):
+                         continue  # empty or comment
+                     magics = ['exclude']
+                     if pattern.startswith('^'):
+                         magics += ['top']
+                         pattern = pattern[1:]
+                     args += [':({0}){1}'.format(','.join(magics), pattern)]

+ 31 - 0
mozilla-release/patches/1655701-81a1.patch

@@ -0,0 +1,31 @@
+# HG changeset patch
+# User Andi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
+# Date 1595940737 0
+# Node ID b6be51cb9bbcd2a30bf1e9d518c817bc9a28c867
+# Parent  251314c317b9d49ba78fa53ebe5577e8980e39aa
+Bug 1655701 - for Coverity static-analysis do not relay on ensure exit code. r=marco
+
+Differential Revision: https://phabricator.services.mozilla.com/D85133
+
+diff --git a/python/mozbuild/mozbuild/code-analysis/mach_commands.py b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+--- a/python/mozbuild/mozbuild/code-analysis/mach_commands.py
++++ b/python/mozbuild/mozbuild/code-analysis/mach_commands.py
+@@ -532,17 +532,17 @@ class StaticAnalysis(MachCommandBase):
+ 
+     def run_cov_command(self, cmd, path=None):
+         if path is None:
+             # We want to run it in topsrcdir
+             path = self.topsrcdir
+ 
+         self.log(logging.INFO, 'static-analysis', {}, 'Running '+' '.join(cmd))
+ 
+-        rc = self.run_process(args=cmd, cwd=path, pass_thru=True)
++        rc = self.run_process(args=cmd, cwd=path, pass_thru=True, ensure_exit_code=False)
+ 
+         if rc != 0:
+             self.log(logging.ERROR, 'static-analysis', {},
+                      'ERROR: Running ' + ' '.join(cmd) + ' failed!')
+             return rc
+         return 0
+ 
+     def get_reliability_index_for_cov_checker(self, checker_name):

+ 49 - 0
mozilla-release/patches/series

@@ -6878,13 +6878,39 @@ TOP-NOBUG-seamonkey-credits.patch
 1519358-66a1.patch
 1561102-1-69a1.patch
 1561102-2-69a1.patch
+1563326-69a1.patch
+1556393-0-69a1.patch
 1540655-01-70a1.patch
+1564824-70a1.patch
+1568558-70a1.patch
+1568535-70a1.patch
+1568771-70a1.patch
+1569880-70a1.patch
+1573434-5-PARTIAL-70a1.patch
+1575659-70a1.patch
+1577726-2-fix-71a1.patch
+1550517-71a1.patch
+1550516-71a1.patch
+1576659-PARTIAL-71a1.patch
+1527818-PARTIAL-71a1.patch
+1584468-71a1.patch
 1582114-71a1.patch
 1579845-4-71a1.patch
 1579845-6-71a1.patch
 1585734-71a1.patch
+1590086-72a1.patch
+1587079-72a1.patch
+1588283-72a1.patch
+1406309-72a1.patch
+1600048-72a1.patch
+1596456-72a1.patch
 1591195-72a1.patch
 1597065-72a1.patch
+1600226-73a1.patch
+1600558-73a1.patch
+1606541-1-73a1.patch
+1606541-2-73a1.patch
+1605852-1-73a1.patch
 1600904-PARTIAL-73a1.patch
 1604079-73a1.patch
 1604916-73a1.patch
@@ -6892,17 +6918,34 @@ TOP-NOBUG-seamonkey-credits.patch
 1606009-2-73a1.patch
 1606009-3-73a1.patch
 1606009-4-73a1.patch
+1605879-74a1.patch
+1605850-74a1.patch
 1602773-1-75a1.patch
 1602773-2no3-75a1.patch
 1602773-4-75a1.patch
 1620860-76a1.patch
 1623433-76a1.patch
 1619555-76a1.patch
+1619956-76a1.patch
+1626190-76a1.patch
+1626640-76a1.patch
+1634050-77a1.patch
 1630047-77a1.patch
 1630668-77a1.patch
 1632688-77a1.patch
+1635526-78a1.patch
+1635795-78a1.patch
+1635112-2-78a1.patch
+1635112-3-78a1.patch
+1635112-4-78a1.patch
+1640142-78a1.patch
+1640878-78a1.patch
 1636251-1-PARTIAL-78a1.patch
 1634391-2-78a1.patch
+1639406-79a1.patch
+1638985-79a1.patch
+1436251-3-PARTIAL-79a1.patch
+1647629-79a1.patch
 1642505-79a1.patch
 1637845-01-79a1.patch
 1637845-02-79a1.patch
@@ -6936,3 +6979,9 @@ TOP-NOBUG-seamonkey-credits.patch
 1646427-2-79a1.patch
 1646427-3-79a1.patch
 1646427-4-79a1.patch
+1645948-80a1.patch
+1650057-80a1.patch
+1606475-80a1.patch
+1654795-80a1.patch
+1655701-81a1.patch
+1653560-81a1.patch