OLD | NEW |
| (Empty) |
1 #!/usr/bin/python2.4 | |
2 # | |
3 # Copyright 2005-2009 Google Inc. | |
4 # | |
5 # Licensed under the Apache License, Version 2.0 (the "License"); | |
6 # you may not use this file except in compliance with the License. | |
7 # You may obtain a copy of the License at | |
8 # | |
9 # http://www.apache.org/licenses/LICENSE-2.0 | |
10 # | |
11 # Unless required by applicable law or agreed to in writing, software | |
12 # distributed under the License is distributed on an "AS IS" BASIS, | |
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 # See the License for the specific language governing permissions and | |
15 # limitations under the License. | |
16 # ======================================================================== | |
17 | |
18 """Creates application specific meta-installers. | |
19 | |
20 Run this script with the directory that contains the build files, | |
21 GoogleupdateSetup_<lang>.exe and pass it the file that contains the application | |
22 information to be stamped inside the binary. | |
23 | |
24 """ | |
25 | |
26 import codecs | |
27 import os | |
28 import sys | |
29 import re | |
30 import urllib | |
31 | |
32 class Bundle: | |
33 """Represents the information for a bundle""" | |
34 def __init__(self, exe_name, admin, language, | |
35 browser_type, stats, installers_txt_filename, applications): | |
36 self.applications = applications | |
37 self.name = exe_name | |
38 self.needs_admin = admin | |
39 self.lang = language | |
40 self.browser = browser_type | |
41 self.usage_stats = stats | |
42 self.installers_txt_filename = installers_txt_filename | |
43 self.output_file_name = "" | |
44 | |
45 def UrlEncodeString(name): | |
46 """Converts the name into utf8 encoded and then urlencodes it. | |
47 | |
48 Args: | |
49 name: The string to utf8 convert. | |
50 | |
51 Returns: | |
52 The utf8 converted urlencoded string. | |
53 """ | |
54 utf8_str = name.encode('utf8') | |
55 return urllib.quote(utf8_str) | |
56 | |
57 def ReadBundleInstallerFile(installers_txt_filename): | |
58 """Read the installation file and return a list of the values. | |
59 Only reads information from bundle installer files. The filename | |
60 should contain the "bundle" word. | |
61 Args: | |
62 installers_txt_filename: The file which contains application specific | |
63 values, of guid, name, exe_name, needs_admin and | |
64 language. | |
65 | |
66 Returns: | |
67 A dictionary of Bundles key=language, value=[Bundle] | |
68 """ | |
69 bundles = {} | |
70 installers_txt_file = codecs.open(installers_txt_filename, 'r', 'utf16') | |
71 for line in installers_txt_file.readlines(): | |
72 line = line.strip() | |
73 if len(line) and not line.startswith('#'): | |
74 (exe_name, needs_admin, language, browser, usage, bundle_apps) =\ | |
75 eval(line) | |
76 bundle = Bundle(exe_name, needs_admin, language, | |
77 browser, usage, | |
78 installers_txt_filename, bundle_apps) | |
79 if (not bundles.has_key(language)): | |
80 bundles[language] = [bundle] | |
81 else: | |
82 bundles[language] .append(bundle) | |
83 return bundles | |
84 | |
85 def BuildOutputDirectory(output_dir, lang, app): | |
86 """Returns the output directory for the app. | |
87 | |
88 Args: | |
89 app: The application for which to generate the path. | |
90 lang: The language of the applicaiton. | |
91 output_dir: The output directory. | |
92 | |
93 Returns: | |
94 The path of the output file. | |
95 """ | |
96 installers_txt_filename = app.installers_txt_filename | |
97 | |
98 end_idx = installers_txt_filename.find('_installers.txt') | |
99 app_dirname = installers_txt_filename[:end_idx] | |
100 | |
101 app_path = os.path.join(output_dir, app_dirname) | |
102 lang_path = os.path.join(app_path, lang) | |
103 return lang_path | |
104 | |
105 | |
106 def SetOutputFileNames(file_name, apps, output_dir): | |
107 """Sets the output file names inside the Application. | |
108 | |
109 Args: | |
110 file_name: The input file name that needs to be stamped. This | |
111 is used for deciding whether to use TEST in the name, | |
112 and the directory. The names of this file is expected | |
113 to be either TEST_GoogleUpdateSetup.exe or | |
114 GoogleUpdateSetup.exe | |
115 apps: Dictionary of applications keyed by language. | |
116 output_dir: The output directory. | |
117 | |
118 Returns: | |
119 All the applications for a particular language. | |
120 """ | |
121 | |
122 # Determine the language. | |
123 file = os.path.basename(file_name) | |
124 if file.startswith('TEST_'): | |
125 test = True | |
126 else: | |
127 test = False | |
128 | |
129 for (lang, apps_lang) in apps.iteritems(): | |
130 # Get the output filename and set it on the application. | |
131 for app in apps_lang: | |
132 output_path = BuildOutputDirectory(output_dir, lang, app) | |
133 path = os.path.join(output_path, GetOutputFileName(test, app.name, lang)) | |
134 app.output_file_name = path | |
135 | |
136 def GetOutputFileName(test, name, lang): | |
137 """Creates the output file name based on the language and the name of the app. | |
138 Args: | |
139 test: Whether the input file name starts with TEST. | |
140 name: The name of the application. I.e. Chrome, GoogleGears. | |
141 lang: The language of the installer. | |
142 Returns: | |
143 The output filename | |
144 """ | |
145 if test: | |
146 file_name = 'Tagged_TEST_%sSetup_%s.exe' % (name, lang) | |
147 else: | |
148 file_name = 'Tagged_%sSetup_%s.exe' % (name, lang) | |
149 return file_name | |
150 | |
151 def BuildTagStringForBundle(bundle): | |
152 """Builds the string to be tagged into the binary for a bundle. | |
153 Args: | |
154 bundle: Contains all information about a bundle. | |
155 Returns: | |
156 The string to be tagged into the installer. | |
157 """ | |
158 args = '\"' | |
159 first_app = True | |
160 for app in bundle.applications: | |
161 if not first_app: | |
162 args += '&' | |
163 first_app = False | |
164 (guid, name, ap) = app | |
165 display_name = UrlEncodeString(name) | |
166 args += 'appguid=%s&appname=%s&needsadmin=%s' % \ | |
167 (guid, display_name, bundle.needs_admin) | |
168 if ap: | |
169 args += '&ap=%s' % ap | |
170 | |
171 if bundle.usage_stats: | |
172 args += '&usagestats=%s' % bundle.usage_stats | |
173 if bundle.browser: | |
174 args += '&browser=%s' % bundle.browser | |
175 if bundle.lang: | |
176 args += '&lang=%s' % bundle.lang | |
177 args += '\"' | |
178 return args | |
179 | |
180 def TagOneFile(file, app, applytag_exe_name): | |
181 """Tags one file with the information contained inside the application. | |
182 Args: | |
183 file: The input file to be stamped. | |
184 app: Contains all the application data. | |
185 applytag_exe_name: The full path of applytag.exe. | |
186 """ | |
187 tag_string = BuildTagStringForBundle(app) | |
188 | |
189 output_path = app.output_file_name | |
190 if not os.path.exists(file): | |
191 print 'Could not find file %s required for creating %s' % \ | |
192 (file, output_path) | |
193 return False | |
194 | |
195 arguments = [applytag_exe_name, | |
196 file, | |
197 output_path, | |
198 tag_string | |
199 ] | |
200 print 'Building %s with tag %s' % (output_path, tag_string) | |
201 os.spawnv(os.P_WAIT, applytag_exe_name, arguments) | |
202 return True | |
203 | |
204 def GetAllSetupExeInDirectory(dir): | |
205 """Creates a number of application specific binaries for the | |
206 passed in binary. | |
207 Args: | |
208 dir: The input directory. | |
209 Returns: | |
210 A list of files that are match the regex: | |
211 TEST_GoogleUpdateSetup_.*.exe$|^GoogleUpdateSetup_.*.exe$ | |
212 """ | |
213 ret_files = [] | |
214 files = os.listdir(dir) | |
215 for file in files: | |
216 regex = re.compile('^TEST_GoogleUpdateSetup_.*.exe$|' | |
217 '^GoogleUpdateSetup_.*.exe$') | |
218 if not regex.match(file): | |
219 continue | |
220 ret_files.append(file) | |
221 return ret_files | |
222 | |
223 def TagBinary(apps, file, applytag_exe_name): | |
224 """Creates a number of application specific binaries for the | |
225 passed in binary. | |
226 Args: | |
227 apps: Dictionary of key=lang, value=[Application]. | |
228 file: The input file to be stamped. | |
229 applytag_exe_name: The full path to applytag_exe_name. | |
230 """ | |
231 if not apps: | |
232 return | |
233 for apps_lang in apps: | |
234 for app in apps[apps_lang]: | |
235 TagOneFile(file, app, applytag_exe_name) | |
236 | |
237 def PrintUsage(): | |
238 print '' | |
239 print 'Tool to stamp the Guid, Application name, needs admin into the' | |
240 print 'meta-installer.' | |
241 print 'Reads <installer file> which contains the application name,' | |
242 print 'guid, needs_admin and stamps the meta-installer <file> with' | |
243 print 'these values.' | |
244 print 'For an example of the <installer file> take a look at' | |
245 print '#/installers/googlegears_installer.txt' | |
246 print '' | |
247 print 'tag_meta_installers.py <applytag> <input file> <installer file>\ | |
248 <output file>' | |
249 | |
250 def main(): | |
251 if len(sys.argv) != 5: | |
252 PrintUsage() | |
253 return | |
254 | |
255 apply_tag_exe = sys.argv[1] | |
256 input_file = sys.argv[2] | |
257 file_name = sys.argv[3] | |
258 output_dir = sys.argv[4] | |
259 | |
260 if not os.path.exists(apply_tag_exe): | |
261 print "Could not find applytag.exe" | |
262 PrintUsage() | |
263 return | |
264 | |
265 if not os.path.exists(file_name): | |
266 print "Invalid filename %s" % file_name | |
267 PrintUsage() | |
268 return | |
269 | |
270 if not os.path.exists(input_file): | |
271 print "Invalid directory %s" % input_file | |
272 PrintUsage() | |
273 return | |
274 | |
275 if not os.path.exists(output_dir): | |
276 os.mkdir(output_dir) | |
277 | |
278 # Read in the installers.txt file. | |
279 apps = ReadBundleInstallerFile(file_name) | |
280 | |
281 SetOutputFileNames(input_file, apps, output_dir) | |
282 TagBinary(apps, input_file, apply_tag_exe) | |
283 | |
284 if __name__ == '__main__': | |
285 main() | |
OLD | NEW |