summaryrefslogtreecommitdiff
path: root/scripts/builder
authorGiulio Cesare Solaroli <giulio.cesare@solaroli.it>2012-03-17 14:43:30 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@solaroli.it>2012-03-17 14:43:30 (UTC)
commit58ec03cc3dba43ccd9826148b99bf3d7b8e97d8a (patch) (unidiff)
treec12d695420bb6281708b367d52970eac5615ef1c /scripts/builder
parente7e021141d7906b537b3622ed706017f31222dfd (diff)
parente61e994abb9738d98447b203b9908793da6f560a (diff)
downloadclipperz-58ec03cc3dba43ccd9826148b99bf3d7b8e97d8a.zip
clipperz-58ec03cc3dba43ccd9826148b99bf3d7b8e97d8a.tar.gz
clipperz-58ec03cc3dba43ccd9826148b99bf3d7b8e97d8a.tar.bz2
Merge pull request #31 from gcsolaroli/master
Updated build scripts
Diffstat (limited to 'scripts/builder') (more/less context) (ignore whitespace changes)
-rw-r--r--scripts/builder/backendBuilder.py21
-rw-r--r--scripts/builder/frontendBuilder.py5
-rw-r--r--scripts/builder/repository.py12
3 files changed, 27 insertions, 11 deletions
diff --git a/scripts/builder/backendBuilder.py b/scripts/builder/backendBuilder.py
index 3e61955..5b91678 100644
--- a/scripts/builder/backendBuilder.py
+++ b/scripts/builder/backendBuilder.py
@@ -1,118 +1,131 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: UTF-8 -*- 2# -*- coding: UTF-8 -*-
3 3
4import sys, os, json 4import sys, os, json
5import shutil 5import shutil
6import hashlib 6import hashlib
7 7
8import main 8import main
9 9
10#=================================================================== 10#===================================================================
11 11
12 12
13class BackendBuilder(object): 13class BackendBuilder(object):
14 14
15 def __init__ (self, projectTargetDir, frontends, versions, settings): 15 def __init__ (self, projectTargetDir, frontends, versions, settings):
16 self.projectTargetDir = projectTargetDir 16 self.projectTargetDir = projectTargetDir
17 self.frontends = frontends 17 self.frontends = frontends
18 self.versions = versions 18 self.versions = versions
19 self.settings = settings 19 self.settings = settings
20 20
21 # -------------------------------------------------------------------------- 21 # --------------------------------------------------------------------------
22 22
23 def name (self): 23 def name (self):
24 raise NotImplementedError() 24 raise NotImplementedError()
25 25
26 26
27 def relativePath (self): 27 def relativePath (self):
28 raise NotImplementedError() 28 raise NotImplementedError()
29 29
30 30
31 def compileCode (self): 31 def compileCode (self):
32 raise NotImplementedError() 32 raise NotImplementedError()
33 33
34 34
35 def createPackage (self): 35 def createPackage (self):
36 raise NotImplementedError() 36 raise NotImplementedError()
37 37
38 # -------------------------------------------------------------------------- 38 # --------------------------------------------------------------------------
39 39
40 def sourceFolder (self): 40 def sourceFolder (self):
41 return os.path.join(main.projectBaseDir() , 'backend', self.relativePath(), 'src') 41 return os.path.join(main.projectBaseDir() , 'backend', self.relativePath(), 'src')
42 42
43 43
44 def tempFolder (self): 44 def tempFolder (self):
45 return os.path.join(self.projectTargetDir, '.tmp', self.relativePath()) 45 return os.path.join(self.projectTargetDir, '.tmp', self.relativePath())
46 46
47 47
48 def frontEndTempFolder (self): 48 def frontEndTempFolder (self):
49 return self.tempFolder() 49 return self.tempFolder()
50 50
51 51
52 def developmentTargetFolder (self): 52 def developmentTargetFolder (self):
53 return os.path.join(self.projectTargetDir, 'development', self.relativePath()) 53 return os.path.join(self.projectTargetDir, 'development', self.relativePath())
54 54
55 def targetFolder (self): 55 def targetFolder (self):
56 return os.path.join(self.projectTargetDir, self.relativePath()) 56 return os.path.join(self.projectTargetDir, self.relativePath())
57 57
58 # -------------------------------------------------------------------------- 58 # --------------------------------------------------------------------------
59 59
60 def writeToFolder (self, folder, filename, content): 60 def writeToFolder (self, folder, filename, content):
61 file = open(os.path.join(folder, filename), 'w') 61 file = open(os.path.join(folder, filename), 'w')
62 file.write(content.encode('utf-8')) 62 file.write(content.encode('utf-8'))
63 file.close() 63 file.close()
64 64
65 65
66 def configureIndexContent (self, indexContent, requestPathPrefix = ".."): 66 def configureIndexContent (self, indexContent, requestPathPrefix = ".."):
67 result = indexContent 67 result = indexContent
68 result = result.replace( '@request.path@', requestPathPrefix + '/' + self.settings['request.path'] ) 68 result = result.replace( '@request.path@', requestPathPrefix + '/' + self.settings['request.path'] )
69 result = result.replace( '@should.pay.toll@', self.settings['should.pay.toll'] ) 69 result = result.replace( '@should.pay.toll@', self.settings['should.pay.toll'] )
70 70
71 return result 71 return result
72 72
73 73
74 def logChecksums (self, content, message): 74 def logChecksums (self, content, message):
75 md5Digest = hashlib.md5(content.encode('utf-8')).hexdigest() 75 md5Digest = hashlib.md5(content.encode('utf-8')).hexdigest()
76 shaDigest = hashlib.sha1(content.encode('utf-8')).hexdigest() 76 shaDigest = hashlib.sha1(content.encode('utf-8')).hexdigest()
77 sha256Digest= hashlib.sha256(content.encode('utf-8')).hexdigest() 77 sha256Digest= hashlib.sha256(content.encode('utf-8')).hexdigest()
78 print message + ": " + md5Digest + " (md5)" 78 print message + ": " + md5Digest + " (md5)"
79 print message + ": " + shaDigest + " (sha1)" 79 print message + ": " + shaDigest + " (sha1)"
80 print message + ": " + sha256Digest + " (sha256)" 80 print message + ": " + sha256Digest + " (sha256)"
81 81
82 82
83 def shouldCompileCode (self): 83 def shouldCompileCode (self):
84 return ('debug' in self.versions) or ('install' in self.versions) 84 return ('debug' in self.versions) or ('install' in self.versions)
85 85
86 86
87 def run (self): 87 def run (self):
88 print self.name() + " - RUN" 88 print self.name() + " - RUN"
89 89
90 if self.shouldCompileCode(): 90 if self.shouldCompileCode():
91 self.compileCode() 91 self.compileCode()
92 92
93 for frontend in self.frontends: 93 for frontend in self.frontends:
94 if (frontend.module == frontend.submodule):
95 submoduleExtension = ''
96 else:
97 submoduleExtension = '.' + frontend.submodule
98
94 main.createFolder(os.path.join(self.frontEndTempFolder(), frontend.module)) 99 main.createFolder(os.path.join(self.frontEndTempFolder(), frontend.module))
95 100
96 if 'debug' in self.versions: 101 if 'debug' in self.versions:
97 frontend.copyResourcesToFolder(self.frontEndTempFolder()) 102 frontend.copyResourcesToFolder(self.frontEndTempFolder())
98 103
99 index = self.configureIndexContent(frontend.assemble(assemblyMode='DEBUG', versionType='DEBUG')) 104 index = self.configureIndexContent(frontend.assemble(assemblyMode='DEBUG', versionType='DEBUG'))
100 self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index_debug.html'), index) 105 self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index_debug' + submoduleExtension + '.html'), index)
101 106
102 if 'install' in self.versions: 107 if 'install' in self.versions:
103 index = self.configureIndexContent(frontend.assemble()) 108 index = self.configureIndexContent(frontend.assemble())
104 self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index.html'), index) 109 self.writeToFolder(self.frontEndTempFolder(), os.path.join(frontend.module, 'index' + submoduleExtension + '.html'), index)
105 110
106 self.logChecksums(index, "[" + self.name() + " - " + frontend.module + "] index.html checksum") 111 self.logChecksums(index, "[" + self.name() + " - " + frontend.module + "] index" + submoduleExtension + ".html checksum")
107 112
108 self.createPackage() 113 self.createPackage()
109 114
110 if 'development' in self.versions: 115 if 'development' in self.versions:
111 for frontend in self.frontends: 116 for frontend in self.frontends:
117 if (frontend.module == frontend.submodule):
118 submoduleExtension = ''
119 else:
120 submoduleExtension = '.' + frontend.submodule
121
122 print "FRONTEND module: " + frontend.module
123 print "FRONTEND submodule: " + frontend.submodule
124
112 main.createFolder(os.path.join(self.developmentTargetFolder(), frontend.module)) 125 main.createFolder(os.path.join(self.developmentTargetFolder(), frontend.module))
113 126
114 index = self.configureIndexContent(frontend.assemble(assemblyMode='DEVELOPMENT', versionType='DEBUG'), self.settings['development.settings']['url']) 127 index = self.configureIndexContent(frontend.assemble(assemblyMode='DEVELOPMENT', versionType='DEBUG'), self.settings['development.settings']['url'])
115 self.writeToFolder(self.developmentTargetFolder(), os.path.join(frontend.module, 'index.html'), index) 128 self.writeToFolder(self.developmentTargetFolder(), os.path.join(frontend.module, 'index' + submoduleExtension + '.html'), index)
116 129
117 130
118#=================================================================== 131#===================================================================
diff --git a/scripts/builder/frontendBuilder.py b/scripts/builder/frontendBuilder.py
index dae837b..1f0f92f 100644
--- a/scripts/builder/frontendBuilder.py
+++ b/scripts/builder/frontendBuilder.py
@@ -1,389 +1,390 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: UTF-8 -*- 2# -*- coding: UTF-8 -*-
3 3
4import sys, os, re 4import sys, os, re
5import cssmin 5import cssmin
6import jsmin 6import jsmin
7import codecs 7import codecs
8import shutil 8import shutil
9import StringIO 9import StringIO
10import urllib 10import urllib
11 11
12import main 12import main
13 13
14class FrontendBuilder(object): 14class FrontendBuilder(object):
15 15
16 def __init__ (self, frontend, settings, repositoryVersion): 16 def __init__ (self, frontend, settings, repositoryVersion):
17 if '.' in frontend: 17 if '.' in frontend:
18 moduleComponents = frontend.split('.') 18 moduleComponents = frontend.split('.')
19 self.module = moduleComponents[0] 19 self.module = moduleComponents[0]
20 self.submodule = moduleComponents[1] 20 self.submodule = moduleComponents[1]
21 else: 21 else:
22 self.module = frontend 22 self.module = frontend
23 self.submodule = frontend 23 self.submodule = frontend
24 24
25 self.settings = settings 25 self.settings = settings
26 self.projectDir = main.projectBaseDir() 26 self.projectDir = main.projectBaseDir()
27 # self.repository = repository.repositoryWithPath(self.projectDir) 27 # self.repository = repository.repositoryWithPath(self.projectDir)
28 self.repositoryVersion = repositoryVersion 28 self.repositoryVersion = repositoryVersion
29 self.processedFiles = {} 29 self.processedFiles = {}
30 30
31 31
32 def log (self, message): 32 def log (self, message):
33 print "frontend [" + self.module + "]: " + message 33 print "frontend [" + self.module + "]: " + message
34 34
35 35
36 def absolutePathForSources (self): 36 def absolutePathForSources (self):
37 return os.path.join(self.projectDir, 'frontend', self.module) 37 return os.path.join(self.projectDir, 'frontend', self.module)
38 38
39 39
40 def absolutePathForSourceFile (self, basePath, file): 40 def absolutePathForSourceFile (self, basePath, file):
41 return os.path.join(self.absolutePathForSources(), basePath, file) 41 return os.path.join(self.absolutePathForSources(), basePath, file)
42 42
43 43
44 def absolutePathForTargetFile (self, folder, basePath, file): 44 def absolutePathForTargetFile (self, folder, basePath, file):
45 return os.path.join(folder, self.module, basePath, file) 45 return os.path.join(folder, self.module, basePath, file)
46 46
47 47
48 def filterFiles (self, files): 48 def filterFiles (self, files):
49 result = [] 49 result = []
50 50
51 for file in files: 51 for file in files:
52 if file.startswith('--'): 52 if file.startswith('--'):
53 pass 53 pass
54 else: 54 else:
55 result.append(file) 55 result.append(file)
56 56
57 return result 57 return result
58 58
59 59
60 def copyResources (self, sourceFolder, destinationFolder, fileType): 60 def copyResources (self, sourceFolder, destinationFolder, fileType):
61 for file in self.filterFiles(self.settings[fileType]): 61 for file in self.filterFiles(self.settings[fileType]):
62 src = self.absolutePathForSourceFile(fileType, file) 62 src = self.absolutePathForSourceFile(fileType, file)
63 dst = self.absolutePathForTargetFile(destinationFolder, fileType, file) 63 dst = self.absolutePathForTargetFile(destinationFolder, fileType, file)
64 main.createFolder(os.path.dirname(dst)) 64 main.createFolder(os.path.dirname(dst))
65 shutil.copy2(src, dst) 65 shutil.copy2(src, dst)
66 66
67 67
68 def copyResourcesToFolder (self, targetFolder): 68 def copyResourcesToFolder (self, targetFolder):
69 self.copyResources(self.projectDir, targetFolder, 'css') 69 self.copyResources(self.projectDir, targetFolder, 'css')
70 self.copyResources(self.projectDir, targetFolder, 'js') 70 self.copyResources(self.projectDir, targetFolder, 'js')
71 71
72 72
73 def loadFilesContent (self, basePath, files): 73 def loadFilesContent (self, basePath, files):
74 result = "" 74 result = ""
75 75
76 for file in self.filterFiles(files): 76 for file in self.filterFiles(files):
77 try: 77 try:
78 fileHandler = codecs.open(self.absolutePathForSourceFile(basePath, file), 'r', 'utf-8') 78 fileHandler = codecs.open(self.absolutePathForSourceFile(basePath, file), 'r', 'utf-8')
79 except: 79 except:
80 print "FILE: " + file 80 print "FILE: " + file
81 81
82 result += fileHandler.read() + '\n' 82 result += fileHandler.read() + '\n'
83 fileHandler.close() 83 fileHandler.close()
84 84
85 return result 85 return result
86 86
87 87
88 def template (self): 88 def template (self):
89 processedFile = 'html_template' 89 processedFile = 'html_template'
90 if not self.processedFiles.has_key(processedFile): 90 if not self.processedFiles.has_key(processedFile):
91 self.processedFiles[processedFile] = self.loadFilesContent('html', ['index_template.html']) 91 #self.processedFiles[processedFile] = self.loadFilesContent('html', ['index_template.html'])
92 self.processedFiles[processedFile] = self.loadFilesContent('html', [self.settings['html.template']])
92 93
93 return self.processedFiles[processedFile] 94 return self.processedFiles[processedFile]
94 95
95 96
96 def cssminCompressor (self, css): 97 def cssminCompressor (self, css):
97 # package found here: 98 # package found here:
98 # - http://stackoverflow.com/questions/222581/python-script-for-minifying-css/2396777#2396777 99 # - http://stackoverflow.com/questions/222581/python-script-for-minifying-css/2396777#2396777
99 # actual downloaded version: http://pypi.python.org/pypi/cssmin/0.1.4 100 # actual downloaded version: http://pypi.python.org/pypi/cssmin/0.1.4
100 return cssmin.cssmin(css) 101 return cssmin.cssmin(css)
101 102
102 103
103 def regexCssCompressor (self, css): 104 def regexCssCompressor (self, css):
104 # http://stackoverflow.com/questions/222581/python-script-for-minifying-css/223689#223689 105 # http://stackoverflow.com/questions/222581/python-script-for-minifying-css/223689#223689
105 106
106 # remove comments - this will break a lot of hacks :-P 107 # remove comments - this will break a lot of hacks :-P
107 css = re.sub( r'\s*/\*\s*\*/', "$$HACK1$$", css ) # preserve IE<6 comment hack 108 css = re.sub( r'\s*/\*\s*\*/', "$$HACK1$$", css ) # preserve IE<6 comment hack
108 css = re.sub( r'/\*[\s\S]*?\*/', "", css ) 109 css = re.sub( r'/\*[\s\S]*?\*/', "", css )
109 css = css.replace( "$$HACK1$$", '/**/' ) # preserve IE<6 comment hack 110 css = css.replace( "$$HACK1$$", '/**/' ) # preserve IE<6 comment hack
110 111
111 # url() doesn't need quotes 112 # url() doesn't need quotes
112 css = re.sub( r'url\((["\'])([^)]*)\1\)', r'url(\2)', css ) 113 css = re.sub( r'url\((["\'])([^)]*)\1\)', r'url(\2)', css )
113 114
114 # spaces may be safely collapsed as generated content will collapse them anyway 115 # spaces may be safely collapsed as generated content will collapse them anyway
115 css = re.sub( r'\s+', ' ', css ) 116 css = re.sub( r'\s+', ' ', css )
116 117
117 # shorten collapsable colors: #aabbcc to #abc 118 # shorten collapsable colors: #aabbcc to #abc
118 css = re.sub( r'#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)', r'#\1\2\3\4', css ) 119 css = re.sub( r'#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)', r'#\1\2\3\4', css )
119 120
120 # fragment values can loose zeros 121 # fragment values can loose zeros
121 css = re.sub( r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css ) 122 css = re.sub( r':\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;', r':\1;', css )
122 123
123 for rule in re.findall( r'([^{]+){([^}]*)}', css ): 124 for rule in re.findall( r'([^{]+){([^}]*)}', css ):
124 125
125 # we don't need spaces around operators 126 # we don't need spaces around operators
126 selectors = [re.sub( r'(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])', r'', selector.strip() ) for selector in rule[0].split( ',' )] 127 selectors = [re.sub( r'(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])', r'', selector.strip() ) for selector in rule[0].split( ',' )]
127 128
128 # order is important, but we still want to discard repetitions 129 # order is important, but we still want to discard repetitions
129 properties = {} 130 properties = {}
130 porder = [] 131 porder = []
131 for prop in re.findall( '(.*?):(.*?)(;|$)', rule[1] ): 132 for prop in re.findall( '(.*?):(.*?)(;|$)', rule[1] ):
132 key = prop[0].strip().lower() 133 key = prop[0].strip().lower()
133 if key not in porder: porder.append( key ) 134 if key not in porder: porder.append( key )
134 properties[ key ] = prop[1].strip() 135 properties[ key ] = prop[1].strip()
135 136
136 # output rule if it contains any declarations 137 # output rule if it contains any declarations
137 if properties: 138 if properties:
138 print "%s{%s}" % ( ','.join( selectors ), ''.join(['%s:%s;' % (key, properties[key]) for key in porder])[:-1] ) 139 print "%s{%s}" % ( ','.join( selectors ), ''.join(['%s:%s;' % (key, properties[key]) for key in porder])[:-1] )
139 140
140 return css 141 return css
141 142
142 143
143 def compressCSS (self, css): 144 def compressCSS (self, css):
144 self.log("compressing CSS") 145 self.log("compressing CSS")
145 #return self.regexCssCompressor(css) 146 #return self.regexCssCompressor(css)
146 return self.cssminCompressor(css) 147 return self.cssminCompressor(css)
147 148
148 149
149 #========================================================================== 150 #==========================================================================
150 151
151 def compressJS_jsmin (self, js, description): 152 def compressJS_jsmin (self, js, description):
152 self.log("compressing " + description + " code") 153 self.log("compressing " + description + " code")
153 original = StringIO.StringIO(js) 154 original = StringIO.StringIO(js)
154 output = StringIO.StringIO() 155 output = StringIO.StringIO()
155 156
156 jsMinifier = jsmin.JavascriptMinify() 157 jsMinifier = jsmin.JavascriptMinify()
157 jsMinifier.minify(original, output) 158 jsMinifier.minify(original, output)
158 159
159 result = output.getvalue() 160 result = output.getvalue()
160 161
161 original.close() 162 original.close()
162 output.close() 163 output.close()
163 164
164 return result 165 return result
165 166
166 def compressJS_closureCompiler (self, js, description): 167 def compressJS_closureCompiler (self, js, description):
167 #Googles Closure compiler 168 #Googles Closure compiler
168 #java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js 169 #java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js
169 170
170 result = js 171 result = js
171 172
172 return result 173 return result
173 174
174 175
175 def compressJS (self, js, description): 176 def compressJS (self, js, description):
176 return self.compressJS_jsmin(js, description) 177 return self.compressJS_jsmin(js, description)
177 #return self.compressJS_closureCompiler(js, description) 178 #return self.compressJS_closureCompiler(js, description)
178 179
179 180
180 #========================================================================== 181 #==========================================================================
181 182
182 def packBookmarklet (self, bookmakeletCode, version): 183 def packBookmarklet (self, bookmakeletCode, version):
183 replacers = [ 184 replacers = [
184 ('isLoginForm', 'ilf'), 185 ('isLoginForm', 'ilf'),
185 ('findLoginForm', 'flf'), 186 ('findLoginForm', 'flf'),
186 ('findLoginForm', 'flf'), 187 ('findLoginForm', 'flf'),
187 ('formParameters', 'fp' ), 188 ('formParameters', 'fp' ),
188 ('pageParameters', 'pp' ), 189 ('pageParameters', 'pp' ),
189 ('serializeJSON', 'sj' ), 190 ('serializeJSON', 'sj' ),
190 ('reprString', 'rs' ), 191 ('reprString', 'rs' ),
191 ('logFormParameters', 'lfp'), 192 ('logFormParameters', 'lfp'),
192 ('loadClipperzBookmarklet','lcb'), 193 ('loadClipperzBookmarklet','lcb'),
193 ('loginForm', 'lf' ), 194 ('loginForm', 'lf' ),
194 ('parameters', 'p' ), 195 ('parameters', 'p' ),
195 ('inputElementValues', 'iev'), 196 ('inputElementValues', 'iev'),
196 ] 197 ]
197 result = self.compressJS(bookmakeletCode, version + " bookmarklet") 198 result = self.compressJS(bookmakeletCode, version + " bookmarklet")
198 199
199 result = re.sub('\n', ' ', result) #Fit all in a single line 200 result = re.sub('\n', ' ', result) #Fit all in a single line
200 # result = re.sub('\s+', ' ', result) #Collapse "redundant" spaces. WARNING: this could have some evil side effects on constant strings used inside to code!! 201 # result = re.sub('\s+', ' ', result) #Collapse "redundant" spaces. WARNING: this could have some evil side effects on constant strings used inside to code!!
201 # result = re.sub('\s?([,\+=\(\)\{\};])\s?', '\\1', result) 202 # result = re.sub('\s?([,\+=\(\)\{\};])\s?', '\\1', result)
202 203
203 for replacer in replacers: 204 for replacer in replacers:
204 result = re.sub(replacer[0], replacer[1], result) 205 result = re.sub(replacer[0], replacer[1], result)
205 206
206 # <!-- escaping required to handle the bookmarklet code within the javascript code --> 207 # <!-- escaping required to handle the bookmarklet code within the javascript code -->
207 result = re.sub('\://', '%3a%2f%2f',result) 208 result = re.sub('\://', '%3a%2f%2f',result)
208 result = re.sub('/', '%2f', result) 209 result = re.sub('/', '%2f', result)
209 # result = re.sub('"', '%22', result) 210 # result = re.sub('"', '%22', result)
210 result = re.sub('"', '\\"', result) 211 result = re.sub('"', '\\"', result)
211 result = re.sub('\"', '%22', result) 212 result = re.sub('\"', '%22', result)
212 result = re.sub('\'', '%22', result) 213 result = re.sub('\'', '%22', result)
213 result = re.sub('\\\\', '%5c', result) 214 result = re.sub('\\\\', '%5c', result)
214 result = result.strip() 215 result = result.strip()
215 result = 'javascript:' + result 216 result = 'javascript:' + result
216 217
217 # replacers = [ 218 # replacers = [
218 # ('aForm', '_1' ), 219 # ('aForm', '_1' ),
219 # ('inputFields', '_2' ), 220 # ('inputFields', '_2' ),
220 # ('passwordFieldsFound','_3' ), 221 # ('passwordFieldsFound','_3' ),
221 # ('aDocument', '_6' ), 222 # ('aDocument', '_6' ),
222 # ('aLevel', '_7' ), 223 # ('aLevel', '_7' ),
223 # # ('result', '_8' ), 224 # # ('result', '_8' ),
224 # ('documentForms', '_9' ), 225 # ('documentForms', '_9' ),
225 # ('iFrames', '_c' ), 226 # ('iFrames', '_c' ),
226 # ('anInputElement', '_d' ), 227 # ('anInputElement', '_d' ),
227 # ('options', '_f' ), 228 # ('options', '_f' ),
228 # ('option', '_12'), 229 # ('option', '_12'),
229 # ('aLoginForm', '_13'), 230 # ('aLoginForm', '_13'),
230 # # ('action', '_17'), 231 # # ('action', '_17'),
231 # ('radioValues', '_18'), 232 # ('radioValues', '_18'),
232 # ('radioValueName', '_19'), 233 # ('radioValueName', '_19'),
233 # ('inputElement', '_1a'), 234 # ('inputElement', '_1a'),
234 # ('elementValues', '_1b'), 235 # ('elementValues', '_1b'),
235 # ('radioValue', '_1c'), 236 # ('radioValue', '_1c'),
236 # ('values', '_1d'), 237 # ('values', '_1d'),
237 # ('objtype', '_21'), 238 # ('objtype', '_21'),
238 # ('useKey', '_27'), 239 # ('useKey', '_27'),
239 # ('bookmarkletDiv', '_28'), 240 # ('bookmarkletDiv', '_28'),
240 # ('someParameters', '_29'), 241 # ('someParameters', '_29'),
241 # ('anException', '_2a'), 242 # ('anException', '_2a'),
242 # ('newDiv', '_2b'), 243 # ('newDiv', '_2b'),
243 # ('base_url', '_2c'), 244 # ('base_url', '_2c'),
244 # ('help_url', '_2d'), 245 # ('help_url', '_2d'),
245 # ('logo_image_url', '_2e'), 246 # ('logo_image_url', '_2e'),
246 # ('background_image_url','_2f'), 247 # ('background_image_url','_2f'),
247 # ('close_image_url', '_30'), 248 # ('close_image_url', '_30'),
248 # #('bookmarklet_textarea','_31'), 249 # #('bookmarklet_textarea','_31'),
249 # ('innerHTML', '_32'), 250 # ('innerHTML', '_32'),
250 # ] 251 # ]
251 # for replacer in replacers: 252 # for replacer in replacers:
252 # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) 253 # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result)
253 254
254 # replacers = [ 255 # replacers = [
255 # ('headNode', '_1' ), 256 # ('headNode', '_1' ),
256 # ('clipperzScriptNode','_2' ), 257 # ('clipperzScriptNode','_2' ),
257 # ] 258 # ]
258 # for replacer in replacers: 259 # for replacer in replacers:
259 # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result) 260 # result = re.sub('([^\.])' + replacer[0], '\\1' + replacer[1], result)
260 261
261 # result = re.sub(';', ';\n', result) 262 # result = re.sub(';', ';\n', result)
262 263
263 return result 264 return result
264 265
265 266
266 267
267 def bookmarklet (self): 268 def bookmarklet (self):
268 cacheKey = 'bookmarklet' 269 cacheKey = 'bookmarklet'
269 if not self.processedFiles.has_key(cacheKey): 270 if not self.processedFiles.has_key(cacheKey):
270 result = 'bookmarklet="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet.js']), "regular") + '";bookmarklet_ie="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet_IE.js']), "IE") + '";' 271 result = 'bookmarklet="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet.js']), "regular") + '";bookmarklet_ie="' + self.packBookmarklet(self.loadFilesContent('js', ['Bookmarklet_IE.js']), "IE") + '";'
271 self.processedFiles[cacheKey] = result 272 self.processedFiles[cacheKey] = result
272 else: 273 else:
273 result = self.processedFiles[cacheKey] 274 result = self.processedFiles[cacheKey]
274 275
275 return result 276 return result
276 277
277 278
278 def replaceTemplatePlaceholders (self, pageTitle, copyright, css, code, jsLoadMode, version, versionType): 279 def replaceTemplatePlaceholders (self, pageTitle, copyright, css, code, jsLoadMode, version, versionType):
279 result = self.template() 280 result = self.template()
280 281
281 result = result.replace('@page.title@', pageTitle, 1) 282 result = result.replace('@page.title@', pageTitle, 1)
282 result = result.replace('@copyright@', copyright, 1) 283 result = result.replace('@copyright@', copyright, 1)
283 result = result.replace('@css@', css, 1) 284 result = result.replace('@css@', css, 1)
284 #result = result.replace('@bookmarklet@', bookmarklet,1) 285 #result = result.replace('@bookmarklet@', bookmarklet,1)
285 result = result.replace('@application.version@', version, 1) 286 result = result.replace('@application.version@', version, 1)
286 result = result.replace('@application.version.type@', versionType,1) 287 result = result.replace('@application.version.type@', versionType,1)
287 result = result.replace('@js_' + jsLoadMode + '@', code, 1) 288 result = result.replace('@js_' + jsLoadMode + '@', code, 1)
288 289
289 result = re.sub('@js_[^@]+@', '', result) 290 result = re.sub('@js_[^@]+@', '', result)
290 291
291 return result 292 return result
292 293
293 294
294 def assembleCopyrightHeader (self): 295 def assembleCopyrightHeader (self):
295 processedFile = 'copyright' 296 processedFile = 'copyright'
296 if not self.processedFiles.has_key(processedFile): 297 if not self.processedFiles.has_key(processedFile):
297 #self.log("assembling copyright header") 298 #self.log("assembling copyright header")
298 copyrightValues = self.settings['copyright.values'] 299 copyrightValues = self.settings['copyright.values']
299 license = self.loadFilesContent('../../properties', ['license.txt']) 300 license = self.loadFilesContent('../../properties', ['license.txt'])
300 result = self.loadFilesContent('properties', ['creditsAndCopyrights.txt']) 301 result = self.loadFilesContent('properties', ['creditsAndCopyrights.txt'])
301 302
302 result = re.sub('@clipperz.license@', license, result) 303 result = re.sub('@clipperz.license@', license, result)
303 for key in copyrightValues: 304 for key in copyrightValues:
304 result = re.sub('@'+key+'@', copyrightValues[key], result) 305 result = re.sub('@'+key+'@', copyrightValues[key], result)
305 306
306 self.processedFiles[processedFile] = result 307 self.processedFiles[processedFile] = result
307 308
308 return self.processedFiles[processedFile] 309 return self.processedFiles[processedFile]
309 310
310 311
311 def cssTagsForFiles (self, basePath, files): 312 def cssTagsForFiles (self, basePath, files):
312 #<link rel="stylesheet" type="text/css" href="./css/reset-min.css" /> 313 #<link rel="stylesheet" type="text/css" href="./css/reset-min.css" />
313 return '\n'.join(map(lambda file: '<link rel="stylesheet" type="text/css" href="' + basePath + '/' + file + '" />', files)) 314 return '\n'.join(map(lambda file: '<link rel="stylesheet" type="text/css" href="' + basePath + '/' + file + '" />', files))
314 315
315 316
316 def cssTagForContent (self, content): 317 def cssTagForContent (self, content):
317 return '<style type="text/css">' + content + '</style>' 318 return '<style type="text/css">' + content + '</style>'
318 319
319 320
320 def scriptTagsForFiles (self, basePath, files): 321 def scriptTagsForFiles (self, basePath, files):
321 #<script type='text/javascript' src='./js/src/bookmarklet.js'></script> 322 #<script type='text/javascript' src='./js/src/bookmarklet.js'></script>
322 return '\n'.join(map(lambda file: '<script type="text/javascript" src="' + basePath + '/' + file + '"></script>', files)) 323 return '\n'.join(map(lambda file: '<script type="text/javascript" src="' + basePath + '/' + file + '" charset="utf-8"></script>', files))
323 324
324 325
325 def scriptTagForContent (self, content): 326 def scriptTagForContent (self, content):
326 return '<script>' + content + '</script>' 327 return '<script>' + content + '</script>'
327 328
328 329
329 def assembleVersion (self, pageTitle, copyright, css, js, jsLoadMode, version, versionType): 330 def assembleVersion (self, pageTitle, copyright, css, js, jsLoadMode, version, versionType):
330 cacheKey = version + "-" + versionType 331 cacheKey = version + "-" + versionType
331 if not self.processedFiles.has_key(cacheKey): 332 if not self.processedFiles.has_key(cacheKey):
332 result = self.replaceTemplatePlaceholders(pageTitle, copyright, css, js, jsLoadMode, version, versionType) 333 result = self.replaceTemplatePlaceholders(pageTitle, copyright, css, js, jsLoadMode, version, versionType)
333 self.processedFiles[cacheKey] = result 334 self.processedFiles[cacheKey] = result
334 else: 335 else:
335 result = self.processedFiles[cacheKey] 336 result = self.processedFiles[cacheKey]
336 337
337 #self.log("# cacheKey:\n" + result) 338 #self.log("# cacheKey:\n" + result)
338 return result 339 return result
339 340
340 341
341 def assemble (self, assemblyMode='INSTALL', versionType='LIVE'): 342 def assemble (self, assemblyMode='INSTALL', versionType='LIVE'):
342 343
343 if versionType == 'LIVE': 344 if versionType == 'LIVE':
344 pageTitle = "Clipperz - " + self.module 345 pageTitle = "Clipperz - " + self.module
345 else: 346 else:
346 pageTitle = "Clipperz - " + self.module + " [" + versionType + " - " + assemblyMode +"]" 347 pageTitle = "Clipperz - " + self.module + " [" + versionType + " - " + assemblyMode +"]"
347 348
348 if assemblyMode == 'INSTALL': 349 if assemblyMode == 'INSTALL':
349 copyright = self.assembleCopyrightHeader() 350 copyright = self.assembleCopyrightHeader()
350 css =self.cssTagForContent(self.compressCSS(self.loadFilesContent('css', self.settings['css']))) 351 css =self.cssTagForContent(self.compressCSS(self.loadFilesContent('css', self.settings['css'])))
351 js =self.scriptTagForContent( 352 js =self.scriptTagForContent(
352 self.bookmarklet() + 353 self.bookmarklet() +
353 '\n' + 354 '\n' +
354 self.compressJS(self.loadFilesContent('js', self.settings['js']), "application") 355 self.compressJS(self.loadFilesContent('js', self.settings['js']), "application")
355 ) 356 )
356 jsLoadMode = 'EMBEDDED' 357 jsLoadMode = 'EMBEDDED'
357 358
358 elif assemblyMode == 'DEBUG': 359 elif assemblyMode == 'DEBUG':
359 copyright = self.assembleCopyrightHeader() 360 copyright = self.assembleCopyrightHeader()
360 css =self.cssTagsForFiles('./css', self.filterFiles(self.settings['css'])) 361 css =self.cssTagsForFiles('./css', self.filterFiles(self.settings['css']))
361 js =self.scriptTagForContent(self.bookmarklet()) + \ 362 js =self.scriptTagForContent(self.bookmarklet()) + \
362 '\n' + \ 363 '\n' + \
363 self.scriptTagsForFiles('./js', self.filterFiles(self.settings['js'])) 364 self.scriptTagsForFiles('./js', self.filterFiles(self.settings['js']))
364 jsLoadMode = 'LINKED' 365 jsLoadMode = 'LINKED'
365 366
366 elif assemblyMode == 'DEVELOPMENT': 367 elif assemblyMode == 'DEVELOPMENT':
367 copyright = "" 368 copyright = ""
368 css =self.cssTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'css')), self.filterFiles(self.settings['css'])) 369 css =self.cssTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'css')), self.filterFiles(self.settings['css']))
369 js =self.scriptTagForContent(self.bookmarklet()) + \ 370 js =self.scriptTagForContent(self.bookmarklet()) + \
370 '\n' + \ 371 '\n' + \
371 self.scriptTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'js')), self.filterFiles(self.settings['js'])) 372 self.scriptTagsForFiles('file://' + str(os.path.join(self.absolutePathForSources(), 'js')), self.filterFiles(self.settings['js']))
372 jsLoadMode = 'LINKED' 373 jsLoadMode = 'LINKED'
373 374
374 else: 375 else:
375 raise NotImplementedError() 376 raise NotImplementedError()
376 377
377 return self.assembleVersion( 378 return self.assembleVersion(
378 pageTitle = pageTitle, 379 pageTitle = pageTitle,
379 copyright = copyright, 380 copyright = copyright,
380 css = css, 381 css = css,
381 js = js, 382 js = js,
382 jsLoadMode = jsLoadMode, 383 jsLoadMode = jsLoadMode,
383 version = self.repositoryVersion, 384 version = self.repositoryVersion,
384 versionType = versionType 385 versionType = versionType
385 ) 386 )
386 387
387 388
388 389
389 390
diff --git a/scripts/builder/repository.py b/scripts/builder/repository.py
index 89db9a5..f8528c2 100644
--- a/scripts/builder/repository.py
+++ b/scripts/builder/repository.py
@@ -1,75 +1,77 @@
1#!/usr/bin/env python 1#!/usr/bin/env python
2# -*- coding: UTF-8 -*- 2# -*- coding: UTF-8 -*-
3 3
4 4
5def repositoryWithPath (path): 5def repositoryWithPath (path):
6 try: 6 try:
7 from dulwich.repo import Repo 7 from git import Repo
8 8
9 repo = Repo(path) 9 repo = Repo(path)
10 result = GitRepository(repo, path) 10 result = GitRepository(repo, path)
11 except: 11 except ImportError:
12 print "Failed to import git, please install http://gitorious.org/git-python"
13 #except:
12 from mercurial import ui, hg 14 from mercurial import ui, hg
13 15
14 repo = hg.repository(ui.ui(), path) 16 repo = hg.repository(ui.ui(), path)
15 result = HgRepository(repo, path) 17 result = HgRepository(repo, path)
16 18
17 return result 19 return result
18 20
19 21
20#=================================================================== 22#===================================================================
21 23
22 24
23class Repository(object): 25class Repository(object):
24 26
25 def __init__ (self, repository, path): 27 def __init__ (self, repository, path):
26 self.repository = repository 28 self.repository = repository
27 self.path = path 29 self.path = path
28 30
29 31
30 def revision (self): 32 def revision (self):
31 raise NotImplementedError() 33 raise NotImplementedError()
32 34
33 35
34 def areTherePendingChanges (self): 36 def areTherePendingChanges (self):
35 raise NotImplementedError() 37 raise NotImplementedError()
36 38
37 39
38 def version (self): 40 def version (self):
39 result = self.revision() 41 result = self.revision()
40 if self.areTherePendingChanges(): 42 if self.areTherePendingChanges():
41 result = '>>> ' + result + ' <<<' 43 result = '>>> ' + result + ' <<<'
42 44
43 # print "VERSION: " + result 45 # print "VERSION: " + result
44 return result 46 return result
45 47
46 48
47#=================================================================== 49#===================================================================
48 50
49 51
50class GitRepository(Repository): 52class GitRepository(Repository):
51 53
52 def revision (self): 54 def revision (self):
53 return repository.refs['HEAD'] 55 return self.repository.head.commit.hexsha
54 56
55 57
56 def areTherePendingChanges (self): 58 def areTherePendingChanges (self):
57 return repository.is_dirty() 59 return self.repository.is_dirty()
58 60
59 61
60#=================================================================== 62#===================================================================
61 63
62 64
63class HgRepository(Repository): 65class HgRepository(Repository):
64 #http://mercurial.selenic.com/wiki/MercurialApi 66 #http://mercurial.selenic.com/wiki/MercurialApi
65 67
66 def revision (self): 68 def revision (self):
67 return 'hg:' + str(self.repository['tip']) 69 return 'hg:' + str(self.repository['tip'])
68 70
69 71
70 def areTherePendingChanges (self): 72 def areTherePendingChanges (self):
71 # TODO: FIXME: repository.status() does not report 'unknown(?)' files. :( 73 # TODO: FIXME: repository.status() does not report 'unknown(?)' files. :(
72 return not all(map(lambda fileList: len(fileList) == 0, self.repository.status())) 74 return not all(map(lambda fileList: len(fileList) == 0, self.repository.status()))
73 75
74 76
75#=================================================================== 77#===================================================================