2 # Copyright (c) 2010 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Update third_party/WebKit using git.
8 Under the assumption third_party/WebKit is a clone of git.webkit.org,
9 we can use git commands to make it match the version requested by DEPS.
11 See http://code.google.com/p/chromium/wiki/UsingWebKitGit for details on
23 """Run a git subcommand, returning its output."""
24 # On Windows, use shell=True to get PATH interpretation.
25 command
= ['git'] + command
26 logging
.info(' '.join(command
))
27 shell
= (os
.name
== 'nt')
28 proc
= subprocess
.Popen(command
, shell
=shell
, stdout
=subprocess
.PIPE
)
29 out
= proc
.communicate()[0].strip()
30 logging
.info('Returned "%s"' % out
)
33 def GetOverrideShortBranchName():
34 """Returns the user-configured override branch name, if any."""
35 override_config_name
= 'chromium.sync-branch'
36 return RunGit(['config', '--get', override_config_name
])
38 def GetGClientBranchName():
39 """Returns the name of the magic branch that lets us know that DEPS is
40 managing the update cycle."""
41 # Is there an override branch specified?
42 override_branch_name
= GetOverrideShortBranchName()
43 if not override_branch_name
:
44 return 'refs/heads/gclient' # No override, so return the default branch.
46 # Verify that the branch from config exists.
47 ref_branch
= 'refs/heads/' + override_branch_name
48 current_head
= RunGit(['show-ref', '--hash', ref_branch
])
52 # Inform the user about the problem and how to fix it.
53 print ("The specified override branch ('%s') doesn't appear to exist." %
55 print "Please fix your git config value '%s'." % overide_config_name
59 """Extract the 'webkit_revision' variable out of DEPS."""
60 locals = {'Var': lambda _
: locals["vars"][_
]}
61 execfile('DEPS', {}, locals)
62 return locals['vars']['webkit_revision']
64 def FindSVNRev(target_rev
):
65 """Map an SVN revision to a git hash.
66 Like 'git svn find-rev' but without the git-svn bits."""
68 # We iterate through the commit log looking for "git-svn-id" lines,
69 # which contain the SVN revision of that commit. We can stop once
70 # we've found our target (or hit a revision number lower than what
71 # we're looking for, indicating not found).
73 target_rev
= int(target_rev
)
75 # regexp matching the "commit" line from the log.
76 commit_re
= re
.compile(r
'^commit ([a-f\d]{40})$')
77 # regexp matching the git-svn line from the log.
78 git_svn_re
= re
.compile(r
'^\s+git-svn-id: [^@]+@(\d+) ')
79 cmd
= ['git', 'log', '--no-color', '--first-parent', '--pretty=medium',
81 logging
.info(' '.join(cmd
))
82 log
= subprocess
.Popen(cmd
, shell
=(os
.name
== 'nt'), stdout
=subprocess
.PIPE
)
83 # Track whether we saw a revision *later* than the one we're seeking.
85 for line
in log
.stdout
:
86 match
= commit_re
.match(line
)
88 commit
= match
.group(1)
90 match
= git_svn_re
.match(line
)
92 rev
= int(match
.group(1))
94 log
.stdout
.close() # Break pipe.
97 return None # Can't be sure whether this rev is ok.
98 print ("WARNING: r%d not found, so using next nearest earlier r%d" %
104 print "Error: reached end of log without finding commit info."
105 print "Something has likely gone horribly wrong."
109 branch
= GetOverrideShortBranchName()
113 remote
= RunGit(['config', '--get', 'branch.' + branch
+ '.remote'])
118 def UpdateGClientBranch(webkit_rev
, magic_gclient_branch
):
119 """Update the magic gclient branch to point at |webkit_rev|.
121 Returns: true if the branch didn't need changes."""
122 target
= FindSVNRev(webkit_rev
)
124 print "r%s not available; fetching." % webkit_rev
125 subprocess
.check_call(['git', 'fetch', GetRemote()],
126 shell
=(os
.name
== 'nt'))
127 target
= FindSVNRev(webkit_rev
)
129 print "ERROR: Couldn't map r%s to a git revision." % webkit_rev
132 current
= RunGit(['show-ref', '--hash', magic_gclient_branch
])
133 if current
== target
:
134 return False # No change necessary.
136 subprocess
.check_call(['git', 'update-ref', '-m', 'gclient sync',
137 magic_gclient_branch
, target
],
138 shell
=(os
.name
== 'nt'))
141 def UpdateCurrentCheckoutIfAppropriate(magic_gclient_branch
):
142 """Reset the current gclient branch if that's what we have checked out."""
143 branch
= RunGit(['symbolic-ref', '-q', 'HEAD'])
144 if branch
!= magic_gclient_branch
:
145 print "We have now updated the 'gclient' branch, but third_party/WebKit"
146 print "has some other branch ('%s') checked out." % branch
147 print "Run 'git checkout gclient' under third_party/WebKit if you want"
148 print "to switch it to the version requested by DEPS."
151 if subprocess
.call(['git', 'diff-index', '--exit-code', '--shortstat',
152 'HEAD'], shell
=(os
.name
== 'nt')):
153 print "Resetting tree state to new revision."
154 subprocess
.check_call(['git', 'reset', '--hard'], shell
=(os
.name
== 'nt'))
157 parser
= optparse
.OptionParser()
158 parser
.add_option('-v', '--verbose', action
='store_true')
159 options
, args
= parser
.parse_args()
161 logging
.basicConfig(level
=logging
.INFO
)
162 if not os
.path
.exists('third_party/WebKit/.git'):
163 if os
.path
.exists('third_party/WebKit'):
164 print "ERROR: third_party/WebKit appears to not be under git control."
166 print "ERROR: third_party/WebKit could not be found."
167 print "Did you run this script from the right directory?"
169 print "See http://code.google.com/p/chromium/wiki/UsingWebKitGit for"
170 print "setup instructions."
173 webkit_rev
= GetWebKitRev()
174 print 'Desired revision: r%s.' % webkit_rev
175 os
.chdir('third_party/WebKit')
176 magic_gclient_branch
= GetGClientBranchName()
177 changed
= UpdateGClientBranch(webkit_rev
, magic_gclient_branch
)
179 return UpdateCurrentCheckoutIfAppropriate(magic_gclient_branch
)
181 print "Already on correct revision."
184 if __name__
== '__main__':