comparison fetch.py @ 29:1c963875e6cd

add a test for manifest and fix resulting bugs
author Jeff Hammel <jhammel@mozilla.com>
date Tue, 15 Nov 2011 10:13:47 -0800
parents 5ecb6507931b
children 60e0e932570e
comparison
equal deleted inserted replaced
28:5ecb6507931b 29:1c963875e6cd
58 from StringIO import StringIO 58 from StringIO import StringIO
59 59
60 class FileFetcher(Fetcher): 60 class FileFetcher(Fetcher):
61 """fetch a single file""" 61 """fetch a single file"""
62 # Note: subpath and clobber for single files are ignored 62 # Note: subpath and clobber for single files are ignored
63 63
64 type = 'file' 64 type = 'file'
65 65
66 @classmethod 66 @classmethod
67 def download(cls, url): 67 def download(cls, url):
68 return urllib2.urlopen(url).read() 68 return urllib2.urlopen(url).read()
128 self.clobber(dest) 128 self.clobber(dest)
129 if self.subpath or self.export: 129 if self.subpath or self.export:
130 # can only export with a subpath 130 # can only export with a subpath
131 self.export(dest, subpath=self.subpath) 131 self.export(dest, subpath=self.subpath)
132 return 132 return
133 133
134 if os.path.exists(dest): 134 if os.path.exists(dest):
135 assert os.path.isdir(dest) 135 assert os.path.isdir(dest)
136 else: 136 else:
137 self.clone(dest) 137 self.clone(dest)
138 138
177 raise NotImplementedError("Abstract base class") 177 raise NotImplementedError("Abstract base class")
178 178
179 def versioned(self, directory): 179 def versioned(self, directory):
180 return os.path.exists(os.path.join(directory, self.vcs_dir)) 180 return os.path.exists(os.path.join(directory, self.vcs_dir))
181 181
182 182
183 if which('hg'): 183 if which('hg'):
184 184
185 class HgFetcher(VCSFetcher): 185 class HgFetcher(VCSFetcher):
186 """checkout a mercurial repository""" 186 """checkout a mercurial repository"""
187 type = 'hg' 187 type = 'hg'
193 193
194 def clone(self, dest): 194 def clone(self, dest):
195 if os.path.exists(dest): 195 if os.path.exists(dest):
196 assert os.path.isdir(dest) 196 assert os.path.isdir(dest)
197 call([self.hg, 'clone', self.url, dest]) 197 call([self.hg, 'clone', self.url, dest])
198 198
199 def update(self, dest): 199 def update(self, dest):
200 assert os.path.versioned(dest) 200 assert os.path.versioned(dest)
201 assert os.path.exists(dest) 201 assert os.path.exists(dest)
202 call([self.hg, 'pull', self.url], cwd=dest) 202 call([self.hg, 'pull', self.url], cwd=dest)
203 call([self.hg, 'update', '-C'], cwd=dest) 203 call([self.hg, 'update', '-C'], cwd=dest)
230 fetchers.append(GitFetcher) 230 fetchers.append(GitFetcher)
231 231
232 __all__ += [i.__name__ for i in fetchers] 232 __all__ += [i.__name__ for i in fetchers]
233 233
234 class Fetch(object): 234 class Fetch(object):
235 235
236 def __init__(self, fetchers=fetchers[:], relative_to=None, strict=True): 236 def __init__(self, fetchers=fetchers[:], relative_to=None, strict=True):
237 self.fetchers = fetchers 237 self.fetchers = fetchers
238 self.relative_to = relative_to 238 self.relative_to = relative_to
239 self.strict = strict 239 self.strict = strict
240 240
254 254
255 if self.strict: 255 if self.strict:
256 # ensure all the required fetchers are available 256 # ensure all the required fetchers are available
257 types = set([i['type'] for i in items]) 257 types = set([i['type'] for i in items])
258 assert not [i for i in types 258 assert not [i for i in types
259 if [True for fetcher in fetchers if fetcher.match(i)]] 259 if not [True for fetcher in fetchers
260 if fetcher.match(i)]]
260 261
261 for item in items: 262 for item in items:
262 263
263 # fix up relative paths 264 # fix up relative paths
264 dest = item['dest'] 265 dest = item['dest']
272 273
273 format_string = "[URL] [destination] [type] <options>" 274 format_string = "[URL] [destination] [type] <options>"
274 def read_manifests(*manifests): 275 def read_manifests(*manifests):
275 """ 276 """
276 read some manifests and return the items 277 read some manifests and return the items
277 278
278 Format: 279 Format:
279 %s 280 %s
280 """ % format_string 281 """ % format_string
281 282
282 # sanity check
283 assert not [i for i in manifests if not os.path.exists(i)]
284
285 retval = [] 283 retval = []
286 284
287 for manifest in manifests: 285 for manifest in manifests:
288 for line in file(i).readlines(): 286 if isinstance(manifest, basestring):
287 assert os.path.exists(manifest), "manifest '%s' not found" % manifest
288 f = file(manifest)
289 else:
290 f = manifest
291
292 for line in f.readlines():
289 line = line.strip() 293 line = line.strip()
290 if line.startswith('#') or not line: 294 if line.startswith('#') or not line:
291 continue 295 continue
292 line = line.split() 296 line = line.split()
293 if len(line) not in (3,4): 297 if len(line) not in (3,4):
314 def format_description(self, description): 318 def format_description(self, description):
315 if description: 319 if description:
316 return description + '\n' 320 return description + '\n'
317 else: 321 else:
318 return '' 322 return ''
319 323
320 parser = optparse.OptionParser(usage=usage, description=__doc__, formatter=PlainDescriptionFormatter()) 324 parser = optparse.OptionParser(usage=usage, description=__doc__, formatter=PlainDescriptionFormatter())
321 parser.add_option('-o', '--output', 325 parser.add_option('-o', '--output',
322 help="output relative to this location vs. the manifest location") 326 help="output relative to this location vs. the manifest location")
323 parser.add_option('-d', '--dest', # XXX unused 327 parser.add_option('-d', '--dest', # XXX unused
324 action='append', 328 action='append',
343 if not args: 347 if not args:
344 # TODO: could read from stdin 348 # TODO: could read from stdin
345 parser.print_help() 349 parser.print_help()
346 parser.exit() 350 parser.exit()
347 351
352 # sanity check
353 assert not [i for i in args if not os.path.exists(i)]
354
348 items = read_manifests(*args) 355 items = read_manifests(*args)
349 fetch = Fetch(fetchers, strict=options.strict) 356 fetch = Fetch(fetchers, strict=options.strict)
350 357
351 # download the files 358 # download the files
352 fetch.fetch(*items) 359 fetch.fetch(*items)
353 360
354 if __name__ == '__main__': 361 if __name__ == '__main__':
355 main() 362 main()
356 363