Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: tools/git-sync-deps

Issue 191133005: git-sync-deps tool (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: AnotherPatchSet Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « docs/quickstart.md ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright 2014 Google Inc.
3 #
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7
8 """Parse a DEPS file and git checkout all of the dependencies.
9
10 Args:
11 An optional list of deps_os values.
12
13 Environment Variables:
epoger 2014/04/14 19:32:14 Maybe it would be more straightforward to use argp
14 GIT_EXECUTABLE if git, git.exe, or git.bat isn't in your path, use this
epoger 2014/04/14 19:32:14 I think this would be more accurate: GIT_EXECUTAB
hal.canary 2014/04/16 18:46:19 Done.
15 variable to specify its path. (optional)
16
17 GIT_SYNC_DEPS_PATH if not set, the DEPS file in this repository
epoger 2014/04/14 19:32:14 This one doesn't quite tell the whole story. Mayb
hal.canary 2014/04/16 18:46:19 Done.
18 will be parsed. (optional)
19
20 GIT_SYNC_DEPS_QUIET if set to non-empty string, suppress messages.
21
22 Git Config:
23 To disable syncing of a single repository:
24 cd path/to/repository
25 git config sync-deps.disable true
26
27 To re-enable sync:
28 cd path/to/repository
29 git config --unset sync-deps.disable
30 """
31
32
33 import os
34 import subprocess
35 import sys
36 import threading
37
38 from git_utils import git_executable
39
40
41 DEFAULT_DEPS_PATH = os.path.normpath(
42 os.path.join(os.path.dirname(__file__), os.pardir, 'DEPS'))
43
44
45 def usage(deps_file_path = None):
46 sys.stderr.write(
47 'Usage: run to grab dependencies, with optional platform support:\n')
48 sys.stderr.write(' python %s' % __file__)
49 if deps_file_path:
50 for deps_os in parse_file_to_dict(deps_file_path)['deps_os']:
51 sys.stderr.write(' [%s]' % deps_os)
52 else:
53 sys.stderr.write(' [DEPS_OS...]')
54 sys.stderr.write('\n\n')
55 sys.stderr.write(__doc__)
56
57
58 def git_checkout_to_directory(git, repo, checkoutable, directory, verbose):
59 """Checkout (and clone if needed) a Git repository.
60
61 Args:
62 git (string) the git executable
63
64 repo (string) the location of the repository, suitable
65 for passing to `git clone`.
66
67 checkoutable (string) a tag, branch, or commit, suitable for
68 passing to `git checkout`
69
70 directory (string) the path into which the repository
71 should be checked out.
72
73 verbose (boolean)
74
75 Raises an exception if any calls to git fail.
76 """
77 at_revision = False
78 if os.path.isdir(directory):
epoger 2014/04/14 19:32:14 Could you rearrange it like so, so that the os.pat
hal.canary 2014/04/16 18:46:19 Done.
79 # Check to see if this repo is disabled. Quick return.
80 try:
81 disable = subprocess.check_output(
82 [git, 'config', 'sync-deps.disable'], cwd=directory)
83 if disable.lower().strip() in ['true', '1', 'yes', 'on']:
84 sys.stdout.write('%s\n SYNC IS DISABLED.\n' % directory)
85 return
86 except subprocess.CalledProcessError:
87 pass
88
89 # Only do a slow git fetch if we are not already on correct revision
epoger 2014/04/14 19:32:14 Sorta-double-negative ("only ... not") and possibl
hal.canary 2014/04/16 18:46:19 I gave up on saving half a second by checking for
90 def revision(rev):
epoger 2014/04/14 19:32:14 Maybe make this a first-class function? I think t
hal.canary 2014/04/16 18:46:19 Simplified out of existence.
91 return subprocess.check_output(
92 [git, 'rev-list', '-1', rev], cwd=directory)
epoger 2014/04/14 19:32:14 Using the more explicit command-line flag will mak
hal.canary 2014/04/16 18:46:19 Simplified out of existence.
93 try:
94 at_revision = (revision('HEAD') == revision(checkoutable))
epoger 2014/04/14 19:32:14 I think the logic would be simpler if we resolved
95 except subprocess.CalledProcessError:
96 # if checkoutable is unknown, maybe fetch will fix that.
97 pass
98 if not at_revision:
99 subprocess.check_call([git, 'fetch', '--quiet'], cwd=directory)
100 # will fail if origin can't be reached.
101
102 else:
103 subprocess.check_call([git, 'clone', '--quiet', repo, directory])
104 # will fail if repo is bad or if directory is a file.
105
106 # we want this repository to be pristine.
107 if (subprocess.check_output(
108 [git, 'diff', '--shortstat'], cwd=directory)
109 or subprocess.check_output([git, 'clean', '-nd'], cwd=directory)):
110 raise Exception("%s has uncommited changes" % directory)
111 # Will fail if `git checkout` can not cleanly be called.
112
113 if not at_revision:
epoger 2014/04/14 19:32:14 Why don't we just do the "git checkout" right afte
hal.canary 2014/04/16 18:46:19 Done.
114 subprocess.check_call(
115 [git, 'checkout', '--quiet', checkoutable], cwd=directory)
116 # Will fail if checkoutable is unknown.
117
118 if verbose:
119 sys.stdout.write('%s\n @ %s\n' % (directory, checkoutable)) # Success.
120
121
122 def parse_file_to_dict(path):
123 dictionary = {}
124 execfile(path, dictionary)
125 return dictionary
126
127
128 class DepsError(Exception):
129 """Raised if deps_os is a bad key.
130 """
131 pass
132
133
134 def git_sync_deps(deps_file_path, deps_os_list, verbose):
135 """Grab dependencies, with optional platform support.
136
137 Args:
138 deps_file_path (string) Path to the DEPS file.
139
140 deps_os_list (list of strings) Can be empty list. List of
141 strings that should each be a key in the deps_os
142 dictionary in the DEPS file.
143
144 Raises DepsError exception and git Exceptions.
145 """
146 git = git_executable()
147 assert git
148
149 deps_file_directory = os.path.dirname(deps_file_path)
150 deps = parse_file_to_dict(deps_file_path)
151 dependencies = deps['deps'].copy()
152 for deps_os in deps_os_list:
153 # Add OS-specific dependencies
154 if deps_os not in deps['deps_os']:
155 raise DepsError(
156 'Argument "%s" not found within deps_os keys %r' %
157 (deps_os, deps['deps_os'].keys()))
158 for dep in deps['deps_os'][deps_os]:
159 dependencies[dep] = deps['deps_os'][deps_os][dep]
160 list_of_arg_lists = []
161 for directory in dependencies:
162 if '@' in dependencies[directory]:
163 repo, checkoutable = dependencies[directory].split('@', 1)
164 else:
165 repo, checkoutable = dependencies[directory], 'origin/master'
166
167 relative_directory = os.path.join(deps_file_directory, directory)
168
169 list_of_arg_lists.append(
170 (git, repo, checkoutable, relative_directory, verbose))
171
172 multithread(git_checkout_to_directory, list_of_arg_lists)
173
174
175 def multithread(function, list_of_arg_lists):
176 # for args in list_of_arg_lists:
177 # function(*args)
178 # return
179 threads = []
180 for args in list_of_arg_lists:
181 thread = threading.Thread(None, function, None, args)
182 thread.start()
183 threads.append(thread)
184 for thread in threads:
185 thread.join()
186
187
188 def main(argv):
189 deps_file_path = os.environ.get(
190 'GIT_SYNC_DEPS_PATH', DEFAULT_DEPS_PATH)
191 verbose = not bool(os.environ.get('GIT_SYNC_DEPS_QUIET', False))
192 try:
193 git_sync_deps(deps_file_path, argv, verbose)
194 return 0
195 except DepsError:
196 usage(deps_file_path)
197 return 1
198
199
200 if __name__ == '__main__':
201 exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « docs/quickstart.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698