Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2012 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. | |
| 5 | |
| 6 """Bootstrap Chrome Telemetry by downloading all its files from SVN servers. | |
| 7 | |
| 8 Requires a DEPS file to specify which directories on which SVN servers | |
| 9 are required to run Telemetry. Format of that DEPS file is a subset of the | |
| 10 normal DEPS file format[1]; currently only only the "deps" dictionary is | |
| 11 supported and nothing else. | |
| 12 | |
| 13 DEPS can be specified with --deps or defaults to ./DEPS | |
| 14 | |
| 15 Fetches all files in the specified directories using WebDAV (SVN is WebDAV under | |
| 16 the hood). | |
| 17 | |
| 18 [1] http://dev.chromium.org/developers/how-tos/depottools#TOC-DEPS-file | |
| 19 """ | |
| 20 | |
| 21 import imp | |
| 22 import logging | |
| 23 from optparse import OptionParser | |
|
nduca
2013/01/05 01:28:19
I think you can ditch main() entirely and thus Opt
wiltzius
2013/01/08 02:53:34
Done.
| |
| 24 import os | |
| 25 import urllib | |
| 26 import urlparse | |
| 27 | |
| 28 # default DEPS filename | |
| 29 DEPS_FILE = "DEPS" | |
|
nduca
2013/01/05 01:28:19
This can go away
wiltzius
2013/01/08 02:53:34
Done.
wiltzius
2013/01/08 02:53:34
Done.
| |
| 30 # link to file containing the 'davclient' WebDAV client library | |
|
nduca
2013/01/05 01:28:19
# Comments start with capitals end and end with a
wiltzius
2013/01/08 02:53:34
Done.
| |
| 31 #TODO(wiltzius) change this to point at Chromium SVN server after checkin | |
|
nduca
2013/01/05 01:28:19
# TODO(wiltzius):
| |
| 32 DAVCLIENT_URL = 'http://svn.osafoundation.org/tools/davclient/trunk/src/davclien t/davclient.py' | |
|
nduca
2013/01/05 01:28:19
_DAVCLIENT_URL since its private to the module. _-
wiltzius
2013/01/08 02:53:34
Done.
| |
| 33 | |
| 34 def bootstrap_davclient(): | |
|
nduca
2013/01/05 01:28:19
_bootstrap_davclient since this shouldn't be calle
wiltzius
2013/01/08 02:53:34
Done.
| |
| 35 """Dynamically import davclient helper library.""" | |
|
nduca
2013/01/05 01:28:19
_download_and_import_davclient_module()?
wiltzius
2013/01/08 02:53:34
Done.
| |
| 36 global davclient | |
| 37 davclient_txt = urllib.urlopen(DAVCLIENT_URL).read() | |
|
nduca
2013/01/05 01:28:19
txt -> source?
wiltzius
2013/01/08 02:53:34
Done.
wiltzius
2013/01/08 02:53:34
Done.
| |
| 38 davclient = imp.new_module('davclient') | |
| 39 exec davclient_txt in davclient.__dict__ | |
| 40 | |
| 41 | |
| 42 class DAVClientWrapper(): | |
| 43 """Knows how to retrieve subdirectories and files from WebDAV/SVN servers.""" | |
| 44 | |
| 45 def __init__(self, root_url): | |
| 46 """Initialize SVN server root_url, save files to local dest_dir. | |
| 47 | |
| 48 Args: | |
| 49 root_url: string url of SVN/WebDAV server | |
| 50 """ | |
| 51 self.root_url = root_url | |
| 52 self.client = davclient.DAVClient(root_url) | |
| 53 | |
| 54 def GetSubdirs(self, path): | |
| 55 """Returns string names of all subdirs of this path on the SVN server.""" | |
| 56 props = self.client.propfind(path, depth=1) | |
| 57 return map(os.path.basename, props.keys()) | |
| 58 | |
| 59 def IsFile(self, path): | |
| 60 """Returns True if the path is a file on the server, False if directory.""" | |
| 61 props = self.client.propfind(path, depth=1) | |
| 62 # build up normalized path list since paths to directories may or may not | |
| 63 # have trailing slashes | |
| 64 norm_keys = {} | |
| 65 for entry in props.keys(): | |
| 66 norm_keys[os.path.normpath(entry)] = entry | |
| 67 return props[norm_keys[os.path.normpath(path)]]['resourcetype'] is None | |
| 68 | |
| 69 def Traverse(self, src_path, dst_path): | |
| 70 """Walks the directory hierarchy pointed to by src_path download all files. | |
| 71 | |
| 72 Recursively walks src_path and saves all files and subfolders into | |
| 73 dst_path. | |
| 74 | |
| 75 Args: | |
| 76 src_path: string path on SVN server to save (absolute path on server). | |
| 77 dest_path: string local path (relative or absolute) to save to. | |
| 78 """ | |
| 79 if self.IsFile(src_path): | |
| 80 if not os.path.exists(os.path.dirname(dst_path)): | |
| 81 logging.info("creating %s", os.path.dirname(dst_path)) | |
| 82 os.makedirs(os.path.dirname(dst_path)) | |
| 83 logging.info("Saving %s to %s", self.root_url + src_path, dst_path) | |
| 84 urllib.urlretrieve(self.root_url + src_path, dst_path) | |
| 85 return | |
| 86 else: | |
| 87 for subdir in self.GetSubdirs(src_path): | |
| 88 if subdir: | |
| 89 self.Traverse(os.path.join(src_path, subdir), | |
| 90 os.path.join(dst_path, subdir)) | |
| 91 | |
| 92 | |
| 93 def ParseOptions(): | |
|
nduca
2013/01/05 01:28:19
I think this can go away
wiltzius
2013/01/08 02:53:34
Done.
| |
| 94 """Parses command-line options for the bootstrap.""" | |
| 95 #TODO(wiltzius) have a --revision flag that pulls at a specific rev | |
| 96 parser = OptionParser() | |
| 97 parser.add_option("-v", "--verbosity", dest="verbosity", default=1, | |
| 98 type="int", help="logging verbosity level (0, 1, 2, 3)") | |
| 99 parser.add_option("--deps", dest="deps_filename", default=DEPS_FILE, | |
| 100 help="look for dependency manifest in this file") | |
| 101 return parser.parse_args() | |
| 102 | |
| 103 | |
| 104 def DownloadDEPS(deps_path): | |
|
nduca
2013/01/05 01:28:19
Should we have a TODO here for what revision of te
wiltzius
2013/01/08 02:53:34
Done.
| |
| 105 """Saves all the dependencies in deps_path.""" | |
| 106 # dynamically import davclient library | |
| 107 bootstrap_davclient() | |
| 108 with open(deps_path) as deps_file: | |
| 109 deps = imp.new_module('deps') | |
| 110 exec deps_file.read() in deps.__dict__ | |
|
nduca
2013/01/05 01:28:19
unindent the exec stuff
so you say
with blah as
wiltzius
2013/01/08 02:53:34
Done.
| |
| 111 #TODO(wiltzius) in the future, make the destination directory configurable | |
|
nduca
2013/01/05 01:28:19
formatting
wiltzius
2013/01/08 02:53:34
Done.
| |
| 112 # as something other than the cwd | |
|
nduca
2013/01/05 01:28:19
this function should take in destination dir. E.g.
wiltzius
2013/01/08 02:53:34
Done.
| |
| 113 destination_dir = os.getcwd() | |
| 114 for dst_path, src_path in deps.deps.iteritems(): | |
| 115 parsed_url = urlparse.urlparse(src_path) | |
| 116 root_url = parsed_url.scheme + '://' + parsed_url.netloc | |
|
nduca
2013/01/05 01:28:19
where will we handle "foo@181" type stuff?
wiltzius
2013/01/08 02:53:34
That's the "fetch at revision" TODO. This will nee
| |
| 117 dav_client = DAVClientWrapper(root_url) | |
| 118 dav_client.Traverse(parsed_url.path, | |
| 119 os.path.join(destination_dir, dst_path)) | |
|
nduca
2013/01/05 01:28:19
after we clone dst_path, what if dst_path has a DE
| |
| 120 | |
| 121 | |
| 122 def Main(): | |
|
nduca
2013/01/05 01:28:19
not needed I think.
wiltzius
2013/01/08 02:53:34
Done.
| |
| 123 """Fetches files specified in dependency manifest from SVN/WebDAV server.""" | |
| 124 options = ParseOptions()[0] | |
| 125 # set logging level per verbosity | |
| 126 logging_levels = [logging.ERROR, logging.WARN, logging.INFO, logging.DEBUG] | |
| 127 logging.basicConfig(level=logging_levels[options.verbosity]) | |
| 128 DownloadDEPS(options.deps_filename) | |
| 129 | |
| 130 | |
| 131 if __name__ == "__main__": | |
|
nduca
2013/01/05 01:28:19
Ditch the __name__ bit as well as the #! bit. If s
wiltzius
2013/01/08 02:53:34
Done.
| |
| 132 Main() | |
|
nduca
2013/01/05 01:28:19
Lets add the stuff that you had in __main__ into t
nduca
2013/01/05 01:28:19
Lets move this to tools/telemetry/tools/telemetry_
wiltzius
2013/01/08 02:53:34
I will do this in a follow-up patch after this boo
| |
| OLD | NEW |