|
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 |