Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100755 263 lines (195 sloc) 7.368 kb
8d24142 @ciju initial commit
authored
1 #!/usr/local/bin/python2.5
2
3 import tempfile
4 import shutil
5 import re
6 import os
7
8 YUI_COMPRESSOR = 'yuicompressor-2.4.2.jar'
9
10 # todo: write script tag with the replaced script. the file would initially be
11 # at temporary place. once all such files are created, read all the htmls and
12 # copy the script and css files they refer to another direcotory and use it to
13 # deploy the code.
14
15 def ext(path):
16 return os.path.splitext(path)[1]
17
18 def join(path, *p):
19 return os.path.join(path, *p)
20
21 def exists(path):
22 return os.path.exists(path)
23
24 def abspath(path):
25 return os.path.abspath(os.path.normpath(path))
26
27 def basename(path):
28 return os.path.basename(path)
29
30 def rm(path):
31 return os.remove(path)
32
33
34 class ProcessCommands():
35 def __init__(self, dest, scripts, base=''):
36 self.dest = dest
37 self.base = base
38 self.scripts = scripts
39 self.data = []
40 self.files = []
41
42 if isinstance(scripts, str):
43 self.paths = self.get_script_files(scripts)
44 elif isinstance(scripts, list):
45 self.paths = scripts
46
47 self.paths = [join(base, re.sub(r'^/*', '', p)) for p in self.paths]
48
49 def get_script_files(self, s):
50 return [i for i in re.findall(r'.*?<script.*?src="(.*?)"', s, re.DOTALL)]
51
52 def process(self):
53 # to be overridden by inherited classes with the act.
54 pass
55
56 class CombineAndBuild(ProcessCommands):
57 def process(self):
58 for p in self.paths:
59 if not exists(p):
60 print ' file doesnt exist: ', p
61 return self.paths, self.scripts
62
63 # do operations like minimization etc here.
64 self.files.append(p)
65 self.data.append(open(p).read())
66
67
68 extension = ext(self.dest)
69 if extension == '':
70 self.dest += '.js'
71
72 print 'combining scripts to!', self.dest.replace(self.base, '')
73 # f = open(self.dest, 'w')
74 # f.write('\n'.join(self.data))
75 # f.close()
76
77 # --
78 tmp_file, tmp_file_name = tempfile.mkstemp()
79 os.close(tmp_file)
80
81 tmp_file = open(tmp_file_name, 'w')
82 tmp_file.write('\n'.join(self.data))
83 tmp_file.close()
84
85 os.system("%s %s --type js -o %s" % (YUI_COMPRESSOR, tmp_file_name, self.dest))
86 os.unlink(tmp_file_name)
87 # --
88
89 return self.paths, '<script src="%s"></script>' % (self.dest.replace(self.base, ''))
90
91
92 def rel_path(base, target):
93 # @see http://code.activestate.com/recipes/302594-another-relative-filepath-script/
94 b_list = (abspath(base)).split(os.sep)
95 t_list = (abspath(target)).split(os.sep)
96
97 for i in range(min(len(b_list), len(t_list))):
98 if b_list[i] <> t_list[i]: break
99 else:
100 i += 1
101
102 rel_list = [os.pardir] * (len(b_list)-i) + t_list[i:]
103
104 return join(*rel_list)
105
106 class ProcessBuildComments():
107
108 def __init__(self, path, base='', nbase=''):
109 f = open(path)
110
111 if f:
112 self.path = path
113 self.base = base
114 self.nbase = nbase
115 self.body = f.read()
116 self.handle_comment()
117 else:
118 # todo: error
119 print 'couldnt find the file', path
120
121 def build_group(self, m, f, s):
122 klass = ''.join([i.capitalize() for i in m.split('_')])
123 k = globals()[klass](f, s, self.base)
124 if k:
125 rep = k.process()
126 return rep
127
128 def handle_comment(self):
129 # find all javascript build groups.
130 regexp = r'.*?<!-- *@([a-z_]*) *([a-z_]*) *-->(.*?)<!-- *@end *-->.*?'
131 matches = re.findall(regexp, self.body, re.DOTALL)
132
133 if not len(matches):
134 return []
135
136 # find the script files mentioned in group. and do the mentioned corresponding action.
137 for m, f, s in matches:
138 paths, rep = self.build_group(m, join(self.nbase, f), s)
139 if rep:
140 # change the body to include the result of operation done on build group.
141 regexp = re.compile(r'<!-- *@%s *%s *-->(.*?)<!-- *@end *-->' % (m, f), re.DOTALL)
142 self.body = re.sub(regexp, rep, self.body, re.DOTALL)
143
144 self.body = self.body.replace('REPLACE_WITH_APP_STATE', '"live"')
145
146
147 dst_file = join(self.nbase, rel_path(self.base, self.path))
148
149 print 'writing the modified html file to: ', dst_file
150 f = open(dst_file, 'w')
151 f.write(self.body)
152 f.close()
153
154
155 def rec_find_files(base, ext='html', ignore=[]):
156 "Find files with the 'ext' under 'base' ignoring the 'ignore' directories "
157 paths = []
158 for root, dirs, files in os.walk(base):
159 for name in files:
160 if re.match(r'.*\.%s$' % ext, join(root, name)):
161 paths.append(join(root, name))
162
163 ignore = [join(base, i) for i in ignore]
164
165 if '.git' in dirs:
166 dirs.remove('.git')
167
168 for d in dirs:
169 if join(root, d) in ignore:
170 print 'ignoring: ', join(root,d)
171 dirs.remove(d)
172 return paths
173
174 def del_unused_files(base, paths):
175 for root, dirs, files in os.walk(base):
176 for name in files:
177 p = join(root, name)
178 if not abspath(p) in paths:
179 rm(p)
180
181 def del_unwanted_files(base):
182 for root, dirs, files in os.walk(base):
183 for name in files:
184 p = join(root, name)
185 if exists(p) and ext(p) == '.pyc':
186 rm(p)
187
188 def copy_to_temp_directory(base):
189 dst = join(tempfile.mkdtemp(), basename(base))
190 shutil.copytree(base, dst)
191 print dst
192 return dst
193
194 def get_script_paths(f):
195 return [re.sub(r'^/*', '', i) for i in re.findall(r'.*?<script.*?src="(.*?)"', open(f).read(), re.DOTALL)]
196
197
198
199 def setup_tmp_deploy(base):
200 tmp = copy_to_temp_directory(abspath(base))
201 bdir = join(tmp, 'build')
202 ignore = ['js']
203 paths = []
204
205 # setup clean build
206 print tmp, bdir
207 if exists(bdir):
208 shutil.rmtree(bdir)
209 os.makedirs(bdir)
210
211 print '[base:', base, '] [dest:', tmp, '] [build dir:', bdir
212
213 for p in rec_find_files(tmp, ext='html', ignore=ignore):
214 ProcessBuildComments(p, tmp, bdir)
215
216 paths.extend(get_script_paths(p))
217
218 # cleanup
219 for i in ignore:
220 del_unused_files( join(tmp, i), [join(tmp, p) for p in paths])
221 del_unwanted_files(tmp)
222
223 return tmp
224
225 def main(base):
226 dply = setup_tmp_deploy(base)
227
228 os.system('cd %s; cd ..; echo `pwd`; appcfg.py -e mail.ciju.cherian@gmail.com update perf-hier' % dply)
229
230 if __name__ == '__main__':
231
232 main('/home/ciju/data/work/perf-hier/')
233 # copy the whole src directory.
234 # make a temporary directory.
235 # copy and create the needed files in the temporary directory.
236 # remove the directories no longer needed.
237 # copy the files in temp dir, to where they belong.
238
239 # write the index file according to instructions.
240
241
242 def rm_key(k, s):
243 os = json.loads(s)
244 ns = {}
245 for i in os:
246 for j in os[i]:
247 if not re.match(r'^'+k, j):
248 if not i in ns:
249 ns[i] = {}
250 ns[i][j] = os[i][j]
251 print i,j
252 return json.dumps(ns)
253
254 def rm_root(root, stat):
255 ostat = json.loads(stat)
256 nstat = {}
257 for i in ostat:
258 if not re.match('^'+root, i):
259 nstat[i] = ostat[i]
260 print i
261 return json.dumps(nstat)
262
Something went wrong with that request. Please try again.