Bug 1298210 - Move remove objdir code into clobber.py so that autoclobber and clobber command share the same code. r?gps
MozReview-Commit-ID: 5X1AQac8Fqi
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -1,29 +1,26 @@
# 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 errno
import json
import logging
import mozpack.path as mozpath
import multiprocessing
import os
import subprocess
import sys
import which
from mach.mixin.logging import LoggingMixin
from mach.mixin.process import ProcessExecutionMixin
-from mozfile.mozfile import remove as mozfileremove
-
from .backend.configenvironment import ConfigEnvironment
from .controller.clobber import Clobberer
from .mozconfig import (
MozconfigFindException,
MozconfigLoadException,
MozconfigLoader,
)
from .util import memoized_property
@@ -284,65 +281,16 @@ class MozbuildObject(ProcessExecutionMix
env[key] = value
return env
def is_clobber_needed(self):
if not os.path.exists(self.topobjdir):
return False
return Clobberer(self.topsrcdir, self.topobjdir).clobber_needed()
- def have_winrm(self):
- # `winrm -h` should print 'winrm version ...' and exit 1
- try:
- p = subprocess.Popen(['winrm.exe', '-h'],
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- return p.wait() == 1 and p.stdout.read().startswith('winrm')
- except:
- return False
-
- def remove_objdir(self, full=True):
- """Remove the object directory.
-
- ``full`` controls whether to fully delete the objdir. If False,
- some directories (e.g. Visual Studio Project Files) will not be
- deleted.
- """
- # Top-level files and directories to not clobber by default.
- no_clobber = {
- '.mozbuild',
- 'msvc',
- }
-
- if full:
- # mozfile doesn't like unicode arguments (bug 818783).
- paths = [self.topobjdir.encode('utf-8')]
- else:
- try:
- paths = []
- for p in os.listdir(self.topobjdir):
- if p not in no_clobber:
- paths.append(os.path.join(self.topobjdir, p).encode('utf-8'))
- except OSError as e:
- if e.errno != errno.ENOENT:
- raise
- return
-
- procs = []
- for p in sorted(paths):
- path = os.path.join(self.topobjdir, p)
- if sys.platform.startswith('win') and self.have_winrm() and os.path.isdir(path):
- procs.append(subprocess.Popen(['winrm', '-rf', path]))
- else:
- # We use mozfile because it is faster than shutil.rmtree().
- mozfileremove(path)
-
- for p in procs:
- p.wait()
-
def get_binary_path(self, what='app', validate_exists=True, where='default'):
"""Obtain the path to a compiled binary for this build configuration.
The what argument is the program or tool being sought after. See the
code implementation for supported values.
If validate_exists is True (the default), we will ensure the found path
exists before returning, raising an exception if it doesn't.
--- a/python/mozbuild/mozbuild/controller/clobber.py
+++ b/python/mozbuild/mozbuild/controller/clobber.py
@@ -1,20 +1,22 @@
# 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
r'''This module contains code for managing clobbering of the tree.'''
+import errno
import os
+import subprocess
import sys
-from mozfile.mozfile import rmtree
+from mozfile.mozfile import remove as mozfileremove
from textwrap import TextWrapper
CLOBBER_MESSAGE = ''.join([TextWrapper().fill(line) + '\n' for line in
'''
The CLOBBER file has been updated, indicating that an incremental build since \
your last build will probably not work. A full/clobber build is required.
@@ -80,16 +82,65 @@ class Clobberer(object):
This returns a list of lines describing why the clobber was required.
Each line is stripped of leading and trailing whitespace.
"""
with open(self.src_clobber, 'rt') as fh:
lines = [l.strip() for l in fh.readlines()]
return [l for l in lines if l and not l.startswith('#')]
+ def have_winrm(self):
+ # `winrm -h` should print 'winrm version ...' and exit 1
+ try:
+ p = subprocess.Popen(['winrm.exe', '-h'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ return p.wait() == 1 and p.stdout.read().startswith('winrm')
+ except:
+ return False
+
+ def remove_objdir(self, full=True):
+ """Remove the object directory.
+
+ ``full`` controls whether to fully delete the objdir. If False,
+ some directories (e.g. Visual Studio Project Files) will not be
+ deleted.
+ """
+ # Top-level files and directories to not clobber by default.
+ no_clobber = {
+ '.mozbuild',
+ 'msvc',
+ }
+
+ if full:
+ # mozfile doesn't like unicode arguments (bug 818783).
+ paths = [self.topobjdir.encode('utf-8')]
+ else:
+ try:
+ paths = []
+ for p in os.listdir(self.topobjdir):
+ if p not in no_clobber:
+ paths.append(os.path.join(self.topobjdir, p).encode('utf-8'))
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ return
+
+ procs = []
+ for p in sorted(paths):
+ path = os.path.join(self.topobjdir, p)
+ if sys.platform.startswith('win') and self.have_winrm() and os.path.isdir(path):
+ procs.append(subprocess.Popen(['winrm', '-rf', path]))
+ else:
+ # We use mozfile because it is faster than shutil.rmtree().
+ mozfileremove(path)
+
+ for p in procs:
+ p.wait()
+
def ensure_objdir_state(self):
"""Ensure the CLOBBER file in the objdir exists.
This is called as part of the build to ensure the clobber information
is configured properly for the objdir.
"""
if not os.path.exists(self.topobjdir):
os.makedirs(self.topobjdir)
@@ -135,28 +186,17 @@ class Clobberer(object):
'mozconfig).')
if cwd.startswith(self.topobjdir) and cwd != self.topobjdir:
return True, False, self._message(
'Cannot clobber while the shell is inside the object directory.')
print('Automatically clobbering %s' % self.topobjdir, file=fh)
try:
- if cwd == self.topobjdir:
- for entry in os.listdir(self.topobjdir):
- full = os.path.join(self.topobjdir, entry)
-
- if os.path.isdir(full):
- rmtree(full)
- else:
- os.unlink(full)
-
- else:
- rmtree(self.topobjdir)
-
+ self.remove_objdir(False)
self.ensure_objdir_state()
print('Successfully completed auto clobber.', file=fh)
return True, True, None
except (IOError) as error:
return True, False, self._message(
'Error when automatically clobbering: ' + str(error))
def _message(self, reason):
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -30,16 +30,17 @@ from mozbuild.base import (
BuildEnvironmentNotFoundException,
MachCommandBase,
MachCommandConditions as conditions,
MozbuildObject,
MozconfigFindException,
MozconfigLoadException,
ObjdirMismatchException,
)
+from mozbuild.controller.clobber import Clobberer
from mozpack.manifests import (
InstallManifest,
)
from mozbuild.backend import backends
from mozbuild.shellutil import quote as shell_quote
@@ -637,17 +638,17 @@ class Clobber(MachCommandBase):
invalid = set(what) - set(self.CLOBBER_CHOICES)
if invalid:
print('Unknown clobber target(s): {}'.format(', '.join(invalid)))
return 1
ret = 0
if 'objdir' in what:
try:
- self.remove_objdir(full=full)
+ Clobberer(self.topsrcdir, self.topobjdir).remove_objdir(full)
except OSError as e:
if sys.platform.startswith('win'):
if isinstance(e, WindowsError) and e.winerror in (5,32):
self.log(logging.ERROR, 'file_access_error', {'error': e},
"Could not clobber because a file was in use. If the "
"application is running, try closing it. {error}")
return 1
raise