summaryrefslogtreecommitdiffstats
path: root/WebKitTools/Scripts/webkitpy/common
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-05-26 10:11:43 +0100
committerSteve Block <steveblock@google.com>2010-05-27 11:14:42 +0100
commite78cbe89e6f337f2f1fe40315be88f742b547151 (patch)
treed778000b84a04f24bbad50c7fa66244365e960e9 /WebKitTools/Scripts/webkitpy/common
parent7b582e96e4e909ed7dba1e07153d20fbddaec3f7 (diff)
downloadexternal_webkit-e78cbe89e6f337f2f1fe40315be88f742b547151.zip
external_webkit-e78cbe89e6f337f2f1fe40315be88f742b547151.tar.gz
external_webkit-e78cbe89e6f337f2f1fe40315be88f742b547151.tar.bz2
Merge WebKit at r60074: Initial merge by git
Change-Id: I18a2dc5439e36c928351ea829d8fb4e39b062fc7
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/common')
-rw-r--r--WebKitTools/Scripts/webkitpy/common/checkout/scm.py43
-rw-r--r--WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py18
-rw-r--r--WebKitTools/Scripts/webkitpy/common/config/committers.py3
-rw-r--r--WebKitTools/Scripts/webkitpy/common/net/bugzilla.py28
-rw-r--r--WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py4
-rw-r--r--WebKitTools/Scripts/webkitpy/common/net/statusserver.py17
-rw-r--r--WebKitTools/Scripts/webkitpy/common/system/executive.py17
-rw-r--r--WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py9
-rw-r--r--WebKitTools/Scripts/webkitpy/common/system/user.py1
-rw-r--r--WebKitTools/Scripts/webkitpy/common/thread/threadedmessagequeue.py21
10 files changed, 129 insertions, 32 deletions
diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py
index ac9c42e..e68ccfa 100644
--- a/WebKitTools/Scripts/webkitpy/common/checkout/scm.py
+++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm.py
@@ -584,25 +584,32 @@ class Git(SCM):
def revert_files(self, file_paths):
self.run(['git', 'checkout', 'HEAD'] + file_paths)
+ def _get_squash_error_message(self, num_local_commits):
+ working_directory_message = "" if self.working_directory_is_clean() else " and working copy changes"
+ return ("""There are %s local commits%s. Do one of the following:
+ 1) Use --squash or --no-squash
+ 2) git config webkit-patch.squash true/false
+ """ % (num_local_commits, working_directory_message))
+
def should_squash(self, squash):
- if squash is not None:
- # Squash is specified on the command-line.
- return squash
-
- config_squash = Git.read_git_config('webkit-patch.squash')
- if (config_squash and config_squash is not ""):
- return config_squash.lower() == "true"
-
- # Only raise an error if there are actually multiple commits to squash.
- num_local_commits = len(self.local_commits())
- if num_local_commits > 1 or num_local_commits > 0 and not self.working_directory_is_clean():
- working_directory_message = "" if self.working_directory_is_clean() else " and working copy changes"
- raise ScriptError(message="""There are %s local commits%s. Do one of the following:
-1) Use --squash or --no-squash
-2) git config webkit-patch.squash true/false
-""" % (num_local_commits, working_directory_message))
-
- return None
+ if squash is None:
+ config_squash = Git.read_git_config('webkit-patch.squash')
+ if (config_squash and config_squash is not ""):
+ squash = config_squash.lower() == "true"
+ else:
+ # Only raise an error if there are actually multiple commits to squash.
+ num_local_commits = len(self.local_commits())
+ if num_local_commits > 1 or (num_local_commits > 0 and not self.working_directory_is_clean()):
+ raise ScriptError(message=self._get_squash_error_message(num_local_commits))
+
+ if squash and self._svn_branch_has_extra_commits():
+ raise ScriptError(message="Cannot use --squash when HEAD is not fully merged/rebased to %s. "
+ "This branch needs to be synced first." % self.svn_branch_name())
+
+ return squash
+
+ def _svn_branch_has_extra_commits(self):
+ return len(run_command(['git', 'rev-list', '--max-count=1', self.svn_branch_name(), '^head']))
def commit_with_message(self, message, username=None, git_commit=None, squash=None):
# Username is ignored during Git commits.
diff --git a/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py b/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py
index 5a2c094..b6ae388 100644
--- a/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/checkout/scm_unittest.py
@@ -875,6 +875,12 @@ class GitTest(SCMTest):
self.assertTrue(re.search(r'test_file_commit2', svn_log))
self.assertTrue(re.search(r'test_file_commit1', svn_log))
+ def test_commit_with_message_not_synced_squash(self):
+ run_command(['git', 'checkout', '-b', 'my-branch', 'trunk~3'])
+ self._two_local_commits()
+ scm = detect_scm_system(self.git_checkout_path)
+ self.assertRaises(ScriptError, scm.commit_with_message, "another test commit", squash=True)
+
def test_reverse_diff(self):
self._shared_test_reverse_diff()
@@ -937,6 +943,12 @@ class GitTest(SCMTest):
self.assertTrue(re.search(r'test_file_commit2', patch))
self.assertTrue(re.search(r'test_file_commit1', patch))
+ def test_create_patch_not_synced_squash(self):
+ run_command(['git', 'checkout', '-b', 'my-branch', 'trunk~3'])
+ self._two_local_commits()
+ scm = detect_scm_system(self.git_checkout_path)
+ self.assertRaises(ScriptError, scm.create_patch, squash=True)
+
def test_create_binary_patch(self):
# Create a git binary patch and check the contents.
scm = detect_scm_system(self.git_checkout_path)
@@ -1016,6 +1028,12 @@ class GitTest(SCMTest):
self.assertTrue('test_file_commit2' in files)
self.assertTrue('test_file_commit1' in files)
+ def test_changed_files_not_synced_squash(self):
+ run_command(['git', 'checkout', '-b', 'my-branch', 'trunk~3'])
+ self._two_local_commits()
+ scm = detect_scm_system(self.git_checkout_path)
+ self.assertRaises(ScriptError, scm.changed_files, squash=True)
+
def test_changed_files(self):
self._shared_test_changed_files()
diff --git a/WebKitTools/Scripts/webkitpy/common/config/committers.py b/WebKitTools/Scripts/webkitpy/common/config/committers.py
index c33d2a6..02f1aed 100644
--- a/WebKitTools/Scripts/webkitpy/common/config/committers.py
+++ b/WebKitTools/Scripts/webkitpy/common/config/committers.py
@@ -85,6 +85,7 @@ committers_unable_to_review = [
Committer("Cameron McCormack", "cam@webkit.org", "heycam"),
Committer("Carol Szabo", "carol.szabo@nokia.com"),
Committer("Chang Shu", "Chang.Shu@nokia.com"),
+ Committer("Chris Evans", "cevans@google.com"),
Committer("Chris Fleizach", "cfleizach@apple.com"),
Committer("Chris Marrin", "cmarrin@apple.com", "cmarrin"),
Committer("Chris Petersen", "cpetersen@apple.com", "cpetersen"),
@@ -163,7 +164,7 @@ committers_unable_to_review = [
Committer("Xiaomei Ji", "xji@chromium.org", "xji"),
Committer("Yael Aharon", "yael.aharon@nokia.com"),
Committer("Yaar Schnitman", ["yaar@chromium.org", "yaar@google.com"]),
- Committer("Yong Li", ["yong.li@torchmobile.com", "yong.li.webkit@gmail.com"], "yong"),
+ Committer("Yong Li", ["yong.li.webkit@gmail.com", "yong.li@torchmobile.com"], "yong"),
Committer("Yongjun Zhang", "yongjun.zhang@nokia.com"),
Committer("Yuzo Fujishima", "yuzo@google.com", "yuzo"),
Committer("Zoltan Herczeg", "zherczeg@webkit.org", "zherczeg"),
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py
index 074a021..26d3652 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla.py
@@ -104,6 +104,9 @@ class Attachment(object):
def name(self):
return self._attachment_dictionary.get("name")
+ def attach_date(self):
+ return self._attachment_dictionary.get("attach_date")
+
def review(self):
return self._attachment_dictionary.get("review")
@@ -430,6 +433,7 @@ class Bugzilla(object):
attachment[flag_name] = flag['status']
if flag['status'] == '+':
attachment[result_key] = flag['setter']
+ # Sadly show_bug.cgi?ctype=xml does not expose the flag modification date.
def _string_contents(self, soup):
# WebKit's bugzilla instance uses UTF-8.
@@ -439,8 +443,23 @@ class Bugzilla(object):
# convert from NavigableString to a real unicode() object using unicode().
return unicode(soup.string)
- def _parse_attachment_element(self, element, bug_id):
+ # Example: 2010-01-20 14:31 PST
+ # FIXME: Some bugzilla dates seem to have seconds in them?
+ # Python does not support timezones out of the box.
+ # Assume that bugzilla always uses PST (which is true for bugs.webkit.org)
+ _bugzilla_date_format = "%Y-%m-%d %H:%M"
+
+ @classmethod
+ def _parse_date(cls, date_string):
+ (date, time, time_zone) = date_string.split(" ")
+ # Ignore the timezone because python doesn't understand timezones out of the box.
+ date_string = "%s %s" % (date, time)
+ return datetime.strptime(date_string, cls._bugzilla_date_format)
+ def _date_contents(self, soup):
+ return self._parse_date(self._string_contents(soup))
+
+ def _parse_attachment_element(self, element, bug_id):
attachment = {}
attachment['bug_id'] = bug_id
attachment['is_obsolete'] = (element.has_key('isobsolete') and element['isobsolete'] == "1")
@@ -448,6 +467,7 @@ class Bugzilla(object):
attachment['id'] = int(element.find('attachid').string)
# FIXME: No need to parse out the url here.
attachment['url'] = self.attachment_url_for_id(attachment['id'])
+ attachment["attach_date"] = self._date_contents(element.find("date"))
attachment['name'] = self._string_contents(element.find('desc'))
attachment['attacher_email'] = self._string_contents(element.find('attacher'))
attachment['type'] = self._string_contents(element.find('type'))
@@ -564,6 +584,7 @@ class Bugzilla(object):
raise Exception(errorMessage)
else:
self.authenticated = True
+ self.username = username
def _fill_attachment_form(self,
description,
@@ -657,6 +678,7 @@ class Bugzilla(object):
patch_description=None,
cc=None,
blocked=None,
+ assignee=None,
mark_for_review=False,
mark_for_commit_queue=False):
self.authenticate()
@@ -679,6 +701,10 @@ class Bugzilla(object):
self.browser["cc"] = cc
if blocked:
self.browser["blocked"] = unicode(blocked)
+ if assignee == None:
+ assignee = self.username
+ if assignee:
+ self.browser["assigned_to"] = assignee
self.browser["short_desc"] = bug_title
self.browser["comment"] = bug_description
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py
index 62a0746..ce992e7 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla_unittest.py
@@ -28,6 +28,8 @@
import unittest
+import datetime
+
from webkitpy.common.config.committers import CommitterList, Reviewer, Committer
from webkitpy.common.net.bugzilla import Bugzilla, BugzillaQueries, parse_bug_id, CommitterValidator, Bug
from webkitpy.common.system.outputcapture import OutputCapture
@@ -97,6 +99,7 @@ class BugzillaTest(unittest.TestCase):
</attachment>
'''
_expected_example_attachment_parsing = {
+ 'attach_date': datetime.datetime(2009, 07, 29, 10, 23),
'bug_id' : 100,
'is_obsolete' : True,
'is_patch' : True,
@@ -204,6 +207,7 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg==
"reporter_email" : "eric@webkit.org",
"assigned_to_email" : "webkit-unassigned@lists.webkit.org",
"attachments" : [{
+ "attach_date": datetime.datetime(2009, 12, 27, 23, 51),
'name': u'Patch',
'url' : "https://bugs.webkit.org/attachment.cgi?id=45548",
'is_obsolete': False,
diff --git a/WebKitTools/Scripts/webkitpy/common/net/statusserver.py b/WebKitTools/Scripts/webkitpy/common/net/statusserver.py
index d9b52a2..0bd68d1 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/statusserver.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/statusserver.py
@@ -31,9 +31,13 @@ from webkitpy.common.system.deprecated_logging import log
from webkitpy.thirdparty.autoinstalled.mechanize import Browser
from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
+import logging
import urllib2
+_log = logging.getLogger("webkitpy.common.net.statusserver")
+
+
class StatusServer:
default_host = "webkit-commit-queue.appspot.com"
@@ -83,6 +87,19 @@ class StatusServer:
self.browser["broken_bot"] = broken_bot
return self.browser.submit().read()
+ def _post_work_items_to_server(self, queue_name, work_items):
+ update_work_items_url = "%s/update-work-items" % self.url
+ self.browser.open(update_work_items_url)
+ self.browser.select_form(name="update_work_items")
+ self.browser["queue_name"] = queue_name
+ work_items = map(unicode, work_items) # .join expects strings
+ self.browser["work_items"] = " ".join(work_items)
+ return self.browser.submit().read()
+
+ def update_work_items(self, queue_name, work_items):
+ _log.debug("Recording work items: %s for %s" % (work_items, queue_name))
+ return NetworkTransaction().run(lambda: self._post_work_items_to_server(queue_name, work_items))
+
def update_status(self, queue_name, status, patch=None, results_file=None):
log(status)
return NetworkTransaction().run(lambda: self._post_status_to_server(queue_name, status, patch, results_file))
diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive.py b/WebKitTools/Scripts/webkitpy/common/system/executive.py
index c7a7aec..9c5889b 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/executive.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/executive.py
@@ -41,6 +41,7 @@ import StringIO
import signal
import subprocess
import sys
+import time
from webkitpy.common.system.deprecated_logging import tee
@@ -255,6 +256,18 @@ class Executive(object):
input = input.encode("utf-8")
return (subprocess.PIPE, input)
+ def _command_for_printing(self, args):
+ """Returns a print-ready string representing command args.
+ The string should be copy/paste ready for execution in a shell."""
+ escaped_args = []
+ for arg in args:
+ if isinstance(arg, unicode):
+ # Escape any non-ascii characters for easy copy/paste
+ arg = arg.encode("unicode_escape")
+ # FIXME: Do we need to fix quotes here?
+ escaped_args.append(arg)
+ return " ".join(escaped_args)
+
# FIXME: run_and_throw_if_fail should be merged into this method.
def run_command(self,
args,
@@ -265,6 +278,8 @@ class Executive(object):
return_stderr=True,
decode_output=True):
"""Popen wrapper for convenience and to work around python bugs."""
+ assert(isinstance(args, list) or isinstance(args, tuple))
+ start_time = time.time()
args = map(unicode, args) # Popen will throw an exception if args are non-strings (like int())
stdin, string_to_communicate = self._compute_stdin(input)
stderr = subprocess.STDOUT if return_stderr else None
@@ -283,6 +298,8 @@ class Executive(object):
# http://bugs.python.org/issue1731717
exit_code = process.wait()
+ _log.debug('"%s" took %.2fs' % (self._command_for_printing(args), time.time() - start_time))
+
if return_exit_code:
return exit_code
diff --git a/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py b/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py
index 30468ce..32f8f51 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/executive_unittest.py
@@ -32,7 +32,7 @@ import subprocess
import sys
import unittest
-from webkitpy.common.system.executive import Executive, run_command
+from webkitpy.common.system.executive import Executive, run_command, ScriptError
class ExecutiveTest(unittest.TestCase):
@@ -42,6 +42,13 @@ class ExecutiveTest(unittest.TestCase):
run_command(["foo_bar_command_blah"], error_handler=Executive.ignore_error, return_exit_code=True)
self.failUnlessRaises(OSError, run_bad_command)
+ def test_run_command_args_type(self):
+ executive = Executive()
+ self.assertRaises(AssertionError, executive.run_command, "echo")
+ self.assertRaises(AssertionError, executive.run_command, u"echo")
+ executive.run_command(["echo", "foo"])
+ executive.run_command(("echo", "foo"))
+
def test_run_command_with_unicode(self):
"""Validate that it is safe to pass unicode() objects
to Executive.run* methods, and they will return unicode()
diff --git a/WebKitTools/Scripts/webkitpy/common/system/user.py b/WebKitTools/Scripts/webkitpy/common/system/user.py
index edce93d..4fa2fa3 100644
--- a/WebKitTools/Scripts/webkitpy/common/system/user.py
+++ b/WebKitTools/Scripts/webkitpy/common/system/user.py
@@ -30,6 +30,7 @@ import logging
import os
import shlex
import subprocess
+import sys
import webbrowser
diff --git a/WebKitTools/Scripts/webkitpy/common/thread/threadedmessagequeue.py b/WebKitTools/Scripts/webkitpy/common/thread/threadedmessagequeue.py
index 6cb6f8c..17b6277 100644
--- a/WebKitTools/Scripts/webkitpy/common/thread/threadedmessagequeue.py
+++ b/WebKitTools/Scripts/webkitpy/common/thread/threadedmessagequeue.py
@@ -26,6 +26,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+from __future__ import with_statement
+
import threading
@@ -36,20 +38,17 @@ class ThreadedMessageQueue(object):
self._lock = threading.Lock()
def post(self, message):
- self._lock.acquire()
- self._messages.append(message)
- self._lock.release()
+ with self._lock:
+ self._messages.append(message)
def stop(self):
- self._lock.acquire()
- self._is_running = False
- self._lock.release()
+ with self._lock:
+ self._is_running = False
def take_all(self):
- self._lock.acquire()
- messages = self._messages
- is_running = self._is_running
- self._messages = []
- self._lock.release()
+ with self._lock:
+ messages = self._messages
+ is_running = self._is_running
+ self._messages = []
return (messages, is_running)