Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: ensure_dependencies.py

Issue 29329056: Issue 3194 - Allow multiple sources for a dependency (Closed)
Left Patch Set: Implemented Sebastian's suggested syntax Created Oct. 15, 2015, 2:53 p.m.
Right Patch Set: Just return a list from merge_seqs instead of coercing the result into a tuple Created Oct. 16, 2015, 10:43 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # coding: utf-8 2 # coding: utf-8
3 3
4 # This Source Code Form is subject to the terms of the Mozilla Public 4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this 5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 7
8 import sys 8 import sys
9 import os 9 import os
10 import posixpath 10 import posixpath
11 import re 11 import re
12 import io 12 import io
13 import errno 13 import errno
14 import logging 14 import logging
15 import subprocess 15 import subprocess
16 import urlparse 16 import urlparse
17 import argparse 17 import argparse
18 18
19 from collections import OrderedDict 19 from collections import OrderedDict
20 from ConfigParser import RawConfigParser 20 from ConfigParser import RawConfigParser
21 21
22 USAGE = """ 22 USAGE = """
23 A dependencies file should look like this: 23 A dependencies file should look like this:
24 24
25 # VCS-specific root URLs for the repositories 25 # VCS-specific root URLs for the repositories
26 _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/ 26 _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/
27 # File to update this script from (optional) 27 # File to update this script from (optional)
28 _self = buildtools/ensure_dependencies.py 28 _self = buildtools/ensure_dependencies.py
29 # Check out elemhidehelper repository into extensions/elemhidehelper directory 29 # Clone elemhidehelper repository into extensions/elemhidehelper directory at
30 # at tag "1.2". 30 # tag "1.2".
31 extensions/elemhidehelper = elemhidehelper 1.2 31 extensions/elemhidehelper = elemhidehelper 1.2
32 # Check out buildtools repository into buildtools directory at VCS-specific 32 # Clone buildtools repository into buildtools directory at VCS-specific
33 # revision IDs. 33 # revision IDs.
34 buildtools = buildtools hg:016d16f7137b git:f3f8692f82e5 34 buildtools = buildtools hg:016d16f7137b git:f3f8692f82e5
35 # Check out the adblockplus repository into adblockplus directory, overwriting 35 # Clone the adblockplus repository into adblockplus directory, overwriting the
Sebastian Noack 2015/10/15 15:19:41 Nit: "Check out" isn't hg/git terminology.
kzar 2015/10/15 16:12:25 Done.
36 # the usual source URL for Git repository and specifying VCS specific revision 36 # usual source URL for Git repository and specifying VCS specific revision IDs .
37 # IDs. 37 adblockplus = adblockplus hg:893426c6a6ab git:git@github.com:user/adblockplus. git@b2ffd52b
38 adblockplus = adblockplus hg:893426c6a6ab git:git@github.com:kzar/adblockplus. git@b2ffd52b 38 # Clone the adblockpluschrome repository into the adblockpluschrome directory,
39 # Check out the adblockpluschrome repository into the adblockpluschrome 39 # from a specific Git repository, specifying the revision ID.
40 # directory, from a specific Git repository, specifying the revision ID. 40 adblockpluschrome = git:git@github.com:user/adblockpluschrome.git@1fad3a7
41 adblockpluschrome = git:git@github.com:kzar/adblockpluschrome.git@1fad3a7
42 """ 41 """
43 42
44 SKIP_DEPENDENCY_UPDATES = os.environ.get( 43 SKIP_DEPENDENCY_UPDATES = os.environ.get(
45 "SKIP_DEPENDENCY_UPDATES", "" 44 "SKIP_DEPENDENCY_UPDATES", ""
46 ).lower() not in ("", "0", "false") 45 ).lower() not in ("", "0", "false")
47 46
48 class Mercurial(): 47 class Mercurial():
49 def istype(self, repodir): 48 def istype(self, repodir):
50 return os.path.exists(os.path.join(repodir, ".hg")) 49 return os.path.exists(os.path.join(repodir, ".hg"))
51 50
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 return "ssh://" + url.replace(":", "/", 1) 136 return "ssh://" + url.replace(":", "/", 1)
138 return url 137 return url
139 138
140 repo_types = OrderedDict(( 139 repo_types = OrderedDict((
141 ("hg", Mercurial()), 140 ("hg", Mercurial()),
142 ("git", Git()), 141 ("git", Git()),
143 )) 142 ))
144 143
145 # [vcs:]value 144 # [vcs:]value
146 item_regexp = re.compile( 145 item_regexp = re.compile(
147 "^(?:(" + "|".join(repo_types.keys()) +"):)?" 146 "^(?:(" + "|".join(map(re.escape, repo_types.keys())) +"):)?"
148 "(.+)$" 147 "(.+)$"
149 ) 148 )
150 149
151 # [url@]rev 150 # [url@]rev
152 source_regexp = re.compile( 151 source_regexp = re.compile(
153 "^(?:(.*)@)?" 152 "^(?:(.*)@)?"
154 "(.+)$" 153 "(.+)$"
155 ) 154 )
156 155
157 def merge_tuples(tuple_1, tuple_2): 156 def merge_seqs(seq1, seq2):
158 """Return tuple containing any truthy values from the suplied tuples 157 """Return a list of any truthy values from the suplied sequences
159 158
160 (None, 2), (1,) => (1, 2) 159 (None, 2), (1,) => [1, 2]
161 None, (1, 2) => (1, 2) 160 None, (1, 2) => [1, 2]
162 (1, 2), (3, 4) => (3, 4) 161 (1, 2), (3, 4) => [3, 4]
163 """ 162 """
164 return tuple(i2 or i1 for i1, i2 in map(None, tuple_1 or (), tuple_2 or ())) 163 return map(lambda item1, item2: item2 or item1, seq1 or (), seq2 or ())
165 164
166 def parse_spec(path, line): 165 def parse_spec(path, line):
167 if "=" not in line: 166 if "=" not in line:
168 logging.warning("Invalid line in file %s: %s" % (path, line)) 167 logging.warning("Invalid line in file %s: %s" % (path, line))
169 return None, None 168 return None, None
170 169
171 key, value = line.split("=", 1) 170 key, value = line.split("=", 1)
172 key = key.strip() 171 key = key.strip()
173 items = value.split() 172 items = value.split()
174 if not len(items): 173 if not len(items):
175 logging.warning("No value specified for key %s in file %s" % (key, path)) 174 logging.warning("No value specified for key %s in file %s" % (key, path))
176 return key, None 175 return key, None
177 176
178 result = OrderedDict() 177 result = OrderedDict()
179 is_dependency_field = not key.startswith("_") 178 is_dependency_field = not key.startswith("_")
180 179
181 for i, item in enumerate(items): 180 for i, item in enumerate(items):
182 try: 181 try:
183 vcs, value = re.match(item_regexp, item).groups() 182 vcs, value = re.search(item_regexp, item).groups()
184 vcs = vcs or "*" 183 vcs = vcs or "*"
185 if is_dependency_field: 184 if is_dependency_field:
186 if i == 0 and vcs == "*": 185 if i == 0 and vcs == "*":
187 # In order to be backwards compatible we have to assume that the first 186 # In order to be backwards compatible we have to assume that the first
188 # source contains only a URL/path for the repo if it does not contain 187 # source contains only a URL/path for the repo if it does not contain
189 # the VCS part 188 # the VCS part
190 url_rev = (value, None) 189 url_rev = (value, None)
191 else: 190 else:
192 url_rev = re.match(source_regexp, value).groups() 191 url_rev = re.search(source_regexp, value).groups()
Sebastian Noack 2015/10/15 15:19:41 We decided a while ago to not use .match() anymore
kzar 2015/10/15 16:12:25 Done.
193 result[vcs] = merge_tuples(result.get(vcs), url_rev) 192 result[vcs] = merge_seqs(result.get(vcs), url_rev)
194 else: 193 else:
195 if vcs in result: 194 if vcs in result:
196 logging.warning("Ignoring duplicate value for type %s" 195 logging.warning("Ignoring duplicate value for type %r "
197 "(key %s in file %s)" % (vcs, key, path)) 196 "(key %r in file %r)" % (vcs, key, path))
198 result[vcs] = value 197 result[vcs] = value
199 except AttributeError: 198 except AttributeError:
200 logging.warning("Ignoring invalid item '%s' for type %s" 199 logging.warning("Ignoring invalid item %r for type %r "
Sebastian Noack 2015/10/15 15:19:41 How about using %r instead '%s'?
kzar 2015/10/15 16:12:25 (Some further testing showed it's clearer if all t
201 "(key %s in file %s)" % (item, vcs, key, path)) 200 "(key %r in file %r)" % (item, vcs, key, path))
202 continue 201 continue
203 return key, result 202 return key, result
204 203
205 def read_deps(repodir): 204 def read_deps(repodir):
206 result = {} 205 result = {}
207 deps_path = os.path.join(repodir, "dependencies") 206 deps_path = os.path.join(repodir, "dependencies")
208 try: 207 try:
209 with io.open(deps_path, "rt", encoding="utf-8") as handle: 208 with io.open(deps_path, "rt", encoding="utf-8") as handle:
210 for line in handle: 209 for line in handle:
211 # Remove comments and whitespace 210 # Remove comments and whitespace
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 skipdependencies.intersection([s[0] for s in sources if s[0]])): 300 skipdependencies.intersection([s[0] for s in sources if s[0]])):
302 continue 301 continue
303 302
304 target = safe_join(repodir, dir) 303 target = safe_join(repodir, dir)
305 parenttype = get_repo_type(repodir) 304 parenttype = get_repo_type(repodir)
306 _root = config.get("_root", {}) 305 _root = config.get("_root", {})
307 306
308 for key in sources.keys() + _root.keys(): 307 for key in sources.keys() + _root.keys():
309 if key == parenttype or key is None and vcs != "*": 308 if key == parenttype or key is None and vcs != "*":
310 vcs = key 309 vcs = key
311 source, rev = merge_tuples(sources.get("*"), sources.get(vcs)) 310 source, rev = merge_seqs(sources.get("*"), sources.get(vcs))
312 311
313 if not (vcs and source and rev): 312 if not (vcs and source and rev):
314 logging.warning("No valid source / revision found to create %s" % target) 313 logging.warning("No valid source / revision found to create %s" % target)
315 continue 314 continue
316 315
317 ensure_repo(repodir, parenttype, target, vcs, _root.get(vcs, ""), source) 316 ensure_repo(repodir, parenttype, target, vcs, _root.get(vcs, ""), source)
318 update_repo(target, vcs, rev) 317 update_repo(target, vcs, rev)
319 resolve_deps(target, level + 1, self_update=False, 318 resolve_deps(target, level + 1, self_update=False,
320 overrideroots=overrideroots, skipdependencies=skipdependencies) 319 overrideroots=overrideroots, skipdependencies=skipdependencies)
321 320
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 args = parser.parse_args() 362 args = parser.parse_args()
364 363
365 if args.quiet: 364 if args.quiet:
366 logging.disable(logging.INFO) 365 logging.disable(logging.INFO)
367 366
368 repos = args.repos 367 repos = args.repos
369 if not len(repos): 368 if not len(repos):
370 repos = [os.path.dirname(__file__)] 369 repos = [os.path.dirname(__file__)]
371 for repo in repos: 370 for repo in repos:
372 resolve_deps(repo) 371 resolve_deps(repo)
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld