2 # Copyright (c) 2011 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 'From': lambda *args
: None}
62 execfile('DEPS', {}, locals)
63 return locals['vars']['webkit_revision']
65 def FindSVNRev(target_rev
):
66 """Map an SVN revision to a git hash.
67 Like 'git svn find-rev' but without the git-svn bits."""
69 # We iterate through the commit log looking for "git-svn-id" lines,
70 # which contain the SVN revision of that commit. We can stop once
71 # we've found our target (or hit a revision number lower than what
72 # we're looking for, indicating not found).
74 target_rev
= int(target_rev
)
76 # regexp matching the "commit" line from the log.
77 commit_re
= re
.compile(r
'^commit ([a-f\d]{40})$')
78 # regexp matching the git-svn line from the log.
79 git_svn_re
= re
.compile(r
'^\s+git-svn-id: [^@]+@(\d+) ')
80 cmd
= ['git', 'log', '--no-color', '--first-parent', '--pretty=medium',
82 logging
.info(' '.join(cmd
))
83 log
= subprocess
.Popen(cmd
, shell
=(os
.name
== 'nt'), stdout
=subprocess
.PIPE
)
84 # Track whether we saw a revision *later* than the one we're seeking.
86 for line
in log
.stdout
:
87 match
= commit_re
.match(line
)
89 commit
= match
.group(1)
91 match
= git_svn_re
.match(line
)
93 rev
= int(match
.group(1))
95 log
.stdout
.close() # Break pipe.
98 return None # Can't be sure whether this rev is ok.
99 print ("WARNING: r%d not found, so using next nearest earlier r%d" %
105 print "Error: reached end of log without finding commit info."
106 print "Something has likely gone horribly wrong."
110 branch
= GetOverrideShortBranchName()
114 remote
= RunGit(['config', '--get', 'branch.' + branch
+ '.remote'])
119 def UpdateGClientBranch(webkit_rev
, magic_gclient_branch
):
120 """Update the magic gclient branch to point at |webkit_rev|.
122 Returns: true if the branch didn't need changes."""
123 target
= FindSVNRev(webkit_rev
)
125 print "r%s not available; fetching." % webkit_rev
126 subprocess
.check_call(['git', 'fetch', GetRemote()],
127 shell
=(os
.name
== 'nt'))
128 target
= FindSVNRev(webkit_rev
)
130 print "ERROR: Couldn't map r%s to a git revision." % webkit_rev
133 current
= RunGit(['show-ref', '--hash', magic_gclient_branch
])
134 if current
== target
:
135 return False # No change necessary.
137 subprocess
.check_call(['git', 'update-ref', '-m', 'gclient sync',
138 magic_gclient_branch
, target
],
139 shell
=(os
.name
== 'nt'))
142 def UpdateCurrentCheckoutIfAppropriate(magic_gclient_branch
):
143 """Reset the current gclient branch if that's what we have checked out."""
144 branch
= RunGit(['symbolic-ref', '-q', 'HEAD'])
145 if branch
!= magic_gclient_branch
:
146 print "We have now updated the 'gclient' branch, but third_party/WebKit"
147 print "has some other branch ('%s') checked out." % branch
148 print "Run 'git checkout gclient' under third_party/WebKit if you want"
149 print "to switch it to the version requested by DEPS."
152 if subprocess
.call(['git', 'diff-index', '--exit-code', '--shortstat',
153 'HEAD'], shell
=(os
.name
== 'nt')):
154 print "Resetting tree state to new revision."
155 subprocess
.check_call(['git', 'reset', '--hard'], shell
=(os
.name
== 'nt'))
158 parser
= optparse
.OptionParser()
159 parser
.add_option('-v', '--verbose', action
='store_true')
160 options
, args
= parser
.parse_args()
162 logging
.basicConfig(level
=logging
.INFO
)
163 if not os
.path
.exists('third_party/WebKit/.git'):
164 if os
.path
.exists('third_party/WebKit'):
165 print "ERROR: third_party/WebKit appears to not be under git control."
167 print "ERROR: third_party/WebKit could not be found."
168 print "Did you run this script from the right directory?"
170 print "See http://code.google.com/p/chromium/wiki/UsingWebKitGit for"
171 print "setup instructions."
174 webkit_rev
= GetWebKitRev()
175 print 'Desired revision: r%s.' % webkit_rev
176 os
.chdir('third_party/WebKit')
177 magic_gclient_branch
= GetGClientBranchName()
178 changed
= UpdateGClientBranch(webkit_rev
, magic_gclient_branch
)
180 return UpdateCurrentCheckoutIfAppropriate(magic_gclient_branch
)
182 print "Already on correct revision."
185 if __name__
== '__main__':