1
#!/usr/bin/env python
2
import itertools
3
import os
4
import platform
5
import re
6
import shutil
7
import sys
8
from subprocess import *
9
from optparse import OptionParser
10
11
excludedFilesAndDirectories = (
12
    '.gitattributes',
13
    '.gitignore',
14
    'Android.mk',
15
    'DerivedSources.pro',
16
    'GNUmakefile.am',
17
    'Source/JavaScriptCore/API/tests',
18
    'Source/JavaScriptCore/AllInOneFile.cpp',
19
    'Source/JavaScriptCore/Android.mk',
20
    'Source/JavaScriptCore/Android.v8.wtf.mk',
21
    'Source/JavaScriptCore/Configurations',
22
    'Source/JavaScriptCore/DerivedSources.make',
23
    'Source/JavaScriptCore/DerivedSources.pro',
24
    'Source/JavaScriptCore/GNUmakefile.am',
25
    'Source/JavaScriptCore/JavaScriptCore.exp',
26
    'Source/JavaScriptCore/JavaScriptCore.gyp',
27
    'Source/JavaScriptCore/JavaScriptCore.vcproj',
28
    'Source/JavaScriptCore/JavaScriptCore.xcodeproj',
29
    'Source/JavaScriptCore/JavaScriptCoreSources.bkl',
30
    'Source/JavaScriptCore/Makefile',
31
    'Source/JavaScriptCore/icu',
32
    'Source/JavaScriptCore/jsc.pro',
33
    'Source/JavaScriptCore/jscore.bkl',
34
    'Source/JavaScriptCore/tests',
35
    'Source/JavaScriptCore/wtf/android',
36
    'Source/JavaScriptCore/wtf/brew',
37
    'Source/JavaScriptCore/wtf/chromium',
38
    'Source/JavaScriptCore/wtf/haiku',
39
    'Source/JavaScriptCore/wtf/mac',
40
    'Source/JavaScriptCore/wtf/win',
41
    'Source/JavaScriptCore/wtf/wx',
42
    'Source/JavaScriptCore/qt',
43
    'Source/JavaScriptGlue',
44
    'LayoutTests',
45
    'Makefile',
46
    'Makefile.shared',
47
    'Websites',
48
    'PerformanceTests',
49
    'Source/DerivedSources.pro',
50
    'Source/WebCore/Android.derived.jscbindings.mk',
51
    'Source/WebCore/Android.derived.mk',
52
    'Source/WebCore/Android.derived.v8bindings.mk',
53
    'Source/WebCore/Android.jscbindings.mk',
54
    'Source/WebCore/Android.mk',
55
    'Source/WebCore/Android.v8bindings.mk',
56
    'Source/WebCore/Configurations',
57
    'Source/WebCore/DerivedSources.cpp',
58
    'Source/WebCore/DerivedSources.make',
59
    'Source/WebCore/DerivedSources.pro',
60
    'Source/WebCore/English.lproj',
61
    'Source/WebCore/GNUmakefile.am',
62
    'Source/WebCore/Makefile',
63
    'Source/WebCore/WebCore.ContextMenus.exp',
64
    'Source/WebCore/WebCore.DragSupport.exp',
65
    'Source/WebCore/WebCore.Inspector.exp',
66
    'Source/WebCore/WebCore.OrientationEvents.exp',
67
    'Source/WebCore/WebCore.PluginHostProcess.exp',
68
    'Source/WebCore/WebCore.base.exp',
69
    'Source/WebCore/WebCore.gyp',
70
    'Source/WebCore/WebCore.vcproj',
71
    'Source/WebCore/WebCore.xcodeproj',
72
    'Source/WebCore/WebCoreSources.bkl',
73
    'Source/WebCore/accessibility/chromium',
74
    'Source/WebCore/accessibility/gtk',
75
    'Source/WebCore/accessibility/mac',
76
    'Source/WebCore/accessibility/win',
77
    'Source/WebCore/accessibility/wx',
78
    'Source/WebCore/bindings/objc',
79
    'Source/WebCore/bindings/v8',
80
    'Source/WebCore/bridge/jni/v8',
81
    'Source/WebCore/bridge/objc',
82
    'Source/WebCore/bridge/testbindings.pro',
83
    'Source/WebCore/editing/android',
84
    'Source/WebCore/editing/chromium',
85
    'Source/WebCore/editing/gtk',
86
    'Source/WebCore/editing/haiku',
87
    'Source/WebCore/editing/mac',
88
    'Source/WebCore/editing/wx',
89
    'Source/WebCore/history/android',
90
    'Source/WebCore/history/cf',
91
    'Source/WebCore/history/mac',
92
    'Source/WebCore/icu',
93
    'Source/WebCore/loader/archive/cf',
94
    'Source/WebCore/loader/cf',
95
    'Source/WebCore/loader/icon/wince',
96
    'Source/WebCore/loader/mac',
97
    'Source/WebCore/loader/win',
98
    'Source/WebCore/manual-tests',
99
    'Source/WebCore/page/android',
100
    'Source/WebCore/page/brew',
101
    'Source/WebCore/page/chromium',
102
    'Source/WebCore/page/efl',
103
    'Source/WebCore/page/gtk',
104
    'Source/WebCore/page/haiku',
105
    'Source/WebCore/page/mac',
106
    'Source/WebCore/page/wince',
107
    'Source/WebCore/page/wx',
108
    'Source/WebCore/platform/android',
109
    'Source/WebCore/platform/brew',
110
    'Source/WebCore/platform/chromium',
111
    'Source/WebCore/platform/efl',
112
    'Source/WebCore/platform/graphics/brew',
113
    'Source/WebCore/platform/graphics/cairo',
114
    'Source/WebCore/platform/graphics/chromium',
115
    'Source/WebCore/platform/graphics/efl',
116
    'Source/WebCore/platform/graphics/gtk',
117
    'Source/WebCore/platform/graphics/haiku',
118
    'Source/WebCore/platform/graphics/skia',
119
    'Source/WebCore/platform/graphics/wince',
120
    'Source/WebCore/platform/graphics/wx',
121
    'Source/WebCore/platform/gtk',
122
    'Source/WebCore/platform/haiku',
123
    'Source/WebCore/platform/image-decoders/bmp',
124
    'Source/WebCore/platform/image-decoders/gif',
125
    'Source/WebCore/platform/image-decoders/haiku',
126
    'Source/WebCore/platform/image-decoders/ico',
127
    'Source/WebCore/platform/image-decoders/jpeg',
128
    'Source/WebCore/platform/image-decoders/png',
129
    'Source/WebCore/platform/image-decoders/skia',
130
    'Source/WebCore/platform/image-decoders/wx',
131
    'Source/WebCore/platform/image-decoders/xbm',
132
    'Source/WebCore/platform/image-decoders/zlib',
133
    'Source/WebCore/platform/image-encoders/skia',
134
    'Source/WebCore/platform/iphone',
135
    'Source/WebCore/platform/network/android',
136
    'Source/WebCore/platform/network/brew',
137
    'Source/WebCore/platform/network/cf',
138
    'Source/WebCore/platform/network/chromium',
139
    'Source/WebCore/platform/network/curl',
140
    'Source/WebCore/platform/network/mac',
141
    'Source/WebCore/platform/network/soup',
142
    'Source/WebCore/platform/network/win',
143
    'Source/WebCore/platform/sql/chromium',
144
    'Source/WebCore/platform/text/android',
145
    'Source/WebCore/platform/text/brew',
146
    'Source/WebCore/platform/text/chromium',
147
    'Source/WebCore/platform/text/efl',
148
    'Source/WebCore/platform/text/gtk',
149
    'Source/WebCore/platform/text/haiku',
150
    'Source/WebCore/platform/text/wx',
151
    'Source/WebCore/platform/wince',
152
    'Source/WebCore/platform/wx',
153
    'Source/WebCore/plugins/chromium',
154
    'Source/WebCore/plugins/gtk',
155
    'Source/WebCore/plugins/wx',
156
    'Source/WebCore/rendering/RenderThemeMac.mm',
157
    'Source/WebCore/storage/chromium',
158
    'Source/WebCore/storage/wince',
159
    'Source/WebCore/webcore-base.bkl',
160
    'Source/WebCore/webcore-wx.bkl',
161
    'Source/WebCore/wscript',
162
    'Source/WebKit/qt/Api/DerivedSources.pro',
163
    'Source/WebKit/English.lproj',
164
    'Source/WebKit/Makefile',
165
    'Source/WebKit/StringsNotToBeLocalized.txt',
166
    'Source/WebKit/WebKit.xcodeproj',
167
    'Source/WebKit/cf',
168
    'Source/WebKit/chromium',
169
    'Source/WebKit/efl',
170
    'Source/WebKit/gtk',
171
    'Source/WebKit/haiku',
172
    'Source/WebKit/scripts',
173
    'Source/WebKit/win',
174
    'Source/WebKit/wx',
175
    'Source/WebKitExamplePlugins',
176
    'Source/WebKitSite',
177
    'autogen.sh',
178
    'configure.ac',
179
    )
180
181
# Any file path under the directory that matches one of the exception regex pattern won't be excluded 
182
excludedDirectoriesWithExceptions = (
183
    (   'Source/WebCore/platform/win',
184
        (   re.compile('BitmapInfo.cpp'),
185
            re.compile('BitmapInfo.h'),
186
            re.compile('SystemInfo.h'),
187
            re.compile('SystemInfo.cpp'),
188
            re.compile('SystemTimeWin.cpp'),
189
            re.compile('WebCoreInstanceHandle.cpp'),
190
            re.compile('WebCoreInstanceHandle.h'), ) ),
191
    (   'Source/WebKit/mac',
192
        (   re.compile('Configurations/Version.xcconfig'), ) ),
193
    (   'Tools',
194
        (   re.compile('Tools/QtLauncher'),
195
            re.compile('Tools/QtTestBrowser'),
196
        ) ),
197
    )
198
199
def system(command):
200
    retval = os.system(command)
201
    if retval != 0:
202
        raise Exception('Command failed with return code [{0}]'.format(retval))
203
204
def requireCleanWorkTree():
205
    # test if working tree is dirty
206
    print('--- Checking the working tree')
207
    if not (os.system('git rev-parse --verify HEAD > ' + os.devnull) == 0
208
            and os.system('git update-index --refresh') == 0
209
            and os.system('git diff-files --quiet') == 0
210
            and os.system('git diff-index --cached --quiet HEAD') == 0):
211
        print('Aborting, Working tree is dirty')
212
        sys.exit(-1)
213
214
def verifySqlite():
215
    # Make sure sqlite didn't get disabled on windows
216
    # Else database and worker support will be disabled for sources generation
217
    # but enabled for compilation in Qt.
218
    proFileName = 'temp-make-package-testsqlite.pro'
219
    MakefileName = 'Makefile.test'
220
    testPro = open(proFileName, 'w')
221
    testPro.write('''
222
        CONFIG -= debug_and_release
223
        defineTest(addExtraCompiler) { 
224
            return(true)
225
        }
226
        include(Source/WebCore/WebCore.pri)
227
        contains(DEFINES, ENABLE_SQLITE=0) {
228
            error(Could not find sqlite in directory [$${SQLITE3SRCDIR}]. You might have to set the SQLITE3SRCDIR environment variable to (Qt Source)/src/3rdparty/sqlite)
229
        }
230
        ''')
231
    testPro.close()
232
    try:
233
        system('qmake -o {0} {1}'.format(MakefileName, proFileName))
234
    finally:
235
        os.remove(proFileName)
236
        os.remove(MakefileName)
237
238
def extract(command):
239
    return Popen(command, stdout=PIPE, shell=True).communicate()[0].rstrip()
240
241
def addQuotes(stringList):
242
    return map(lambda s: '"'+s+'"', stringList)
243
244
make = "make"
245
# Not perfect, but for the time being we assume windows == nmake
246
# Perhaps it would be better to use the qmake spec
247
if platform.system() == "Windows":
248
    make = "nmake"
249
250
# Setup the option parser
251
parser = OptionParser(usage = 'Usage: %prog [options] [archive file name]')
252
parser.add_option('-p', '--submitToPulse', dest='submitToPulse', action='store_true', default=False, help='Submit result to pulse (please make sure you have a remote called [package-repository] pointing to a repository monitored by pulse)')
253
options, args = parser.parse_args()
254
if len(args) > 0:
255
    archiveName = args[0]
256
else:
257
    branch = extract('git symbolic-ref HEAD 2>/dev/null | sed -e "s,refs/heads/,,"')
258
    archiveName = '{0}-source.tar.gz'.format(branch)
259
260
261
requireCleanWorkTree()
262
verifySqlite()
263
264
print('--- Generating derived sources')
265
system('qmake -o Makefile.DerivedSources -r QT_CONFIG+=phonon CONFIG+=standalone_package Source/DerivedSources.pro')
266
system('%s -f Source/Makefile.DerivedSources generated_files' % make)
267
system('perl -pi -e "s,%s,,g" Source/*/generated/*.cpp Source/*/generated/*.h' % os.getcwd())
268
269
# add a tag file containing the packaged commit's sha1
270
system('git rev-parse HEAD > .tag')
271
272
# set up a temporary index
273
indexFile = ".git/package-index"
274
os.environ["GIT_INDEX_FILE"] = indexFile
275
system('git read-tree HEAD')
276
277
print('--- Adding generated files to the git index')
278
system('git add Source/WebCore/generated Source/JavaScriptCore/generated include')
279
system('git add .tag')
280
281
print('--- Removing unneeded files from the index')
282
# Remove paths in excludedFilesAndDirectories
283
system('git rm --quiet --ignore-unmatch -r --cached ' + ' '.join(addQuotes(excludedFilesAndDirectories)))
284
# Remove paths in excludedDirectoriesWithExceptions
285
for (directoryPath, exceptionPatterns) in excludedDirectoriesWithExceptions:
286
    # Extract the list of files to remove from the archive
287
    excludedPaths = extract("git ls-files --cached " + directoryPath).splitlines()
288
    # Keep in this list only paths that all exception patterns matching returns False
289
    excludedPaths = [path for path in excludedPaths if not any(map(lambda pattern: pattern.search(path), exceptionPatterns))]
290
    # Delete files in batch of 100 to prevent a "The command line is too long" error
291
    BatchSize = 100
292
    while excludedPaths:
293
        system('git rm --quiet --ignore-unmatch -r --cached ' + ' '.join(addQuotes(excludedPaths[:BatchSize])))
294
        del excludedPaths[:BatchSize]
295
296
297
tree = extract('git write-tree');
298
299
if options.submitToPulse:
300
    webkitCommit=extract('git rev-parse HEAD')
301
    packageBranch = '{0}-package'.format(branch)
302
    parentCommit = ''
303
    if os.system('git rev-parse -q --verify package-repository/' + packageBranch) == 0:
304
        parentCommit = '-p ' + extract('git rev-parse package-repository/' + packageBranch)
305
    packageCommit = extract('echo Created webkit package for {0} | git commit-tree {1} {2}'.format(webkitCommit, tree, parentCommit))
306
307
    print('Pushing...')
308
    if os.system('git push package-repository {0}:refs/heads/{1}'.format(packageCommit, packageBranch)) != 0:
309
        sys.exit(1)
310
else:
311
    print('--- Creating the archive...')
312
    pathPrefix = ''
313
    pathPrefixMatch = re.match('(.+)\.tar\.\w+$', archiveName)
314
    if not pathPrefixMatch:
315
        pathPrefixMatch = re.match('(.+)\.\w+$', archiveName)
316
    if pathPrefixMatch:
317
        pathPrefix = pathPrefixMatch.group(1)
318
    system('git archive --prefix={0}/ {1} | gzip -9 > {2}'.format(pathPrefix, tree, archiveName))
319
    print('=== Archive [{0}] sucessfully created'.format(archiveName))
320
321
print('--- Resetting the git index and cleaning up...')
322
os.remove('.tag')
323
os.remove('Source/Makefile.DerivedSources')
324
os.remove('JavaScriptCore/Makefile.DerivedSources')
325
os.remove('WebCore/Makefile.DerivedSources')
326
os.remove('WebKit/qt/Api/Makefile.DerivedSources')
327
shutil.rmtree('Source/JavaScriptCore/generated', ignore_errors=True)
328
shutil.rmtree('Source/WebCore/generated', ignore_errors=True)
329
shutil.rmtree('include', ignore_errors=True)
330
331
# Remove temporary index
332
os.remove(indexFile)
333
334
print('--- Done')