Diff
Modified: trunk/Tools/ChangeLog (100103 => 100104)
--- trunk/Tools/ChangeLog 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/ChangeLog 2011-11-14 08:07:55 UTC (rev 100104)
@@ -1,3 +1,38 @@
+2011-11-13 Eric Seidel <[email protected]>
+
+ Add SCMDetector object to make scm detection mockable
+ https://bugs.webkit.org/show_bug.cgi?id=72247
+
+ Reviewed by Adam Barth.
+
+ I think SCM detection may eventually be rolled into Checkout,
+ but this patch at least makes it possible to mock code-paths
+ which rely on scm detection.
+ In the process of replacing callers of these free-functions
+ I found that one of the functions was no longer used,
+ and that one of the callers could instead just use the SCM
+ object it already had access to through port.host.scm().
+ I also discovered that I was not calling Host._initialize_scm()
+ and thus host.scm() was always returning None!
+
+ * Scripts/check-webkit-style:
+ * Scripts/webkitpy/common/checkout/checkout_unittest.py:
+ * Scripts/webkitpy/common/checkout/deps.py:
+ * Scripts/webkitpy/common/checkout/scm/__init__.py:
+ * Scripts/webkitpy/common/checkout/scm/detection.py:
+ * Scripts/webkitpy/common/checkout/scm/git.py:
+ * Scripts/webkitpy/common/checkout/scm/scm_unittest.py:
+ * Scripts/webkitpy/common/checkout/scm/svn.py:
+ * Scripts/webkitpy/common/host.py:
+ * Scripts/webkitpy/common/host_mock.py:
+ * Scripts/webkitpy/layout_tests/controllers/manager.py:
+ * Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py:
+ * Scripts/webkitpy/layout_tests/port/base.py:
+ * Scripts/webkitpy/layout_tests/port/mock_drt.py:
+ * Scripts/webkitpy/layout_tests/run_webkit_tests.py:
+ * Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py:
+ * Scripts/webkitpy/tool/servers/rebaselineserver.py:
+
2011-11-13 Gavin Peters <[email protected]>
command line control of webcore log channels in chromium DumpRenderTree
Modified: trunk/Tools/Scripts/check-webkit-style (100103 => 100104)
--- trunk/Tools/Scripts/check-webkit-style 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/check-webkit-style 2011-11-14 08:07:55 UTC (rev 100104)
@@ -48,7 +48,7 @@
import os.path
import sys
-from webkitpy.common.checkout.scm import detect_scm_system
+from webkitpy.common.checkout.scm.detection import detect_scm_system
import webkitpy.style.checker as checker
from webkitpy.style.patchreader import PatchReader
from webkitpy.style.checker import StyleProcessor
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -36,21 +36,15 @@
from .checkout import Checkout
from .changelog import ChangeLogEntry
-from .scm import detect_scm_system, CommitMessage
+from .scm import CommitMessage, SCMDetector
from .scm.scm_mock import MockSCM
from webkitpy.common.system.executive import Executive, ScriptError
+from webkitpy.common.system.filesystem import FileSystem # FIXME: This should not be needed.
from webkitpy.common.system.filesystem_mock import MockFileSystem
from webkitpy.common.system.executive_mock import MockExecutive
from webkitpy.thirdparty.mock import Mock
-
-# FIXME: Copied from scm_unittest.py
-def write_into_file_at_path(file_path, contents, encoding="utf-8"):
- with codecs.open(file_path, "w", encoding) as file:
- file.write(contents)
-
-
_changelog1entry1 = u"""2010-03-25 Tor Arne Vestb\u00f8 <[email protected]>
Unreviewed build fix to un-break webkit-patch land.
@@ -103,35 +97,39 @@
"""
def setUp(self):
- self.temp_dir = tempfile.mkdtemp(suffix="changelogs")
- self.old_cwd = os.getcwd()
- os.chdir(self.temp_dir)
+ # FIXME: This should not need to touch the filesystem, however
+ # ChangeLog is difficult to mock at current.
+ self.filesystem = FileSystem()
+ self.temp_dir = str(self.filesystem.mkdtemp(suffix="changelogs"))
+ self.old_cwd = self.filesystem.getcwd()
+ self.filesystem.chdir(self.temp_dir)
# Trick commit-log-editor into thinking we're in a Subversion working copy so it won't
# complain about not being able to figure out what SCM is in use.
- os.mkdir(".svn")
+ self.filesystem.maybe_make_directory(".svn")
- self.changelogs = map(os.path.abspath, (os.path.join("Tools", "ChangeLog"), os.path.join("LayoutTests", "ChangeLog")))
+ self.changelogs = map(self.filesystem.abspath, (self.filesystem.join("Tools", "ChangeLog"), self.filesystem.join("LayoutTests", "ChangeLog")))
for path, contents in zip(self.changelogs, (_changelog1, _changelog2)):
- os.makedirs(os.path.dirname(path))
- write_into_file_at_path(path, contents)
+ self.filesystem.maybe_make_directory(self.filesystem.dirname(path))
+ self.filesystem.write_text_file(path, contents)
def tearDown(self):
- shutil.rmtree(self.temp_dir, ignore_errors=True)
- os.chdir(self.old_cwd)
+ self.filesystem.rmtree(self.temp_dir)
+ self.filesystem.chdir(self.old_cwd)
- # FIXME: This should not need to touch the file system, however
- # ChangeLog is difficult to mock at current.
def test_commit_message_for_this_commit(self):
+ executive = Executive()
+
def mock_run(*args, **kwargs):
# Note that we use a real Executive here, not a MockExecutive, so we can test that we're
# invoking commit-log-editor correctly.
env = os.environ.copy()
env['CHANGE_LOG_EMAIL_ADDRESS'] = '[email protected]'
kwargs['env'] = env
- return Executive().run_command(*args, **kwargs)
+ return executive.run_command(*args, **kwargs)
- real_scm = detect_scm_system(self.old_cwd)
+ detector = SCMDetector(self.filesystem, executive)
+ real_scm = detector.detect_scm_system(self.old_cwd)
mock_scm = MockSCM()
mock_scm.run = mock_run
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/deps.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/deps.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/deps.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -30,7 +30,6 @@
import codecs
import fileinput
-import os.path
import re
import textwrap
@@ -40,6 +39,7 @@
_variable_regexp = r"\s+'%s':\s+'(?P<value>\d+)'"
def __init__(self, path):
+ # FIXME: This should take a FileSystem object.
self._path = path
def read_variable(self, name):
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/__init__.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/__init__.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/__init__.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -2,7 +2,7 @@
# We only export public API here.
from .commitmessage import CommitMessage
-from .detection import find_checkout_root, default_scm, detect_scm_system
+from .detection import SCMDetector
from .git import Git, AmbiguousCommitError
from .scm import SCM, AuthenticationError, CheckoutNeedsUpdate
from .svn import SVN
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/detection.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/detection.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/detection.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -27,58 +27,56 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import os
+from webkitpy.common.system.filesystem import FileSystem
+from webkitpy.common.system.executive import Executive
-from webkitpy.common.system.deprecated_logging import error, log
+from webkitpy.common.system.deprecated_logging import log
from .svn import SVN
from .git import Git
-def find_checkout_root():
- """Returns the current checkout root (as determined by default_scm().
+class SCMDetector(object):
+ def __init__(self, filesystem, executive):
+ self._filesystem = filesystem
+ self._executive = executive
- Returns the absolute path to the top of the WebKit checkout, or None
- if it cannot be determined.
+ def default_scm(self, patch_directories=None):
+ """Return the default SCM object as determined by the CWD and running code.
- """
- scm_system = default_scm()
- if scm_system:
- return scm_system.checkout_root
- return None
+ Returns the default SCM object for the current working directory; if the
+ CWD is not in a checkout, then we attempt to figure out if the SCM module
+ itself is part of a checkout, and return that one. If neither is part of
+ a checkout, None is returned.
+ """
+ cwd = self._filesystem.getcwd()
+ scm_system = self.detect_scm_system(cwd, patch_directories)
+ if not scm_system:
+ script_directory = self._filesystem.dirname(self._filesystem.path_to_module(self.__module__))
+ scm_system = self.detect_scm_system(script_directory, patch_directories)
+ if scm_system:
+ log("The current directory (%s) is not a WebKit checkout, using %s" % (cwd, scm_system.checkout_root))
+ else:
+ raise Exception("FATAL: Failed to determine the SCM system for either %s or %s" % (cwd, script_directory))
+ return scm_system
-def default_scm(patch_directories=None):
- """Return the default SCM object as determined by the CWD and running code.
+ def detect_scm_system(self, path, patch_directories=None):
+ absolute_path = self._filesystem.abspath(path)
- Returns the default SCM object for the current working directory; if the
- CWD is not in a checkout, then we attempt to figure out if the SCM module
- itself is part of a checkout, and return that one. If neither is part of
- a checkout, None is returned.
+ if patch_directories == []:
+ patch_directories = None
- """
- cwd = os.getcwd()
- scm_system = detect_scm_system(cwd, patch_directories)
- if not scm_system:
- script_directory = os.path.dirname(os.path.abspath(__file__))
- scm_system = detect_scm_system(script_directory, patch_directories)
- if scm_system:
- log("The current directory (%s) is not a WebKit checkout, using %s" % (cwd, scm_system.checkout_root))
- else:
- error("FATAL: Failed to determine the SCM system for either %s or %s" % (cwd, script_directory))
- return scm_system
+ if SVN.in_working_directory(absolute_path):
+ return SVN(cwd=absolute_path, patch_directories=patch_directories, filesystem=self._filesystem, executive=self._executive)
+ if Git.in_working_directory(absolute_path):
+ return Git(cwd=absolute_path, filesystem=self._filesystem, executive=self._executive)
-def detect_scm_system(path, patch_directories=None):
- absolute_path = os.path.abspath(path)
+ return None
- if patch_directories == []:
- patch_directories = None
- if SVN.in_working_directory(absolute_path):
- return SVN(cwd=absolute_path, patch_directories=patch_directories)
+# FIXME: These free functions are all deprecated:
- if Git.in_working_directory(absolute_path):
- return Git(cwd=absolute_path)
-
- return None
+def detect_scm_system(path, patch_directories=None):
+ return SCMDetector(FileSystem(), Executive()).detect_scm_system(path, patch_directories)
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/git.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -62,8 +62,8 @@
# 1 or 128, mostly.
ERROR_FILE_IS_MISSING = 128
- def __init__(self, cwd, executive=None):
- SCM.__init__(self, cwd, executive)
+ def __init__(self, cwd, **kwargs):
+ SCM.__init__(self, cwd, **kwargs)
self._check_git_architecture()
def _machine_is_64bit(self):
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -233,6 +233,7 @@
os.chdir(detect_scm_system(path).checkout_root)
+# FIXME: This should move to testing SCMDetector instead.
class StandaloneFunctionsTest(unittest.TestCase):
"""This class tests any standalone/top-level functions in the package."""
def setUp(self):
@@ -283,6 +284,7 @@
self.assertRaises(SystemExit, default_scm)
os.path.abspath = self.orig_abspath
+
# For testing the SCM baseclass directly.
class SCMClassTests(unittest.TestCase):
def setUp(self):
Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/svn.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -72,14 +72,14 @@
_svn_metadata_files = frozenset(['.svn', '_svn'])
- def __init__(self, cwd, patch_directories, executive=None):
- SCM.__init__(self, cwd, executive)
+ def __init__(self, cwd, patch_directories, **kwargs):
+ SCM.__init__(self, cwd, **kwargs)
self._bogus_dir = None
if patch_directories == []:
# FIXME: ScriptError is for Executive, this should probably be a normal Exception.
raise ScriptError(script_args=svn_info_args, message='Empty list of patch directories passed to SCM.__init__')
elif patch_directories == None:
- self._patch_directories = [ospath.relpath(cwd, self.checkout_root)]
+ self._patch_directories = [self._filesystem.relpath(cwd, self.checkout_root)]
else:
self._patch_directories = patch_directories
Modified: trunk/Tools/Scripts/webkitpy/common/host.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/host.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/host.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -29,7 +29,7 @@
from webkitpy.common.checkout import Checkout
-from webkitpy.common.checkout.scm import default_scm
+from webkitpy.common.checkout.scm.detection import SCMDetector
from webkitpy.common.memoized import memoized
from webkitpy.common.net import bugzilla, buildbot, web
from webkitpy.common.net.buildbot.chromiumbuildbot import ChromiumBuildBot
@@ -64,7 +64,8 @@
self.port_factory = PortFactory(self)
def _initialize_scm(self, patch_directories=None):
- self._scm = default_scm(patch_directories)
+ detector = SCMDetector(self.filesystem, self.executive)
+ self._scm = detector.default_scm(patch_directories)
self._checkout = Checkout(self.scm())
def scm(self):
Modified: trunk/Tools/Scripts/webkitpy/common/host_mock.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/common/host_mock.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/common/host_mock.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -66,6 +66,9 @@
self._watch_list = MockWatchList()
+ def _initialize_scm(self, patch_directories=None):
+ pass
+
def scm(self):
return self._scm
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -46,7 +46,6 @@
import sys
import time
-from webkitpy.common.checkout.scm import default_scm
from webkitpy.layout_tests.controllers import manager_worker_broker
from webkitpy.layout_tests.controllers import worker
from webkitpy.layout_tests.layout_package import json_layout_results_generator
@@ -231,14 +230,9 @@
results['has_wdiff'] = port_obj.wdiff_available()
results['has_pretty_patch'] = port_obj.pretty_patch_available()
try:
- results['revision'] = default_scm().head_svn_revision()
+ results['revision'] = port_obj.host.scm().head_svn_revision()
except Exception, e:
- # FIXME: We would like to warn here, but that would cause all passing_run integration tests
- # to fail, since they assert that we have no logging output.
- # The revision lookup always fails when running the tests since it tries to read from
- # "/mock-checkout" using the real file system (since there is no way to mock out detect_scm_system at current).
- # Once we fix detect_scm_system to use the mock file system we can add this log back.
- #_log.warn("Failed to determine svn revision for checkout (cwd: %s, webkit_base: %s), leaving 'revision' key blank in full_results.json.\n%s" % (port_obj._filesystem.getcwd(), port_obj.path_from_webkit_base(), e))
+ _log.warn("Failed to determine svn revision for checkout (cwd: %s, webkit_base: %s), leaving 'revision' key blank in full_results.json.\n%s" % (port_obj._filesystem.getcwd(), port_obj.path_from_webkit_base(), e))
# Handle cases where we're running outside of version control.
import traceback
_log.debug('Failed to learn head svn revision:')
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -255,6 +255,7 @@
# FIXME: This should get the Host from the owner of this object
# so this function can be properly mocked!
host = Host()
+ host._initialize_scm()
port_obj = host.port_factory.get(self._platform_name, options)
# The unix multiprocessing implementation clones the
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/base.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -37,7 +37,6 @@
import errno
import os
-from webkitpy.common.checkout.scm import detect_scm_system
from webkitpy.common.memoized import memoized
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/mock_drt.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -279,4 +279,5 @@
if __name__ == '__main__':
# FIXME: Why is this using a real Host object instead of MockHost?
host = Host()
+ host._initialize_scm()
sys.exit(main(sys.argv[1:], host, sys.stdin, sys.stdout, sys.stderr))
Modified: trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -430,6 +430,7 @@
def main():
options, args = parse_args()
host = Host()
+ host._initialize_scm()
port = host.port_factory.get(options.platform, options)
return run(port, options, args)
Modified: trunk/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/to_be_moved/rebaseline_chromium_webkit_tests.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -944,6 +944,7 @@
logger.addHandler(log_handler)
host = Host()
+ host._initialize_scm()
target_port_obj = host.port_factory.get(None, target_options)
host_port_obj = get_host_port_object(host.port_factory, options)
if not host_port_obj or not target_port_obj:
Modified: trunk/Tools/Scripts/webkitpy/tool/servers/rebaselineserver.py (100103 => 100104)
--- trunk/Tools/Scripts/webkitpy/tool/servers/rebaselineserver.py 2011-11-14 07:57:42 UTC (rev 100103)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/rebaselineserver.py 2011-11-14 08:07:55 UTC (rev 100104)
@@ -164,9 +164,8 @@
def get_test_baselines(test_file, test_config):
# FIXME: This seems like a hack. This only seems used to access the Port.expected_baselines logic.
class AllPlatformsPort(WebKitPort):
- def __init__(self):
- # FIXME: This should get the Host from the test_config to be mockable!
- WebKitPort.__init__(self, Host(), filesystem=test_config.filesystem)
+ def __init__(self, host):
+ WebKitPort.__init__(self, host)
self._platforms_by_directory = dict([(self._webkit_baseline_path(p), p) for p in test_config.platforms])
def baseline_search_path(self):
@@ -177,7 +176,11 @@
test_path = test_config.filesystem.join(test_config.layout_tests_directory, test_file)
- all_platforms_port = AllPlatformsPort()
+ # FIXME: This should get the Host from the test_config to be mockable!
+ host = Host()
+ host._initialize_scm()
+ host.filesystem = test_config.filesystem
+ all_platforms_port = AllPlatformsPort(host)
all_test_baselines = {}
for baseline_extension in ('.txt', '.checksum', '.png'):