mirror of
https://github.com/zotero/zotero.git
synced 2026-10-10 03:28:10 +00:00
Compare commits
4701 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44fe83d98b | ||
|
|
d18d2d1701 | ||
|
|
b0db83d9dc | ||
|
|
a69b55ea96 | ||
|
|
5336c3562b | ||
|
|
734e2e6840 | ||
|
|
b551fb6705 | ||
|
|
8cf0203bb9 | ||
|
|
d0a728bb78 | ||
|
|
c280964d46 | ||
|
|
338ce732bd | ||
|
|
9cbba8c4d2 | ||
|
|
fb4bed7522 | ||
|
|
1e2cc6820a | ||
|
|
09c3c8cd3d | ||
|
|
9071805bdc | ||
|
|
cdf10bf62b | ||
|
|
a6e814417f | ||
|
|
d81484d2e8 | ||
|
|
9b769d3987 | ||
|
|
364181f4e7 | ||
|
|
ba2d6ecee4 | ||
|
|
15f6a81181 | ||
|
|
d8382c5c11 | ||
|
|
ae50d52589 | ||
|
|
4118f47bc3 | ||
|
|
9e234ee64f | ||
|
|
0d0bbc8925 | ||
|
|
d7751b93d8 | ||
|
|
ebdc1287ac | ||
|
|
34000fb29f | ||
|
|
f8ef8e2119 | ||
|
|
9ea080f896 | ||
|
|
df78b51dab | ||
|
|
a64e367160 | ||
|
|
196bec4e7d | ||
|
|
c694e88ec3 | ||
|
|
fcbc6ec1d5 | ||
|
|
e863643a43 | ||
|
|
8c3b967bf9 | ||
|
|
53ded5eb44 | ||
|
|
cc951f9916 | ||
|
|
5237f27060 | ||
|
|
3ff64b658d | ||
|
|
ed8ca1bfce | ||
|
|
22a26bb483 | ||
|
|
4e3b208e4a | ||
|
|
5245b6cf5e | ||
|
|
e061e565b7 | ||
|
|
8e7639d73d | ||
|
|
7c7560bad1 | ||
|
|
b6f0f6c0ba | ||
|
|
213b0d7d76 | ||
|
|
acc4fd5ad2 | ||
|
|
bdb656ad5c | ||
|
|
c30163ed90 | ||
|
|
1d4b8bc89a | ||
|
|
3c959e1012 | ||
|
|
ab34e9031a | ||
|
|
913aff342d | ||
|
|
cc700a1e11 | ||
|
|
e03920890a | ||
|
|
26988646bf | ||
|
|
bdaecbb5cc | ||
|
|
a43c1d5ad5 | ||
|
|
fc17dcd24a | ||
|
|
1086d80cec | ||
|
|
92dfac8c64 | ||
|
|
e88b7ee10f | ||
|
|
53bcd30a5f | ||
|
|
22a1b33a42 | ||
|
|
0e46a5356b | ||
|
|
d0a32a3b4f | ||
|
|
b3b6e7f33d | ||
|
|
4d94810def | ||
|
|
54cea6cc37 | ||
|
|
f3810befde | ||
|
|
e3da52bebc | ||
|
|
9086156a91 | ||
|
|
e56fad828d | ||
|
|
0e00c1ce51 | ||
|
|
5697ee0af7 | ||
|
|
fac6c8ebf6 | ||
|
|
08ed64f17f | ||
|
|
9e28eb0d39 | ||
|
|
661843b03f | ||
|
|
a0ce7b3256 | ||
|
|
4a8a88dd41 | ||
|
|
b4f1deb998 | ||
|
|
984a72a3d9 | ||
|
|
e679473db1 | ||
|
|
30425e024d | ||
|
|
c19177a469 | ||
|
|
ace9fa0227 | ||
|
|
57c8c81872 | ||
|
|
892898040b | ||
|
|
d276ec19c5 | ||
|
|
bccaf46ff2 | ||
|
|
fa94212496 | ||
|
|
c8b841df8a | ||
|
|
41353f01cf | ||
|
|
dffcbb553f | ||
|
|
eb33fa5835 | ||
|
|
07745b634b | ||
|
|
c098f5e84d | ||
|
|
1d1d32a211 | ||
|
|
c2052cfff1 | ||
|
|
61174e2158 | ||
|
|
e29d8f151e | ||
|
|
8e4ec83abd | ||
|
|
3b93d33b35 | ||
|
|
0c9ba2d05c | ||
|
|
b6efbe880e | ||
|
|
ff93139cce | ||
|
|
4a250cd20f | ||
|
|
d153397151 | ||
|
|
5d20c692e8 | ||
|
|
a1ea7037c2 | ||
|
|
6d8198bbfa | ||
|
|
56eb77b704 | ||
|
|
e69ee69218 | ||
|
|
baa47e3bb9 | ||
|
|
753dbf557a | ||
|
|
786cdea884 | ||
|
|
f2a42bec15 | ||
|
|
070ae8b615 | ||
|
|
e8055dfdf2 | ||
|
|
9e45191b22 | ||
|
|
7243648ed7 | ||
|
|
85e1cbc75c | ||
|
|
ad98e84d24 | ||
|
|
77a3a8815e | ||
|
|
766cb079a0 | ||
|
|
0ee3e4052e | ||
|
|
0746c665a9 | ||
|
|
73f4273e2d | ||
|
|
04796dff22 | ||
|
|
5f978c71ca | ||
|
|
c220866d9a | ||
|
|
6ce33bcd81 | ||
|
|
f5a2985a34 | ||
|
|
cdb13af13b | ||
|
|
32640e2019 | ||
|
|
22b3daf845 | ||
|
|
aa49b48915 | ||
|
|
c7cffdd26c | ||
|
|
da705c36ec | ||
|
|
b930ddb863 | ||
|
|
847dffbf18 | ||
|
|
96972db8c6 | ||
|
|
dac1ad489f | ||
|
|
ed8049dffc | ||
|
|
e1759daa00 | ||
|
|
4e532a17a2 | ||
|
|
ad1bec62f2 | ||
|
|
18f6fa50d5 | ||
|
|
db1216d3e2 | ||
|
|
b6837a3a57 | ||
|
|
bba85a3939 | ||
|
|
5757396197 | ||
|
|
5a6c9245f0 | ||
|
|
844bd87824 | ||
|
|
e0f9710c46 | ||
|
|
b8fdee865a | ||
|
|
29a4d9d140 | ||
|
|
472a0bf856 | ||
|
|
68bec97114 | ||
|
|
4a6a8220ff | ||
|
|
f53d4b5eca | ||
|
|
1d6158dfd8 | ||
|
|
5df473cf96 | ||
|
|
e7767c5bfa | ||
|
|
8d01216e5c | ||
|
|
8ac1273acb | ||
|
|
399a63ade2 | ||
|
|
d9d52de516 | ||
|
|
a9e765e37f | ||
|
|
fdec96911c | ||
|
|
ad7159834c | ||
|
|
e5508e870c | ||
|
|
896582ab32 | ||
|
|
c1cdd038a2 | ||
|
|
fe35127f50 | ||
|
|
b8cbdc8c95 | ||
|
|
04321fc627 | ||
|
|
3630b904d7 | ||
|
|
646fbfae65 | ||
|
|
46603ca4eb | ||
|
|
1d279fba5b | ||
|
|
45867cea54 | ||
|
|
c87328ada9 | ||
|
|
8f6dc583b8 | ||
|
|
3af8cea1af | ||
|
|
09249bfb73 | ||
|
|
8fb2870f93 | ||
|
|
9da57a9fe3 | ||
|
|
b83342d8e0 | ||
|
|
2f90893e59 | ||
|
|
8052b8f9e2 | ||
|
|
aaeb9c6c9a | ||
|
|
adc5648d29 | ||
|
|
300305a9fb | ||
|
|
97de8858fe | ||
|
|
770f44568c | ||
|
|
a2a419c6da | ||
|
|
0ae2e42ca2 | ||
|
|
1dffe21de0 | ||
|
|
d5aacafe3f | ||
|
|
ea30bbd2af | ||
|
|
72115c3cb4 | ||
|
|
6f3e4b5499 | ||
|
|
e4ee85296c | ||
|
|
b5ceb6fa65 | ||
|
|
35a70117b0 | ||
|
|
030cd3dc5e | ||
|
|
503bb03aec | ||
|
|
3430ad241b | ||
|
|
00cad2ced0 | ||
|
|
2bd9342188 | ||
|
|
d43dc2fa37 | ||
|
|
78d21617af | ||
|
|
7793b469c9 | ||
|
|
8110ab4eea | ||
|
|
45e38322e1 | ||
|
|
2eba3398e9 | ||
|
|
01b7d0667c | ||
|
|
a32dd2b959 | ||
|
|
6fbe5e4135 | ||
|
|
567cc2d43a | ||
|
|
f245f5c2b2 | ||
|
|
bcd8ad20ec | ||
|
|
eac3838f00 | ||
|
|
bca6537e6d | ||
|
|
5ea6243384 | ||
|
|
3bb3b4f2c9 | ||
|
|
1c005c7e21 | ||
|
|
14b43c9559 | ||
|
|
b7232f130f | ||
|
|
c192127ab1 | ||
|
|
d701c43862 | ||
|
|
06848ce17f | ||
|
|
408179ad09 | ||
|
|
242bbccda5 | ||
|
|
fdd3434349 | ||
|
|
c9d5aa3c8e | ||
|
|
d54327a045 | ||
|
|
b5ea455c1f | ||
|
|
9c03a93e00 | ||
|
|
a7cae87be8 | ||
|
|
4ec5ba9c27 | ||
|
|
7abcf23ef7 | ||
|
|
8bebaf0ead | ||
|
|
80658e928e | ||
|
|
4388f6da20 | ||
|
|
9ed00c843d | ||
|
|
08880f7a0e | ||
|
|
c39f16891f | ||
|
|
efcfaec5d4 | ||
|
|
dc6d55a137 | ||
|
|
783da0e66e | ||
|
|
1d97f6448e | ||
|
|
5d1a2cba32 | ||
|
|
e45871fa9d | ||
|
|
c92c75eb36 | ||
|
|
3da869b2e6 | ||
|
|
85a33e1586 | ||
|
|
3bf74a3e46 | ||
|
|
ae98136ec8 | ||
|
|
2fb8d69a93 | ||
|
|
681c48f1c2 | ||
|
|
caeffa9f41 | ||
|
|
b66519cb4c | ||
|
|
db5e7edb49 | ||
|
|
7925b4e9ac | ||
|
|
93d66e3999 | ||
|
|
938c414e0c | ||
|
|
8526a022ec | ||
|
|
75b78b410b | ||
|
|
a37a9e782a | ||
|
|
77f2432103 | ||
|
|
9dd17a212e | ||
|
|
12114f6a86 | ||
|
|
ce20a5f228 | ||
|
|
91d7e73d26 | ||
|
|
566115dc7c | ||
|
|
512a2444d8 | ||
|
|
9eea7d9a0c | ||
|
|
3a54a5ecb1 | ||
|
|
0b32e93cb1 | ||
|
|
a81af0c268 | ||
|
|
ea4b301f73 | ||
|
|
4f825ad50c | ||
|
|
6fb30346e6 | ||
|
|
a4b39b91f3 | ||
|
|
146520aed5 | ||
|
|
cddb19bf36 | ||
|
|
e81e72dccf | ||
|
|
40974e493d | ||
|
|
621c0fbb91 | ||
|
|
ee68452b05 | ||
|
|
5877952954 | ||
|
|
ccb592ba68 | ||
|
|
ddcdea3795 | ||
|
|
14c6167a4c | ||
|
|
5a785c4e0f | ||
|
|
ccbeab61e2 | ||
|
|
59c1801a10 | ||
|
|
0dc256166a | ||
|
|
8437de1a4f | ||
|
|
4a7c359ae2 | ||
|
|
f171e7b5d8 | ||
|
|
c233fcf5f0 | ||
|
|
30b5bf4bb9 | ||
|
|
d739fed03e | ||
|
|
bcfa43b7e9 | ||
|
|
0ce289a7fe | ||
|
|
228799774f | ||
|
|
f8f83cceac | ||
|
|
10b1dbb785 | ||
|
|
994d557e92 | ||
|
|
fb20a84ab7 | ||
|
|
a2c7e0c00e | ||
|
|
6c5d160895 | ||
|
|
d3b04e7748 | ||
|
|
404fb4c3ae | ||
|
|
d78cceac71 | ||
|
|
cae3ab6160 | ||
|
|
73c45f8ec9 | ||
|
|
ea2ee7391d | ||
|
|
02fb0e92ed | ||
|
|
3ec407d861 | ||
|
|
5ade25f5f5 | ||
|
|
7c2a1d127d | ||
|
|
e2536ba299 | ||
|
|
ae46954167 | ||
|
|
da88c63231 | ||
|
|
984c0a7f8c | ||
|
|
3bd8d641b8 | ||
|
|
d0f8d438b5 | ||
|
|
cf09a0547c | ||
|
|
c6595d6456 | ||
|
|
4f45db5009 | ||
|
|
933e207013 | ||
|
|
0ba89211ce | ||
|
|
bdea584a17 | ||
|
|
1a5e32a7b6 | ||
|
|
142f77b094 | ||
|
|
6e35bd1497 | ||
|
|
2c6185d8f1 | ||
|
|
89880e3284 | ||
|
|
5a8badae7b | ||
|
|
28867883a1 | ||
|
|
cdb9134537 | ||
|
|
7cdd74bd2b | ||
|
|
24fe50cfd5 | ||
|
|
c181aac7f6 | ||
|
|
582333397d | ||
|
|
5fe4c901ed | ||
|
|
8eb71a588d | ||
|
|
dea2fb8491 | ||
|
|
6225931f93 | ||
|
|
540735785d | ||
|
|
4188ef0ebc | ||
|
|
ccc7d0a5ad | ||
|
|
3a34c6a18f | ||
|
|
a6c3ad51ef | ||
|
|
1e0cf49a16 | ||
|
|
cc28fad6da | ||
|
|
d95d8f294d | ||
|
|
c43f028c96 | ||
|
|
8daed576ba | ||
|
|
2c62010c4c | ||
|
|
0a67f4967c | ||
|
|
64165eabf6 | ||
|
|
243ef0e28f | ||
|
|
606d8f19ba | ||
|
|
03a610e696 | ||
|
|
c3787495cc | ||
|
|
e1f19f34f5 | ||
|
|
1c9bf88888 | ||
|
|
39a1c56f6c | ||
|
|
d07dd66c21 | ||
|
|
3ae3bd41dc | ||
|
|
4314494455 | ||
|
|
f9e711a9b2 | ||
|
|
77a3cd82a9 | ||
|
|
49e284bab0 | ||
|
|
7d33215a37 | ||
|
|
dfd745c5d5 | ||
|
|
1fe9cad5f8 | ||
|
|
62a431f42b | ||
|
|
4c392c4764 | ||
|
|
bd25413213 | ||
|
|
094d5cc2b6 | ||
|
|
225e91c5e7 | ||
|
|
2b7f46227f | ||
|
|
55eceab3b3 | ||
|
|
e2db3c7966 | ||
|
|
cddf0ea237 | ||
|
|
057966000c | ||
|
|
e416ea2dfa | ||
|
|
2f364f2fab | ||
|
|
a48336350a | ||
|
|
af704dc119 | ||
|
|
26c30d8ecd | ||
|
|
95ee1c616c | ||
|
|
40b272c46b | ||
|
|
1d8cdb13c1 | ||
|
|
163c27ca79 | ||
|
|
d28bdd8d6e | ||
|
|
279e25c57e | ||
|
|
13bd8c9d8d | ||
|
|
7f30b0e47d | ||
|
|
f3328b02ee | ||
|
|
9cffc1c7c2 | ||
|
|
36d025f6a9 | ||
|
|
2d56936bfe | ||
|
|
2006cdac6d | ||
|
|
02b19d0cde | ||
|
|
340ba92513 | ||
|
|
6c7c661fb1 | ||
|
|
a1f36f750e | ||
|
|
fe340283c1 | ||
|
|
0e587176e8 | ||
|
|
d4507544af | ||
|
|
98308c65b9 | ||
|
|
f7e67f6643 | ||
|
|
cf7ee984ea | ||
|
|
3875f411e5 | ||
|
|
680452cc59 | ||
|
|
3544848e5f | ||
|
|
b56c153125 | ||
|
|
2717aafedd | ||
|
|
cb2110e1c1 | ||
|
|
2239dd20a4 | ||
|
|
60807d552c | ||
|
|
ccf6f18643 | ||
|
|
786b85bf2d | ||
|
|
0529c9a579 | ||
|
|
092295da22 | ||
|
|
8b5a77a75e | ||
|
|
1341b6d5cc | ||
|
|
cdc70d1280 | ||
|
|
5904f0e4bf | ||
|
|
d808988540 | ||
|
|
c01def2a85 | ||
|
|
9a4317daa7 | ||
|
|
8f96a6d191 | ||
|
|
aab912e4ee | ||
|
|
d7660f2f27 | ||
|
|
962e1334c8 | ||
|
|
40cb1cfa84 | ||
|
|
35317982f5 | ||
|
|
bdf79336f9 | ||
|
|
e71bd89e0d | ||
|
|
c92148c3ec | ||
|
|
8d7f5a39f9 | ||
|
|
ff094330f5 | ||
|
|
4a318617d6 | ||
|
|
6092b0335c | ||
|
|
35c8448582 | ||
|
|
e37a7d8f06 | ||
|
|
2e79bbe402 | ||
|
|
e38f8f78b0 | ||
|
|
90aa5d33a0 | ||
|
|
f4adb452ee | ||
|
|
08d875c7f7 | ||
|
|
6d1cd85211 | ||
|
|
39954dc437 | ||
|
|
20fd5fe3e2 | ||
|
|
618fcfa49d | ||
|
|
1c76195a7c | ||
|
|
94c78759ab | ||
|
|
b80fa996f5 | ||
|
|
15c2c95470 | ||
|
|
2ddb4e991b | ||
|
|
e23a453e5c | ||
|
|
4d38970ef0 | ||
|
|
e6f82dabfd | ||
|
|
cf876033f6 | ||
|
|
f03004bb9e | ||
|
|
80ca898a74 | ||
|
|
7eef2fb3f0 | ||
|
|
22055d92b7 | ||
|
|
39d7835472 | ||
|
|
e41c788c4c | ||
|
|
580e423d4c | ||
|
|
27560d9476 | ||
|
|
81b3c13b13 | ||
|
|
a3180d87c5 | ||
|
|
8ed617ae53 | ||
|
|
97aa4f93ea | ||
|
|
3d334dc244 | ||
|
|
18d332ec5e | ||
|
|
702094f703 | ||
|
|
40851e1f58 | ||
|
|
2689997c50 | ||
|
|
00527332c4 | ||
|
|
d2f1c56250 | ||
|
|
cd29a818b0 | ||
|
|
0f2d3e103d | ||
|
|
40f949ba94 | ||
|
|
c72d80f22b | ||
|
|
cd39445b94 | ||
|
|
632f11db74 | ||
|
|
55434d14a1 | ||
|
|
98d82d2909 | ||
|
|
982c00aaf6 | ||
|
|
06e16c297c | ||
|
|
de1bf1cec1 | ||
|
|
4e3baf09a0 | ||
|
|
fde4086e08 | ||
|
|
3e7030a642 | ||
|
|
fa3e0f683f | ||
|
|
dcf5010415 | ||
|
|
31d9e89165 | ||
|
|
d0507e02c8 | ||
|
|
31b3ead557 | ||
|
|
615ba3c178 | ||
|
|
e029354a35 | ||
|
|
87901c1c21 | ||
|
|
8cf5c9b3d1 | ||
|
|
c838e9b29e | ||
|
|
8277277948 | ||
|
|
786960079b | ||
|
|
70c4cadab1 | ||
|
|
bf8c6f2027 | ||
|
|
cfd5596814 | ||
|
|
a692ca3493 | ||
|
|
9ca79a2cb1 | ||
|
|
d2631cc614 | ||
|
|
ad4caa8688 | ||
|
|
37bf9d0965 | ||
|
|
f81e7cb5da | ||
|
|
8f44172342 | ||
|
|
b7437faf55 | ||
|
|
c2a9ea2687 | ||
|
|
5c232d65c0 | ||
|
|
596882980d | ||
|
|
714d4416f8 | ||
|
|
ba7e036582 | ||
|
|
431e1dabde | ||
|
|
789c83249c | ||
|
|
504447de41 | ||
|
|
ddf2419e78 | ||
|
|
d66682b04e | ||
|
|
fda72a3434 | ||
|
|
575dc5351c | ||
|
|
4b2c0518f1 | ||
|
|
99228a6c76 | ||
|
|
ede90ac04a | ||
|
|
fc37e524fe | ||
|
|
8d59331d43 | ||
|
|
3c53118f2c | ||
|
|
ef7896ab5f | ||
|
|
178f162449 | ||
|
|
a7d001fc1d | ||
|
|
36e25d171a | ||
|
|
a57cb6276f | ||
|
|
373accce3b | ||
|
|
66dc97de33 | ||
|
|
03d94060b4 | ||
|
|
13cb8d99b6 | ||
|
|
82b31574a8 | ||
|
|
bc2ede0459 | ||
|
|
2e19017d0e | ||
|
|
2f38926da5 | ||
|
|
5dc817db44 | ||
|
|
fd812070b6 | ||
|
|
e13e85b2e5 | ||
|
|
7ca8242a3e | ||
|
|
a43d6a5d37 | ||
|
|
1ff2f640eb | ||
|
|
462357e49e | ||
|
|
777d01b5c2 | ||
|
|
5ca1fbb167 | ||
|
|
6b42f9f9c0 | ||
|
|
d7920e320b | ||
|
|
f0474fa250 | ||
|
|
df6037ce0a | ||
|
|
24e16c0aad | ||
|
|
2d14f33de2 | ||
|
|
de69835419 | ||
|
|
0b15b794e6 | ||
|
|
e7ed0b2881 | ||
|
|
a487dd9eef | ||
|
|
9abd13fd22 | ||
|
|
e1cd83214f | ||
|
|
fa9a54b773 | ||
|
|
a835136d3b | ||
|
|
89ee4c21c0 | ||
|
|
26816b03e2 | ||
|
|
07906931c1 | ||
|
|
c52a6151dc | ||
|
|
ce424c6b67 | ||
|
|
cc76207a23 | ||
|
|
32e43cb8f1 | ||
|
|
00ece3db68 | ||
|
|
0fe31b0f04 | ||
|
|
45596e70e9 | ||
|
|
11c75ae6e5 | ||
|
|
c2c66795d2 | ||
|
|
55672ba933 | ||
|
|
488fd29978 | ||
|
|
d2d4451165 | ||
|
|
a9fe8e3b62 | ||
|
|
acfb7c7915 | ||
|
|
7334080693 | ||
|
|
c89abbc5be | ||
|
|
676d609d0d | ||
|
|
ad4bb17db9 | ||
|
|
683ecf1620 | ||
|
|
56ef61e45b | ||
|
|
f20eb5b566 | ||
|
|
62815bdd00 | ||
|
|
1ed1fab55b | ||
|
|
16b63a97dd | ||
|
|
b27c4cb023 | ||
|
|
e22e2cd9dd | ||
|
|
3e04f5e3e7 | ||
|
|
a0198e2571 | ||
|
|
e96d65f0ed | ||
|
|
1a89239a13 | ||
|
|
a1baa68006 | ||
|
|
f82efc766d | ||
|
|
ea230faa26 | ||
|
|
c3d8058794 | ||
|
|
117fa1dddb | ||
|
|
4b14ca9af4 | ||
|
|
91e82566ff | ||
|
|
70047b6fd6 | ||
|
|
5671a724e8 | ||
|
|
a3aa2bb5c7 | ||
|
|
3f0de027a2 | ||
|
|
4398a2bcee | ||
|
|
67288047f3 | ||
|
|
b11d776b36 | ||
|
|
92c876e47d | ||
|
|
d5ee350081 | ||
|
|
5a347f4be5 | ||
|
|
a602d21258 | ||
|
|
7f9fdc0786 | ||
|
|
2d88a3f181 | ||
|
|
0ff3ec6a1b | ||
|
|
c2ce0af87a | ||
|
|
92db62df0a | ||
|
|
862573eabc | ||
|
|
41b5442952 | ||
|
|
c6a95fd5b7 | ||
|
|
842115ff7e | ||
|
|
8effdacf65 | ||
|
|
d2a01d02f8 | ||
|
|
6f5f221db0 | ||
|
|
df18ac4e1f | ||
|
|
0e7ed13a43 | ||
|
|
f3ecf285b3 | ||
|
|
293cd25fb6 | ||
|
|
5f942684b6 | ||
|
|
2ad4618efb | ||
|
|
fb8389d654 | ||
|
|
391e8497a6 | ||
|
|
1267440187 | ||
|
|
16380e4a19 | ||
|
|
6140088b0c | ||
|
|
1d437d88f0 | ||
|
|
8a0a798672 | ||
|
|
0e8b195c5a | ||
|
|
8167c903f3 | ||
|
|
322b764091 | ||
|
|
5ac56ae717 | ||
|
|
2522be0c17 | ||
|
|
a3909af5ab | ||
|
|
6998235a31 | ||
|
|
81591eb890 | ||
|
|
6bec3c817e | ||
|
|
587d5cda7e | ||
|
|
351860273f | ||
|
|
5823247df9 | ||
|
|
d21a5d9cad | ||
|
|
763330d1f4 | ||
|
|
6fa5c4b3e3 | ||
|
|
fd7cc84f6b | ||
|
|
5bceea7b7b | ||
|
|
46ba21fe75 | ||
|
|
8af91b0147 | ||
|
|
e629a3c456 | ||
|
|
6e5738de0f | ||
|
|
518056f9e7 | ||
|
|
ba3c3a506f | ||
|
|
e28c97dc56 | ||
|
|
7b17187a1a | ||
|
|
eb3a136ccd | ||
|
|
0ade1b9ed5 | ||
|
|
98d911f6b1 | ||
|
|
883747e372 | ||
|
|
35713fefd0 | ||
|
|
3ebd26acc0 | ||
|
|
5dc9705294 | ||
|
|
cf7fcd751f | ||
|
|
1d31ed2508 | ||
|
|
1502214b5d | ||
|
|
1f702fc5dc | ||
|
|
c9f893a5a2 | ||
|
|
376fba55b6 | ||
|
|
8401b83cb6 | ||
|
|
1fad46f983 | ||
|
|
5b5b70b499 | ||
|
|
489a46564f | ||
|
|
f0af0bec9d | ||
|
|
07d99d891f | ||
|
|
aaed7ddfc0 | ||
|
|
288fa8e401 | ||
|
|
085a6fa5e0 | ||
|
|
d20cac39c9 | ||
|
|
34039991f8 | ||
|
|
0ce5cd5bac | ||
|
|
08c75006f3 | ||
|
|
290d44480e | ||
|
|
43f422a989 | ||
|
|
a9342cc242 | ||
|
|
426d681b65 | ||
|
|
fb4ac78291 | ||
|
|
fa476245fe | ||
|
|
518e7d22a0 | ||
|
|
3328557d00 | ||
|
|
259abb15f5 | ||
|
|
d3509ae259 | ||
|
|
be1373dd3a | ||
|
|
fcce3bb21d | ||
|
|
f130e3b3e5 | ||
|
|
25a96c35ca | ||
|
|
d2d66d322c | ||
|
|
db70d92b4c | ||
|
|
2c234c4c0a | ||
|
|
2f6825027a | ||
|
|
f9a10e1874 | ||
|
|
f6811bd1a8 | ||
|
|
e60bf91e31 | ||
|
|
81f80a62e3 | ||
|
|
12942ec717 | ||
|
|
ce11d5295c | ||
|
|
b80bcea184 | ||
|
|
0abf2b455f | ||
|
|
20735c425f | ||
|
|
76c7a613a9 | ||
|
|
c0c9437da8 | ||
|
|
3a11ac146d | ||
|
|
c9d108ba5e | ||
|
|
810626e458 | ||
|
|
c4df6b2151 | ||
|
|
3d09df1419 | ||
|
|
9d5f46587e | ||
|
|
7c61d282ee | ||
|
|
a6a919234a | ||
|
|
f07d7077b5 | ||
|
|
4e60a9fbca | ||
|
|
db124860ed | ||
|
|
f5dd72dfb5 | ||
|
|
1cd12791f6 | ||
|
|
520a12ebe0 | ||
|
|
b6ffa16893 | ||
|
|
a7c76e3202 | ||
|
|
041fa48664 | ||
|
|
13f1606dc7 | ||
|
|
3f90e60cd0 | ||
|
|
e63ed25b3f | ||
|
|
8adee749e0 | ||
|
|
b0b2378866 | ||
|
|
5905638907 | ||
|
|
578361913a | ||
|
|
da4978354b | ||
|
|
003bdab3ff | ||
|
|
f0d3347b26 | ||
|
|
f21e1b2d32 | ||
|
|
2739b29709 | ||
|
|
3386490a03 | ||
|
|
2aaf0c213f | ||
|
|
0d16d81a3c | ||
|
|
fe74fce120 | ||
|
|
7fe4e50c4c | ||
|
|
c9ab1ec62c | ||
|
|
ae397ca37c | ||
|
|
c377c4c7ec | ||
|
|
427fb1d4d9 | ||
|
|
94dbdd5981 | ||
|
|
fcd887a89d | ||
|
|
9640875fcf | ||
|
|
c35d7f21e9 | ||
|
|
8a1bdacf7d | ||
|
|
5cb83c69c6 | ||
|
|
fe3021701e | ||
|
|
06794ce278 | ||
|
|
fa30baf523 | ||
|
|
c7014b97c7 | ||
|
|
752b0f7008 | ||
|
|
d966eee6a7 | ||
|
|
2f7055e15d | ||
|
|
bd8d56e384 | ||
|
|
bbb39719f0 | ||
|
|
eecdd66098 | ||
|
|
5e82c888b6 | ||
|
|
0f565ecfef | ||
|
|
7b0f5d8f32 | ||
|
|
2f064a5604 | ||
|
|
818ce564bb | ||
|
|
331a83d2e8 | ||
|
|
56cd4713f1 | ||
|
|
089701eca8 | ||
|
|
e7d1772470 | ||
|
|
1347023b39 | ||
|
|
62894d56e5 | ||
|
|
a0758e016a | ||
|
|
0c97b6f74c | ||
|
|
f3c0e4fdc2 | ||
|
|
2c2b6fe171 | ||
|
|
22f62138a3 | ||
|
|
1969bde82c | ||
|
|
db9598f01e | ||
|
|
c31386dc3e | ||
|
|
aef4beee89 | ||
|
|
4880674668 | ||
|
|
85bff00a3c | ||
|
|
0e78eb6709 | ||
|
|
2b262c5442 | ||
|
|
aabac2576c | ||
|
|
56de1abb79 | ||
|
|
7d79ec01a5 | ||
|
|
8b446b7fc5 | ||
|
|
cc53bc1699 | ||
|
|
98b0a3a741 | ||
|
|
1f9d9d2967 | ||
|
|
83e1a6030a | ||
|
|
c9f34754a9 | ||
|
|
ea1ef4492d | ||
|
|
3c6ad491b5 | ||
|
|
c42f3b8174 | ||
|
|
e0ff103afd | ||
|
|
f58ca4b399 | ||
|
|
6697db1dba | ||
|
|
69002c122d | ||
|
|
6c4fde54be | ||
|
|
a34b845154 | ||
|
|
e3e122b69d | ||
|
|
67c10a9ff7 | ||
|
|
9891b6dc51 | ||
|
|
2ffd6a893b | ||
|
|
b1b0d45353 | ||
|
|
3424ab511b | ||
|
|
3c6c90a2a1 | ||
|
|
c21d8983de | ||
|
|
fef2178450 | ||
|
|
d53d760cb6 | ||
|
|
aab4a08267 | ||
|
|
dfca2f5862 | ||
|
|
404667f6a9 | ||
|
|
dcad02c1d4 | ||
|
|
bd89c00d37 | ||
|
|
5dcb1a4bba | ||
|
|
3e248c703e | ||
|
|
14a26038d5 | ||
|
|
0d864ae83e | ||
|
|
620d1b96b9 | ||
|
|
4706601213 | ||
|
|
2c0bebdaf0 | ||
|
|
da82e8aa28 | ||
|
|
d681caba1c | ||
|
|
6a4f36ad82 | ||
|
|
686ebb5a5c | ||
|
|
4399329b83 | ||
|
|
cc95b93741 | ||
|
|
e9bcf6f10a | ||
|
|
42a4807d59 | ||
|
|
86c4bc23c7 | ||
|
|
d6fc06cd7c | ||
|
|
7a61614450 | ||
|
|
97d0bdbaea | ||
|
|
eb62aad999 | ||
|
|
1b0442e773 | ||
|
|
37ce3c0ed7 | ||
|
|
145fbfa194 | ||
|
|
0af7c56b7e | ||
|
|
564d3f90c7 | ||
|
|
395aadff4e | ||
|
|
2bb8ba60ad | ||
|
|
72321ead34 | ||
|
|
42b559dda2 | ||
|
|
913a60fa0f | ||
|
|
d1d4065dae | ||
|
|
bed1d1ff35 | ||
|
|
ddb3488680 | ||
|
|
e478c89ca0 | ||
|
|
c37a79e066 | ||
|
|
e899012e5e | ||
|
|
faf8f2510e | ||
|
|
29bf6a7809 | ||
|
|
a67ad90b9a | ||
|
|
8c8da79116 | ||
|
|
d04843e41d | ||
|
|
21f0ba5a03 | ||
|
|
59f4dacc55 | ||
|
|
bb17ac2c74 | ||
|
|
47e6a0f7ab | ||
|
|
46385b06fa | ||
|
|
58baa44ad4 | ||
|
|
c6ef23a650 | ||
|
|
6c48cd54ce | ||
|
|
05e1d39217 | ||
|
|
7316aeb92c | ||
|
|
fb20db9a58 | ||
|
|
a5843d8e2d | ||
|
|
4d7a099c32 | ||
|
|
ef2f7049c7 | ||
|
|
b30c9bea11 | ||
|
|
87bb7d17b2 | ||
|
|
689e59f161 | ||
|
|
0320a45d46 | ||
|
|
3256273015 | ||
|
|
22d4bdcef8 | ||
|
|
f0ff173ad2 | ||
|
|
7ac22dbef2 | ||
|
|
d1fd7c998b | ||
|
|
f7764ca9a4 | ||
|
|
7487595e6a | ||
|
|
7bf3084e65 | ||
|
|
b3ef63859d | ||
|
|
b94dac5586 | ||
|
|
f0bbb9b370 | ||
|
|
611acd0703 | ||
|
|
0692985c80 | ||
|
|
8bd3bf976a | ||
|
|
5fa92f87fe | ||
|
|
e4ffcfc822 | ||
|
|
891a9809d0 | ||
|
|
7d57c0c103 | ||
|
|
f149b8985b | ||
|
|
1564af89f2 | ||
|
|
7acb28099d | ||
|
|
d6fc071139 | ||
|
|
bf9e5d3a83 | ||
|
|
7422538fb3 | ||
|
|
9e23214c77 | ||
|
|
6bf4c371fc | ||
|
|
ca6dd437a5 | ||
|
|
834d3b3bb3 | ||
|
|
cf8dd78a4a | ||
|
|
8a76aac83f | ||
|
|
51dae17314 | ||
|
|
ccfa109fcf | ||
|
|
c60134e8f1 | ||
|
|
e522f6185e | ||
|
|
f1c7b7939c | ||
|
|
0cb8116bed | ||
|
|
06b2475b7a | ||
|
|
1233fd5a75 | ||
|
|
be8c64b2bf | ||
|
|
ead0924a79 | ||
|
|
d31fd8aac0 | ||
|
|
86823e45ef | ||
|
|
aec284b0b8 | ||
|
|
2d79f1f959 | ||
|
|
c6a6832444 | ||
|
|
b20084be43 | ||
|
|
60ece63df4 | ||
|
|
4ca9bbdae5 | ||
|
|
7859016ec1 | ||
|
|
67fe951572 | ||
|
|
34508e145c | ||
|
|
6e44fc1c62 | ||
|
|
3dec4217aa | ||
|
|
ae9330b513 | ||
|
|
e6068833ae | ||
|
|
8b9ca9dbce | ||
|
|
a2c3e80f0f | ||
|
|
6e723d3262 | ||
|
|
11223451d2 | ||
|
|
cc1b72ebf2 | ||
|
|
84764570f4 | ||
|
|
49325e27d9 | ||
|
|
2f2dfc9038 | ||
|
|
b9ef88d4fc | ||
|
|
8a57f6c45b | ||
|
|
3f8a0b5b86 | ||
|
|
aec7b6a1ea | ||
|
|
6c70ccc66c | ||
|
|
4bd829ebdb | ||
|
|
721306879a | ||
|
|
0748b09753 | ||
|
|
01d764ef2f | ||
|
|
c45ed42af7 | ||
|
|
544e9d11a3 | ||
|
|
a7cc94c04c | ||
|
|
7877c63600 | ||
|
|
e09e993081 | ||
|
|
260ae891f5 | ||
|
|
85d1f723fb | ||
|
|
ef1fc4fc66 | ||
|
|
b1941fbff4 | ||
|
|
a2a6df529a | ||
|
|
06afaf3316 | ||
|
|
49130c71d8 | ||
|
|
2d6deda04a | ||
|
|
7aefa6d9ee | ||
|
|
59a789c750 | ||
|
|
30784dd241 | ||
|
|
5b82a38383 | ||
|
|
128f2229e6 | ||
|
|
d1f478fc4e | ||
|
|
82f08cc4b8 | ||
|
|
892a4c48ce | ||
|
|
f621de41c7 | ||
|
|
9d91ff8df9 | ||
|
|
9509c62918 | ||
|
|
e921a4bc7f | ||
|
|
7da9c0669d | ||
|
|
90972577af | ||
|
|
18a34b938f | ||
|
|
9d22c5406f | ||
|
|
6359d69ef4 | ||
|
|
52f5ab035f | ||
|
|
05e4982245 | ||
|
|
2e3deb0a21 | ||
|
|
cc4c8cd191 | ||
|
|
46f879dcdb | ||
|
|
e2fc3d35b8 | ||
|
|
da0578fc39 | ||
|
|
dbce2b33b3 | ||
|
|
ee9ea5d5a1 | ||
|
|
b75ebd6f41 | ||
|
|
77420760b0 | ||
|
|
6131da92c4 | ||
|
|
e9dd050229 | ||
|
|
5cb537274e | ||
|
|
1f04c55765 | ||
|
|
e3926c657a | ||
|
|
59742ccc8f | ||
|
|
fefad8a9e3 | ||
|
|
5a96e7c90f | ||
|
|
3089a4a534 | ||
|
|
b48aed2fed | ||
|
|
ac36b6d361 | ||
|
|
dd19cf58cc | ||
|
|
b21e442c4f | ||
|
|
42b47c5453 | ||
|
|
e27b58176d | ||
|
|
516d230647 | ||
|
|
91a74ed063 | ||
|
|
913d15632b | ||
|
|
9ab9ccf79d | ||
|
|
0d072f2945 | ||
|
|
0125de3d06 | ||
|
|
e3ab296a72 | ||
|
|
ceb32b3d8a | ||
|
|
e3fc1e62a0 | ||
|
|
562fed6e7e | ||
|
|
e896fd0137 | ||
|
|
17bcb1e84c | ||
|
|
c67e35c5ae | ||
|
|
eaf3f0c5df | ||
|
|
cd8ae9308d | ||
|
|
8f5471d96b | ||
|
|
b3223dd94b | ||
|
|
5a7444f424 | ||
|
|
015769a9f8 | ||
|
|
41055ce0a1 | ||
|
|
4ae1ea1daf | ||
|
|
25a881255e | ||
|
|
afc02141ce | ||
|
|
cd82ab7c59 | ||
|
|
86b9d28451 | ||
|
|
b4dc00eca1 | ||
|
|
b857283ed6 | ||
|
|
f5010ce764 | ||
|
|
bab0237727 | ||
|
|
33bd1327a0 | ||
|
|
11d17c5803 | ||
|
|
7abc35bc02 | ||
|
|
e4e6b4189c | ||
|
|
31e2e95452 | ||
|
|
23567b0395 | ||
|
|
5c95c35743 | ||
|
|
08e4d6b06b | ||
|
|
1a3ea508fe | ||
|
|
b1dbe35102 | ||
|
|
4d803fe2cd | ||
|
|
7f1c59fde8 | ||
|
|
5c6400e21b | ||
|
|
2216729721 | ||
|
|
ea3f14f195 | ||
|
|
ee42f44254 | ||
|
|
74c8226323 | ||
|
|
ba4949e822 | ||
|
|
098be27375 | ||
|
|
2f262c943c | ||
|
|
4f1589132c | ||
|
|
7f9418fe98 | ||
|
|
8eb803292e | ||
|
|
d854058be6 | ||
|
|
d35bdd333b | ||
|
|
bdf49b9b00 | ||
|
|
72cc386207 | ||
|
|
3a61e782ad | ||
|
|
dfc869bd2d | ||
|
|
8df8182f01 | ||
|
|
bf59a1e2f8 | ||
|
|
07066fd8c1 | ||
|
|
8b0f8d7c20 | ||
|
|
20f738ba0d | ||
|
|
86f9dd7400 | ||
|
|
d69a1a65ee | ||
|
|
a993ac74f1 | ||
|
|
f3227275b1 | ||
|
|
71c2ffb3ee | ||
|
|
9330db9ff8 | ||
|
|
9f14f8424f | ||
|
|
3e17928547 | ||
|
|
96dd7b16ac | ||
|
|
06ef9ab657 | ||
|
|
24a249353c | ||
|
|
970675a2ac | ||
|
|
c72a8a1424 | ||
|
|
d514786239 | ||
|
|
cc3fc42b0a | ||
|
|
2c7475a5e6 | ||
|
|
e644df74fe | ||
|
|
8355a95407 | ||
|
|
f8a1a2c6ed | ||
|
|
487677958e | ||
|
|
68ffe9583c | ||
|
|
fd6c52ede4 | ||
|
|
91732419b6 | ||
|
|
2a60011414 | ||
|
|
873beebc0f | ||
|
|
74926fcc2e | ||
|
|
37ff8c9143 | ||
|
|
1dbfb1a998 | ||
|
|
2bff6541f2 | ||
|
|
b1e163b7f5 | ||
|
|
87d27f9c51 | ||
|
|
773ca6f724 | ||
|
|
69fdf0b145 | ||
|
|
19a848484a | ||
|
|
5063a8b396 | ||
|
|
efadc21cdc | ||
|
|
a5cdd8d5aa | ||
|
|
682722bc29 | ||
|
|
95e4a34476 | ||
|
|
7f684ce130 | ||
|
|
87971248c5 | ||
|
|
18ff5c30f0 | ||
|
|
922af23c63 | ||
|
|
57fd2162d1 | ||
|
|
08e2be9875 | ||
|
|
0ce54e2b14 | ||
|
|
747a3f7a9f | ||
|
|
5af15f6496 | ||
|
|
4a5689e9b6 | ||
|
|
c1270e635e | ||
|
|
2e135d035f | ||
|
|
0a33eeb0c0 | ||
|
|
4c51883b97 | ||
|
|
d797c7a4d8 | ||
|
|
dd5667c09b | ||
|
|
d1c6ee33be | ||
|
|
a53e474f9c | ||
|
|
e7805914f4 | ||
|
|
0f560f4e4c | ||
|
|
5c172e3be9 | ||
|
|
0a62553746 | ||
|
|
9442b7ee6c | ||
|
|
7e706354f9 | ||
|
|
c8aff336b3 | ||
|
|
26ffaf0ad3 | ||
|
|
f81763b173 | ||
|
|
26b6c70b96 | ||
|
|
6809aa50ad | ||
|
|
dc80fb2d50 | ||
|
|
1500fb9fa3 | ||
|
|
0bf4fc54c4 | ||
|
|
c2b6a9cc12 | ||
|
|
c4cfee1807 | ||
|
|
b7c2002b63 | ||
|
|
e07ac6243c | ||
|
|
9f038891ef | ||
|
|
97dbcc6870 | ||
|
|
6203b9712d | ||
|
|
b87bdeea41 | ||
|
|
20e75c3251 | ||
|
|
2bc0afa830 | ||
|
|
d9341bbf1a | ||
|
|
2b7535cd83 | ||
|
|
7e1f4b8dbf | ||
|
|
52b4fc0b9d | ||
|
|
519c4cb518 | ||
|
|
db29ed6501 | ||
|
|
331ed31b1c | ||
|
|
2562871424 | ||
|
|
4eae5bc658 | ||
|
|
f4a5ee0c7e | ||
|
|
e4878052aa | ||
|
|
072b2e3285 | ||
|
|
ac32c0fd8b | ||
|
|
233cfb80ea | ||
|
|
964b5a0e88 | ||
|
|
1dd60c948b | ||
|
|
04e03478a9 | ||
|
|
b50d87a6f4 | ||
|
|
12354bd23b | ||
|
|
69963dce2c | ||
|
|
38cfc233cf | ||
|
|
f31dde4a1b | ||
|
|
93edf4e099 | ||
|
|
44bba85ce8 | ||
|
|
3e0d2c06f1 | ||
|
|
67d2e1cead | ||
|
|
d3419ed124 | ||
|
|
6fc1726da7 | ||
|
|
ae83e01923 | ||
|
|
581157ca75 | ||
|
|
363383363d | ||
|
|
19903271ce | ||
|
|
601a1f2292 | ||
|
|
35919f640c | ||
|
|
94aa126107 | ||
|
|
4657156c91 | ||
|
|
e1a595d78d | ||
|
|
21aaa1c33c | ||
|
|
63741ca9bc | ||
|
|
48e9bda610 | ||
|
|
6b2331b647 | ||
|
|
ae0413ce80 | ||
|
|
499ce2709c | ||
|
|
0937d47721 | ||
|
|
f9541b3281 | ||
|
|
0970415c3a | ||
|
|
d71a0db4a2 | ||
|
|
303b3a9a89 | ||
|
|
e2bcf90856 | ||
|
|
8fb3e6d1a9 | ||
|
|
8ff5d9e3e1 | ||
|
|
6231b6dd5a | ||
|
|
cb449989b8 | ||
|
|
1c4d2b84e0 | ||
|
|
64a2237fb3 | ||
|
|
b9e560d33e | ||
|
|
0f2690eb75 | ||
|
|
0c1e341f50 | ||
|
|
3e2f6a8783 | ||
|
|
e52b1993f4 | ||
|
|
4ecac12cc6 | ||
|
|
31edc728d4 | ||
|
|
6cbb0bc103 | ||
|
|
ed20f8b4d1 | ||
|
|
ed00016caa | ||
|
|
c4a0a760b1 | ||
|
|
e81f5d96f1 | ||
|
|
e6aba9b879 | ||
|
|
fbf0177215 | ||
|
|
ee859e374a | ||
|
|
be0cc2c602 | ||
|
|
7b7c153711 | ||
|
|
90e92e995f | ||
|
|
9a44834289 | ||
|
|
68255d075e | ||
|
|
70f75fd3b0 | ||
|
|
122b160639 | ||
|
|
18500b19d0 | ||
|
|
676be3fc00 | ||
|
|
da6efecaef | ||
|
|
14afba4b62 | ||
|
|
ffb68f2f6c | ||
|
|
ce0ee4b693 | ||
|
|
9cad92b817 | ||
|
|
2a077ab131 | ||
|
|
76232fda21 | ||
|
|
2b0255435e | ||
|
|
6222737d1a | ||
|
|
488bcc484f | ||
|
|
bb8a8a4362 | ||
|
|
c434ec40dd | ||
|
|
c8dd6095c8 | ||
|
|
08879d81d6 | ||
|
|
587e4227d7 | ||
|
|
f6f920350d | ||
|
|
cbefe513c2 | ||
|
|
001a6cc259 | ||
|
|
c634273fe1 | ||
|
|
0a80484919 | ||
|
|
9d6669eb1e | ||
|
|
f0ac59f3dc | ||
|
|
60983dadd5 | ||
|
|
1197683ab3 | ||
|
|
4f8a1bc968 | ||
|
|
a9df0424e5 | ||
|
|
6053091563 | ||
|
|
95038a7da5 | ||
|
|
ff72087da1 | ||
|
|
4b7ac315b5 | ||
|
|
33d97f585e | ||
|
|
27bd0708b6 | ||
|
|
c1f018eae8 | ||
|
|
c607b8f455 | ||
|
|
496e067d11 | ||
|
|
c16b74ec5b | ||
|
|
32f812d515 | ||
|
|
ab5758c0b6 | ||
|
|
9be57b3110 | ||
|
|
06dc00af24 | ||
|
|
4a1ca8ea96 | ||
|
|
37a6e0a61f | ||
|
|
c9a5a66020 | ||
|
|
a61f7035ad | ||
|
|
75a2c325ec | ||
|
|
eeb94aea48 | ||
|
|
a080b7c9c6 | ||
|
|
f8826a9e8a | ||
|
|
ece2b59700 | ||
|
|
845b5a9006 | ||
|
|
c506e41072 | ||
|
|
14f4881d04 | ||
|
|
741940dd9a | ||
|
|
e94ed24e20 | ||
|
|
05d19fc6aa | ||
|
|
8d0923f119 | ||
|
|
ee512680ac | ||
|
|
cd9f90da8d | ||
|
|
163ed14f92 | ||
|
|
e6cd5f322f | ||
|
|
0f7590ad13 | ||
|
|
e715593eb7 | ||
|
|
fd4dde300d | ||
|
|
832575b7c0 | ||
|
|
f5907ed3b2 | ||
|
|
78534ff2d2 | ||
|
|
c3f8ba8eb1 | ||
|
|
735922a2bf | ||
|
|
27affb9f14 | ||
|
|
11014be449 | ||
|
|
b31b71304d | ||
|
|
a370ec8979 | ||
|
|
cc0b1ad0c9 | ||
|
|
8041d7d4df | ||
|
|
1eb248553a | ||
|
|
5e1541c5ee | ||
|
|
d4a5fbbefe | ||
|
|
cc691abeee | ||
|
|
9b1950c9ea | ||
|
|
d1ea8a397b | ||
|
|
9698927d22 | ||
|
|
e2a96e512a | ||
|
|
2d4a086819 | ||
|
|
162fb4d51b | ||
|
|
ce6c27ae7e | ||
|
|
9c82fed152 | ||
|
|
0e3b695a85 | ||
|
|
c945afb2e1 | ||
|
|
248ddf05d2 | ||
|
|
057c798202 | ||
|
|
59730c0fca | ||
|
|
dd10111e5d | ||
|
|
42e21d4fa1 | ||
|
|
01683b6ccb | ||
|
|
845361bdbc | ||
|
|
7a4aef1b32 | ||
|
|
a85e1fb40a | ||
|
|
387d5966c3 | ||
|
|
98d7d8c408 | ||
|
|
3b8e8bea33 | ||
|
|
aff57c2254 | ||
|
|
b8e1b994e0 | ||
|
|
c32e050c6e | ||
|
|
f9b3694dd1 | ||
|
|
d9a45726d4 | ||
|
|
7beed24756 | ||
|
|
114bd3c495 | ||
|
|
bdcc5c551a | ||
|
|
4808ebd2e9 | ||
|
|
c19032a004 | ||
|
|
9ba1580c3b | ||
|
|
80d01c9d02 | ||
|
|
355c61e6d8 | ||
|
|
4dbe0f7842 | ||
|
|
774173f04d | ||
|
|
37f8c4d4f4 | ||
|
|
6eb8a80e12 | ||
|
|
0b5012555d | ||
|
|
0acfcd3f99 | ||
|
|
50cafe57a2 | ||
|
|
57bc913304 | ||
|
|
e6ce021b5f | ||
|
|
408f1274f4 | ||
|
|
f50e8b0b35 | ||
|
|
1c469ce1a0 | ||
|
|
9dbac93dc9 | ||
|
|
96d3f312b3 | ||
|
|
195629186b | ||
|
|
3f84856e1e | ||
|
|
c493a17b13 | ||
|
|
e50787c94f | ||
|
|
15269763bb | ||
|
|
b05ddaf32b | ||
|
|
4f7f9ae75b | ||
|
|
65bc56b07b | ||
|
|
7a74384b42 | ||
|
|
27648bd73a | ||
|
|
28ffdd4c10 | ||
|
|
777d6f951f | ||
|
|
8cf61fed9e | ||
|
|
6ff349d65d | ||
|
|
51a62022e9 | ||
|
|
0b7340a651 | ||
|
|
110d04f5f7 | ||
|
|
ee35361608 | ||
|
|
ded8dca668 | ||
|
|
05a2539b81 | ||
|
|
1f8e05bfd8 | ||
|
|
cdcac8a6e1 | ||
|
|
769b4c8c34 | ||
|
|
3b151a0b18 | ||
|
|
9d04392eb0 | ||
|
|
3ff13bc08d | ||
|
|
46f80ebdfb | ||
|
|
dfc31d9961 | ||
|
|
086b0c3d84 | ||
|
|
e18bf2165a | ||
|
|
b0506aafe1 | ||
|
|
2bc0c4861c | ||
|
|
ed24cce4a1 | ||
|
|
1eacc8bbdf | ||
|
|
9ed3f6363c | ||
|
|
420b84d17e | ||
|
|
51649b0045 | ||
|
|
e54665cf49 | ||
|
|
1b61be71b9 | ||
|
|
e625c0009e | ||
|
|
f539d7439d | ||
|
|
c1cea87743 | ||
|
|
3102b6b67a | ||
|
|
c42e144f56 | ||
|
|
0b339a3a30 | ||
|
|
32009ccdb6 | ||
|
|
143829065f | ||
|
|
6eafb89e82 | ||
|
|
971c57fedd | ||
|
|
f8a517d286 | ||
|
|
61b62d0a02 | ||
|
|
c6e5e6c1e6 | ||
|
|
4b5bee37b1 | ||
|
|
55423024ea | ||
|
|
de0907c8f7 | ||
|
|
af6e4cc44c | ||
|
|
54763ff722 | ||
|
|
31845457a2 | ||
|
|
03b33d995e | ||
|
|
68aff7b23e | ||
|
|
22996da722 | ||
|
|
929bacaac7 | ||
|
|
3fc8e4d02e | ||
|
|
a7964f7116 | ||
|
|
d9b9046201 | ||
|
|
36d979f71e | ||
|
|
d7d1d03b8b | ||
|
|
230e3d8065 | ||
|
|
4521f750a4 | ||
|
|
bd9735baf3 | ||
|
|
54006b7c8c | ||
|
|
70af1165a5 | ||
|
|
48fd23ccec | ||
|
|
3144314d20 | ||
|
|
a63cb647ff | ||
|
|
d74db17cf1 | ||
|
|
97f8d942a0 | ||
|
|
56b4c15de9 | ||
|
|
e80615eab8 | ||
|
|
1655265189 | ||
|
|
f2a86e4af9 | ||
|
|
cc87ff3af6 | ||
|
|
2cd4ba205a | ||
|
|
69dcbda1a0 | ||
|
|
9579aa154a | ||
|
|
d6d01f66b9 | ||
|
|
5b1ed9ac8b | ||
|
|
5e18337cc6 | ||
|
|
d781151b9a | ||
|
|
6d206f98bb | ||
|
|
67b5a0bb19 | ||
|
|
db1c542a50 | ||
|
|
e690b0b18e | ||
|
|
1c089bf448 | ||
|
|
dc084b6961 | ||
|
|
a7778b93e8 | ||
|
|
b067e0d940 | ||
|
|
173660d5c7 | ||
|
|
1459ca210d | ||
|
|
f568363098 | ||
|
|
0bff70b186 | ||
|
|
246005a097 | ||
|
|
2db51eb0e5 | ||
|
|
71a4742092 | ||
|
|
8c7ab1eb6a | ||
|
|
f616d41546 | ||
|
|
060a15fe78 | ||
|
|
cef26fae09 | ||
|
|
1116be4a02 | ||
|
|
e480c78898 | ||
|
|
ba3cd9e094 | ||
|
|
3d1cf90934 | ||
|
|
650be7d350 | ||
|
|
a4db5c9bd2 | ||
|
|
4fc7730181 | ||
|
|
b0b9442c95 | ||
|
|
f279e9f33b | ||
|
|
c6688ba9d4 | ||
|
|
db90eb9103 | ||
|
|
c400d11c5c | ||
|
|
e6f1983073 | ||
|
|
3d538d71ca | ||
|
|
0b8b4c0ff6 | ||
|
|
fcfb6e16d0 | ||
|
|
c59c1f7e7c | ||
|
|
4f03c5d360 | ||
|
|
a8d32291a4 | ||
|
|
f1244d824c | ||
|
|
b8ec6eb75e | ||
|
|
2bff0ea93f | ||
|
|
3a536c647b | ||
|
|
d5d24f5d9d | ||
|
|
8eda90cdc0 | ||
|
|
5a5f2c2e59 | ||
|
|
929147b33a | ||
|
|
d9e8ea8ff7 | ||
|
|
4421de63de | ||
|
|
a366f16346 | ||
|
|
b3a3757716 | ||
|
|
314bd08c03 | ||
|
|
8ec81da1d9 | ||
|
|
951ed4fa4b | ||
|
|
cf37bf5ce1 | ||
|
|
6787dcd596 | ||
|
|
41bb2784b5 | ||
|
|
93b677aaf4 | ||
|
|
eb54cd82f6 | ||
|
|
9a58be243e | ||
|
|
753032a001 | ||
|
|
d79baf8251 | ||
|
|
01db0bfe86 | ||
|
|
2a31c1977e | ||
|
|
ab2880471e | ||
|
|
35659b599e | ||
|
|
ebc670bb56 | ||
|
|
ccf4fd20cc | ||
|
|
d92ddd18b7 | ||
|
|
087df1f0c1 | ||
|
|
80f9622c65 | ||
|
|
c9f43bcdb8 | ||
|
|
91546e2e20 | ||
|
|
d780eed06f | ||
|
|
fef389290a | ||
|
|
0d934c846f | ||
|
|
99b4171500 | ||
|
|
4915f1fadf | ||
|
|
583fbf4e95 | ||
|
|
a49e4e5449 | ||
|
|
bbf91d65f9 | ||
|
|
de0f5693e8 | ||
|
|
ebdeab4b3e | ||
|
|
92d6e69b6e | ||
|
|
a98d172cd7 | ||
|
|
bbfede2b55 | ||
|
|
bcb7e08f2f | ||
|
|
ea71725e7f | ||
|
|
38188ff7d0 | ||
|
|
e9c0e47a17 | ||
|
|
2d95cad479 | ||
|
|
de24306c90 | ||
|
|
cb53c6eb2e | ||
|
|
011c5bd6c0 | ||
|
|
b78bf8e24b | ||
|
|
9cdfadbbae | ||
|
|
764dd1a9da | ||
|
|
6d52656a92 | ||
|
|
4a00304925 | ||
|
|
27f1103d88 | ||
|
|
cbd6ccbec3 | ||
|
|
a3654652b2 | ||
|
|
8ddb6bfd17 | ||
|
|
e532e435f4 | ||
|
|
659d5e864b | ||
|
|
ac0813e0f5 | ||
|
|
8a06edab49 | ||
|
|
679de040ec | ||
|
|
8082516bf6 | ||
|
|
c9c9c500bf | ||
|
|
d931319b12 | ||
|
|
d7ce4191b1 | ||
|
|
d0bf8f8993 | ||
|
|
05f3ea3b82 | ||
|
|
8021ca0a0b | ||
|
|
6add721e68 | ||
|
|
a464fe0408 | ||
|
|
d3cee95fb7 | ||
|
|
c262a5b392 | ||
|
|
3a26ce3bb1 | ||
|
|
1f401f0897 | ||
|
|
ccc1800f21 | ||
|
|
cab8e38806 | ||
|
|
5c8859b618 | ||
|
|
c19f43ea46 | ||
|
|
1e08985dcd | ||
|
|
307753d313 | ||
|
|
1b64e3417c | ||
|
|
6f8da4825e | ||
|
|
ba7b521bb1 | ||
|
|
ddb5977c48 | ||
|
|
9077310669 | ||
|
|
3c8d50dd47 | ||
|
|
26221b6786 | ||
|
|
90a9c5164a | ||
|
|
c049120efb | ||
|
|
a3ebb4ad41 | ||
|
|
854f2188c2 | ||
|
|
54346b0ca7 | ||
|
|
96e71762f9 | ||
|
|
d3871d6864 | ||
|
|
45310397e5 | ||
|
|
2e9b9d4070 | ||
|
|
eb30c23a0d | ||
|
|
239b68e6b8 | ||
|
|
d231fb3b53 | ||
|
|
e765a4d3af | ||
|
|
3b7dd58c50 | ||
|
|
fc3b7e0f83 | ||
|
|
9c6b3368f2 | ||
|
|
8e08527991 | ||
|
|
51d668db56 | ||
|
|
c51133f43c | ||
|
|
506f3b14e3 | ||
|
|
5978353d57 | ||
|
|
8dbc6177ce | ||
|
|
87f8229b32 | ||
|
|
4d8d4bf6a9 | ||
|
|
98a5b7eaec | ||
|
|
d25b96643c | ||
|
|
fb8b65b329 | ||
|
|
7256072c5b | ||
|
|
083b4f69c9 | ||
|
|
d358915707 | ||
|
|
46879a8241 | ||
|
|
5d5c043161 | ||
|
|
41396c8148 | ||
|
|
553f0f3994 | ||
|
|
553e2466ed | ||
|
|
3d75801a84 | ||
|
|
6582f7ffda | ||
|
|
0ac57f8262 | ||
|
|
7466fa479f | ||
|
|
eb776f8e6e | ||
|
|
51349a5a97 | ||
|
|
a2a99c12f5 | ||
|
|
2a7f4fb2a5 | ||
|
|
2aee7ae8d5 | ||
|
|
2afbe030d5 | ||
|
|
d1e67987bd | ||
|
|
65393d09eb | ||
|
|
a7fff8cada | ||
|
|
6cdae37e5b | ||
|
|
48b50064e9 | ||
|
|
be023c3a95 | ||
|
|
71d697801e | ||
|
|
7a467b8bfa | ||
|
|
814e59f694 | ||
|
|
39cbf5e520 | ||
|
|
465cc89ad6 | ||
|
|
9510eef69a | ||
|
|
ff3ab619d1 | ||
|
|
679b1df116 | ||
|
|
3a816fad55 | ||
|
|
5f983d71c1 | ||
|
|
79092fadcd | ||
|
|
b6ca3eac37 | ||
|
|
dcf809961a | ||
|
|
ed045e640a | ||
|
|
ec280c5bdf | ||
|
|
8642091d8e | ||
|
|
e3387bbe96 | ||
|
|
aaf7984a8e | ||
|
|
39b92d6cdb | ||
|
|
d2952d3e71 | ||
|
|
9e569c33f8 | ||
|
|
a2f3b28b48 | ||
|
|
6308ea6a18 | ||
|
|
00c0679333 | ||
|
|
296edc3fdd | ||
|
|
a4414cc2f0 | ||
|
|
67da025e3f | ||
|
|
810062a1af | ||
|
|
850431af93 | ||
|
|
e1cee8cc45 | ||
|
|
b84f1a70f0 | ||
|
|
94650e2ee9 | ||
|
|
998315dd58 | ||
|
|
e11d93f0bc | ||
|
|
9f83790ed6 | ||
|
|
c8051aa3f8 | ||
|
|
0bdae76e49 | ||
|
|
8cfcdeb8e6 | ||
|
|
484eb1f1d7 | ||
|
|
524660e10b | ||
|
|
459d00448a | ||
|
|
52c342b697 | ||
|
|
b86305f40e | ||
|
|
c44d845c8c | ||
|
|
c41eb54278 | ||
|
|
b538b12d51 | ||
|
|
ef8de73d5a | ||
|
|
2c377316e3 | ||
|
|
ab9849e71a | ||
|
|
46d5d2f5ee | ||
|
|
bad01686d8 | ||
|
|
c1c2bc76b7 | ||
|
|
bc3c05d064 | ||
|
|
74216a5887 | ||
|
|
9bee1b1d79 | ||
|
|
5fd94e22df | ||
|
|
805378e49f | ||
|
|
c672392fe4 | ||
|
|
7e7ceffd77 | ||
|
|
9777d21001 | ||
|
|
7dad8377df | ||
|
|
0b44461a66 | ||
|
|
6ee556500d | ||
|
|
54db192be8 | ||
|
|
7b7a0b9e46 | ||
|
|
a89e0a1554 | ||
|
|
001c94b585 | ||
|
|
20e28d3f9e | ||
|
|
244d182293 | ||
|
|
e8b1ea5b55 | ||
|
|
fa48e978c7 | ||
|
|
013a814765 | ||
|
|
cddbbdd208 | ||
|
|
7031d1928a | ||
|
|
878d1cc401 | ||
|
|
485033b4a4 | ||
|
|
b806b41b6f | ||
|
|
aa4f942b26 | ||
|
|
b007bd4364 | ||
|
|
4d90fe72bd | ||
|
|
e80b5787fe | ||
|
|
28e7966973 | ||
|
|
b0fab21cc3 | ||
|
|
42b97d8fcd | ||
|
|
d63c39acff | ||
|
|
f118d49d24 | ||
|
|
1fa34daeef | ||
|
|
ee66d2042b | ||
|
|
e3b243ba45 | ||
|
|
d580e420d3 | ||
|
|
ca1e9bc467 | ||
|
|
967b0c6df4 | ||
|
|
fed4097384 | ||
|
|
0152769201 | ||
|
|
fd7e0ec640 | ||
|
|
507fd519bb | ||
|
|
a9e68d9530 | ||
|
|
468155c548 | ||
|
|
43f9d98c16 | ||
|
|
fa20733353 | ||
|
|
d6f3acfede | ||
|
|
7c2720e8fc | ||
|
|
4319b8d78e | ||
|
|
a0bdeab401 | ||
|
|
26bcc49174 | ||
|
|
d9550bb5df | ||
|
|
b858645957 | ||
|
|
67b5545b93 | ||
|
|
7833c6fc29 | ||
|
|
275fc4a230 | ||
|
|
268ba4821c | ||
|
|
a32e327ef8 | ||
|
|
c963e5785f | ||
|
|
d271c6c931 | ||
|
|
72b56e7a59 | ||
|
|
f28fa763cc | ||
|
|
a96b7f1b68 | ||
|
|
160cc8ba72 | ||
|
|
45e681431b | ||
|
|
9606fca3ad | ||
|
|
f11fb6c2a0 | ||
|
|
78975f0f2a | ||
|
|
9b4961a31f | ||
|
|
f341341012 | ||
|
|
5c4a0c3b30 | ||
|
|
187b1649c1 | ||
|
|
24bf583b78 | ||
|
|
6b3ea14aa1 | ||
|
|
97329752a1 | ||
|
|
7f619e3fe3 | ||
|
|
3fde2a3e43 | ||
|
|
b18b15fc08 | ||
|
|
05ae75d3b4 | ||
|
|
d970f00243 | ||
|
|
31bbf2acfa | ||
|
|
67486965dd | ||
|
|
4196b61dc5 | ||
|
|
85deee9631 | ||
|
|
d3ef6cfebd | ||
|
|
6c437e3df2 | ||
|
|
e4f2894424 | ||
|
|
8c58d887bf | ||
|
|
021c004923 | ||
|
|
64c03792ea | ||
|
|
404fc41b88 | ||
|
|
f3d274afeb | ||
|
|
61b034898d | ||
|
|
0a60953226 | ||
|
|
886dbd17ff | ||
|
|
d57392d810 | ||
|
|
6740115cf2 | ||
|
|
8317f77837 | ||
|
|
1c70e53006 | ||
|
|
6fe2772318 | ||
|
|
0f415063ce | ||
|
|
5939f53e9a | ||
|
|
4067745c7a | ||
|
|
99b80723b8 | ||
|
|
b5310d5f04 | ||
|
|
969feb620d | ||
|
|
7296583f2a | ||
|
|
c9c373854c | ||
|
|
052cbb7702 | ||
|
|
247826194a | ||
|
|
bacb60a103 | ||
|
|
0e2427fc9f | ||
|
|
5a005b9adb | ||
|
|
08ed672445 | ||
|
|
bb0d7ab951 | ||
|
|
501b7a9801 | ||
|
|
204c1e3514 | ||
|
|
ee4c244e0f | ||
|
|
fa822b516c | ||
|
|
d698287558 | ||
|
|
2e202a59c9 | ||
|
|
f824741d07 | ||
|
|
56ae6d9793 | ||
|
|
2ce9b4701b | ||
|
|
5e92421114 | ||
|
|
9a578f8572 | ||
|
|
a195750f31 | ||
|
|
8c5a863aaf | ||
|
|
5d0420a7d0 | ||
|
|
e9f3d667b3 | ||
|
|
bc2c7956db | ||
|
|
f5b653e7fd | ||
|
|
8e2ec86e56 | ||
|
|
e3f2f4455b | ||
|
|
dc39ca3756 | ||
|
|
75fb301f0a | ||
|
|
ddacfc0b8a | ||
|
|
dc47650eb3 | ||
|
|
1a4ecff347 | ||
|
|
3284cb461e | ||
|
|
7f57a43f27 | ||
|
|
e3c18ee1c7 | ||
|
|
14c2d58e91 | ||
|
|
f001123c9b | ||
|
|
5b89ceb15e | ||
|
|
6270311b24 | ||
|
|
a6c178dfe8 | ||
|
|
c1bef57123 | ||
|
|
e94789c8db | ||
|
|
d75d638337 | ||
|
|
5e84944cd6 | ||
|
|
7fa00d1cfd | ||
|
|
c937b36e25 | ||
|
|
055fbb68fc | ||
|
|
a4e89e62f2 | ||
|
|
aec6e61cb3 | ||
|
|
347caaff4c | ||
|
|
28e3c7b47f | ||
|
|
5152d2c7ff | ||
|
|
4ca3843ce7 | ||
|
|
7c91f37348 | ||
|
|
e9a19cb7a1 | ||
|
|
9f8c5c8581 | ||
|
|
d3456b050a | ||
|
|
5b2e666f4f | ||
|
|
bc62bbfdda | ||
|
|
913c500733 | ||
|
|
1b43521786 | ||
|
|
e2905b22ad | ||
|
|
682cceca2d | ||
|
|
7f26f246e7 | ||
|
|
c567905bf6 | ||
|
|
67505f3960 | ||
|
|
bd8cae6fdd | ||
|
|
17f003df0f | ||
|
|
51f2c76d82 | ||
|
|
0db1bae009 | ||
|
|
30024487f3 | ||
|
|
7c8e672f2f | ||
|
|
e202924324 | ||
|
|
884a62d526 | ||
|
|
fadbf3d2df | ||
|
|
d0a7cfae6d | ||
|
|
f0da5aaf2b | ||
|
|
d9c2abd701 | ||
|
|
364e87a57f | ||
|
|
10ed78212b | ||
|
|
00b2978c8b | ||
|
|
bb7a7ab961 | ||
|
|
88e10cdace | ||
|
|
19977c69c4 | ||
|
|
bba016ecb8 | ||
|
|
ece595e79c | ||
|
|
28f3a29f35 | ||
|
|
8e87aa15e7 | ||
|
|
504ec7eb4a | ||
|
|
7c1eb0c3f1 | ||
|
|
88d4598fce | ||
|
|
03b00669ed | ||
|
|
cb62ab064d | ||
|
|
8a6bc2cb10 | ||
|
|
7c9a0ac624 | ||
|
|
bfa9d5b6d2 | ||
|
|
c0c3d93019 | ||
|
|
3e37c44c82 | ||
|
|
a2ed2c8b12 | ||
|
|
62de988cb8 | ||
|
|
d2c8f5f186 | ||
|
|
c338c0262d | ||
|
|
eea1291314 | ||
|
|
1c0c17ea47 | ||
|
|
5ead1c5aad | ||
|
|
6e6c212b76 | ||
|
|
48a1a97c66 | ||
|
|
76618b4de7 | ||
|
|
f8e30cff08 | ||
|
|
e3fda0819a | ||
|
|
46bdf3805f | ||
|
|
1f5b7f5414 | ||
|
|
bb6085bbe0 | ||
|
|
b6d44520a8 | ||
|
|
1df2a96ae3 | ||
|
|
4c68f834c1 | ||
|
|
ae101f5393 | ||
|
|
06844d18ad | ||
|
|
36f4cb48c9 | ||
|
|
7efb296da9 | ||
|
|
f13791de60 | ||
|
|
617b014b85 | ||
|
|
c75119324c | ||
|
|
a36e0a88f6 | ||
|
|
f2367c88f5 | ||
|
|
ba45c72dc0 | ||
|
|
a6c9af3c28 | ||
|
|
d51218cddd | ||
|
|
e5bc22f64b | ||
|
|
1904675b71 | ||
|
|
5bd068860c | ||
|
|
7cf9097467 | ||
|
|
2f5a7aa369 | ||
|
|
d786454a3f | ||
|
|
d14a72e1b0 | ||
|
|
cde21ac9f2 | ||
|
|
d1960cee6b | ||
|
|
0e07c7a26a | ||
|
|
7ac4c8d667 | ||
|
|
c14896a640 | ||
|
|
15ccf28fb4 | ||
|
|
237a2e5b86 | ||
|
|
e1cf60b3cf | ||
|
|
f22f87537c | ||
|
|
528ee8adac | ||
|
|
dc60b10f00 | ||
|
|
40dd345280 | ||
|
|
00182e317c | ||
|
|
54cee37703 | ||
|
|
1caeb1ef08 | ||
|
|
9d9d98b907 | ||
|
|
43b491fbd3 | ||
|
|
f1aeb278a6 | ||
|
|
fa2316154e | ||
|
|
23f9ebcd17 | ||
|
|
fc7307fd84 | ||
|
|
dc5ec2dd36 | ||
|
|
b00b23306d | ||
|
|
d462330347 | ||
|
|
6282eef3cc | ||
|
|
684c63669b | ||
|
|
e754fa0c41 | ||
|
|
e2bbe60b65 | ||
|
|
508c34c95b | ||
|
|
304e76685e | ||
|
|
cca605e9c8 | ||
|
|
605b986a92 | ||
|
|
9672571913 | ||
|
|
a0da169664 | ||
|
|
20d13f5a8e | ||
|
|
afe669aa46 | ||
|
|
1391bf23da | ||
|
|
7c7e1cba34 | ||
|
|
3fcdae8fa9 | ||
|
|
4434724278 | ||
|
|
5ff35c896c | ||
|
|
a4225592a1 | ||
|
|
f7a56efacf | ||
|
|
3ffe736d99 | ||
|
|
c59c8cbffe | ||
|
|
e35c220be4 | ||
|
|
d4b2fbf33b | ||
|
|
b946946b00 | ||
|
|
acc727358b | ||
|
|
7749302295 | ||
|
|
1278445f5c | ||
|
|
da10878f6f | ||
|
|
6e130a8649 | ||
|
|
9e5b9545e7 | ||
|
|
b4239fd4c9 | ||
|
|
2ca1389b43 | ||
|
|
564b1766aa | ||
|
|
8fbed0b62b | ||
|
|
8de36726a0 | ||
|
|
74a89933dc | ||
|
|
82d50676d3 | ||
|
|
78077fab9d | ||
|
|
58d98af6c1 | ||
|
|
6504c95d24 | ||
|
|
01017e7d63 | ||
|
|
64bed48de4 | ||
|
|
7a0fb5d1f1 | ||
|
|
f95b40f05f | ||
|
|
dcf6c14d66 | ||
|
|
fe3fdac88e | ||
|
|
8e6c801127 | ||
|
|
95fa3cb199 | ||
|
|
b9bdc6618c | ||
|
|
5a3f2ddfa6 | ||
|
|
5695d08e7d | ||
|
|
42219772a7 | ||
|
|
5233e0f487 | ||
|
|
aff5aef4c1 | ||
|
|
58f5e188e3 | ||
|
|
4c04dc583e | ||
|
|
6631e7c3e0 | ||
|
|
5bd5bfa343 | ||
|
|
af3602124b | ||
|
|
dbeb1f167c | ||
|
|
974ac78618 | ||
|
|
8de5eb360d | ||
|
|
989956f392 | ||
|
|
1f8b480e70 | ||
|
|
3861af50d1 | ||
|
|
7652fb25f0 | ||
|
|
9b10164eac | ||
|
|
ce1061c2fb | ||
|
|
576e50552b | ||
|
|
901cc7d635 | ||
|
|
6b7834876f | ||
|
|
474b0eb0d7 | ||
|
|
181196149a | ||
|
|
e0aaa7e366 | ||
|
|
a0a8cceda4 | ||
|
|
679c99e465 | ||
|
|
051d3384c5 | ||
|
|
460d5e0f9b | ||
|
|
aed604ddc0 | ||
|
|
8d7e9cc0e3 | ||
|
|
a7c008b546 | ||
|
|
e64ef5c781 | ||
|
|
a2bac6b299 | ||
|
|
92165cb9ed | ||
|
|
f9faa0415f | ||
|
|
4549cbf1ed | ||
|
|
d5bc1dc4b3 | ||
|
|
718c25b2b8 | ||
|
|
a9953b3f91 | ||
|
|
cb6e1e3e59 | ||
|
|
15f9a84060 | ||
|
|
671577e35e | ||
|
|
75e6e46fb6 | ||
|
|
d1a82af43c | ||
|
|
3017770954 | ||
|
|
5e71fdf1cc | ||
|
|
9978fa73e1 | ||
|
|
6f9abaaffe | ||
|
|
9ca70a7946 | ||
|
|
175541ed86 | ||
|
|
868947f4c8 | ||
|
|
c900eb7951 | ||
|
|
10d27b8f68 | ||
|
|
b350613770 | ||
|
|
ed53f4b756 | ||
|
|
f54becf32e | ||
|
|
e3c80ac6a0 | ||
|
|
e6c9d912f1 | ||
|
|
78d59f65df | ||
|
|
ab814c361a | ||
|
|
2065a60b79 | ||
|
|
0d68ac9660 | ||
|
|
f5247cff0d | ||
|
|
ceb60f5ccc | ||
|
|
3fbe0d62ac | ||
|
|
da0e1763a7 | ||
|
|
5df708d34f | ||
|
|
f8970b92de | ||
|
|
182bfb9a38 | ||
|
|
dba666b990 | ||
|
|
4b45b8780d | ||
|
|
d54f5e516f | ||
|
|
f53ce16b8b | ||
|
|
a80a9a1598 | ||
|
|
0c9200c862 | ||
|
|
06eb1d7341 | ||
|
|
3d0b5d0099 | ||
|
|
365d6f4295 | ||
|
|
aef0e51186 | ||
|
|
2a0d245018 | ||
|
|
cff7e45d90 | ||
|
|
58234a133a | ||
|
|
04dbe51280 | ||
|
|
cd6c5cd30d | ||
|
|
d2d4bd8fe5 | ||
|
|
6cc03f79f3 | ||
|
|
f8fe506a86 | ||
|
|
db34491dfd | ||
|
|
cc10987dee | ||
|
|
d6c78336da | ||
|
|
5dc17be46c | ||
|
|
2e24e046e2 | ||
|
|
1f26b64519 | ||
|
|
0f866d6d33 | ||
|
|
596703b21b | ||
|
|
ca9508ebce | ||
|
|
ec7ffa8c0e | ||
|
|
a83852367f | ||
|
|
874f42df36 | ||
|
|
f0d453187d | ||
|
|
64238d56bc | ||
|
|
4f1e44978e | ||
|
|
ca83e4303c | ||
|
|
f5af1898fd | ||
|
|
531e8697be | ||
|
|
ec50539e80 | ||
|
|
53ad856ef4 | ||
|
|
ed311cacb9 | ||
|
|
5d998a3b37 | ||
|
|
0530afd669 | ||
|
|
d879c507a5 | ||
|
|
97650efe05 | ||
|
|
9b23755190 | ||
|
|
8c3f13909c | ||
|
|
a566d83411 | ||
|
|
d5deb406d7 | ||
|
|
16bb95ad3f | ||
|
|
51fe17c13d | ||
|
|
181afb92ac | ||
|
|
98b3745a20 | ||
|
|
b1b06cedde | ||
|
|
b8b4bebfc5 | ||
|
|
6e155de3e1 | ||
|
|
b564924c7c | ||
|
|
041d190286 | ||
|
|
b3589e1d89 | ||
|
|
a7eb49162e | ||
|
|
69b4789c17 | ||
|
|
b7bfdd5f7c | ||
|
|
f55d5c1067 | ||
|
|
5d54b4d37d | ||
|
|
4816eed0f4 | ||
|
|
c8fbad4be7 | ||
|
|
794dc6bf01 | ||
|
|
2d32efbccd | ||
|
|
9dd3807683 | ||
|
|
7450622047 | ||
|
|
19dad92b92 | ||
|
|
083ad9ee05 | ||
|
|
7f21da9334 | ||
|
|
6f6444dc12 | ||
|
|
01f9222735 | ||
|
|
4c32317ba4 | ||
|
|
35da1187b3 | ||
|
|
531f55120c | ||
|
|
14ab0cd529 | ||
|
|
214a668286 | ||
|
|
4bdbc1a2fe | ||
|
|
d869d7898e | ||
|
|
b72bcc3118 | ||
|
|
55017926b5 | ||
|
|
206496332d | ||
|
|
24aed7d530 | ||
|
|
c1f681a228 | ||
|
|
151218e4de | ||
|
|
79a3cbd182 | ||
|
|
2ac677e848 | ||
|
|
0cac4f5c86 | ||
|
|
46813ff9ed | ||
|
|
0352fa35b4 | ||
|
|
802210a6bc | ||
|
|
d446fc3c6f | ||
|
|
36e499c259 | ||
|
|
129938c8fe | ||
|
|
c5027106c2 | ||
|
|
256efd3195 | ||
|
|
e307b5e4d8 | ||
|
|
4e889934b9 | ||
|
|
71d2cbd66a | ||
|
|
b4f6c050e5 | ||
|
|
17c0aa9ef3 | ||
|
|
833b85d33a | ||
|
|
30cb2e1721 | ||
|
|
8209ee6279 | ||
|
|
aa19153ebc | ||
|
|
144f2caed8 | ||
|
|
11a5853657 | ||
|
|
e40cf686bc | ||
|
|
56bcd8e69c | ||
|
|
1ca243fa8c | ||
|
|
41031bc995 | ||
|
|
6cb6dd3bb5 | ||
|
|
aab90527ec | ||
|
|
61d6ef8d3d | ||
|
|
687399d9b0 | ||
|
|
f93718d0af | ||
|
|
9a9f11c5e3 | ||
|
|
7c3d04e03a | ||
|
|
41fe1e4aea | ||
|
|
255de649ca | ||
|
|
804b2d1216 | ||
|
|
374dab2cb4 | ||
|
|
93c4fd346f | ||
|
|
98d1f84263 | ||
|
|
ed983484d1 | ||
|
|
072cf33de2 | ||
|
|
3d85eb663c | ||
|
|
fd232e8ac5 | ||
|
|
dd1601793c | ||
|
|
06f359df23 | ||
|
|
99a2b83cb6 | ||
|
|
15fa86410d | ||
|
|
fbcadd06ba | ||
|
|
74b86a7033 | ||
|
|
c7757131a6 | ||
|
|
6530ccd101 | ||
|
|
a538a5588e | ||
|
|
1d5971c48f | ||
|
|
73a317b8d8 | ||
|
|
c836fb3448 | ||
|
|
fadcdcaef9 | ||
|
|
80cc971251 | ||
|
|
ba7ab0c262 | ||
|
|
8df6661f7e | ||
|
|
9d8845b961 | ||
|
|
1573d251e0 | ||
|
|
9a2d6fd8c0 | ||
|
|
10c3459a70 | ||
|
|
3d0014f258 | ||
|
|
75cb9d44bd | ||
|
|
5f717d3bde | ||
|
|
1cdb364361 | ||
|
|
00ae8bb9b2 | ||
|
|
29f4aece24 | ||
|
|
4187819cd1 | ||
|
|
4653059536 | ||
|
|
8b67fbcdce | ||
|
|
6a99fb673a | ||
|
|
629c5ecab2 | ||
|
|
7020d60351 | ||
|
|
297af9b409 | ||
|
|
99df46cbbb | ||
|
|
a92521bd30 | ||
|
|
8c5d4c7cd5 | ||
|
|
b71547469f | ||
|
|
2917f41cb9 | ||
|
|
7c7d8c1433 | ||
|
|
1463b58b5b | ||
|
|
dbc8b9bfed | ||
|
|
bf59645133 | ||
|
|
8076c97900 | ||
|
|
2d8bcce314 | ||
|
|
9b38d3a02f | ||
|
|
352647a068 | ||
|
|
cf389ff20f | ||
|
|
0f777efbf6 | ||
|
|
4bd46821de | ||
|
|
ef2cceba7e | ||
|
|
9a43e8f057 | ||
|
|
10adea71fc | ||
|
|
32f7919952 | ||
|
|
d825b51db6 | ||
|
|
0944f3bdc6 | ||
|
|
c2575d2a14 | ||
|
|
74ec6620e3 | ||
|
|
c5c613c82c | ||
|
|
846279da01 | ||
|
|
8a075dce9e | ||
|
|
1d0cdf4df0 | ||
|
|
3b1cb2b9c2 | ||
|
|
9446f7f583 | ||
|
|
7e01a7d0ec | ||
|
|
d16ea8fe15 | ||
|
|
e20e62d4f7 | ||
|
|
934a74fba4 | ||
|
|
34eb8205d1 | ||
|
|
532ae729c0 | ||
|
|
10fecce381 | ||
|
|
691d26886f | ||
|
|
6969ce394c | ||
|
|
b04f2c8ccb | ||
|
|
53fed83e05 | ||
|
|
38391f356c | ||
|
|
192ea54de0 | ||
|
|
e6b5ba60dd | ||
|
|
40fd5efe05 | ||
|
|
a46f1bcbbb | ||
|
|
220bb43830 | ||
|
|
ed1f3853b4 | ||
|
|
16a5b5b6bc | ||
|
|
a73035c848 | ||
|
|
f227aeb6e0 | ||
|
|
25d0cf66bd | ||
|
|
abad33116b | ||
|
|
06741ceb62 | ||
|
|
d949748945 | ||
|
|
26f7c707ba | ||
|
|
833ecca364 | ||
|
|
ac1cb29c69 | ||
|
|
b16bbc4a8a | ||
|
|
174bde7451 | ||
|
|
f79dab8f3e | ||
|
|
c0f6671542 | ||
|
|
f387c67fbc | ||
|
|
c3e927e52f | ||
|
|
0ea3d232f0 | ||
|
|
40a9ebc225 | ||
|
|
260709969e | ||
|
|
9cb7e7bb92 | ||
|
|
843300c62d | ||
|
|
80b5486991 | ||
|
|
8f9d5e190e | ||
|
|
a07117c938 | ||
|
|
657d5c4c42 | ||
|
|
0b3eda5d82 | ||
|
|
d90f655513 | ||
|
|
5d67514705 | ||
|
|
9ea56705a0 | ||
|
|
327206f931 | ||
|
|
13496afeb3 | ||
|
|
2f1aa19ae5 | ||
|
|
fd93af8305 | ||
|
|
37991e220e | ||
|
|
af4bbd2c4d | ||
|
|
4e0c89b352 | ||
|
|
6eea3704a9 | ||
|
|
a334d9fdd8 | ||
|
|
c05d43fa8e | ||
|
|
38764efb5a | ||
|
|
3e6cc03e2e | ||
|
|
0f5fc2962a | ||
|
|
ddfe376900 | ||
|
|
043c6e1795 | ||
|
|
ea2d4417e1 | ||
|
|
b0fa4415ee | ||
|
|
32b92c0205 | ||
|
|
8cb93b35a4 | ||
|
|
b899fc9d46 | ||
|
|
287ab3296d | ||
|
|
5c08e07bf5 | ||
|
|
da1599ca34 | ||
|
|
af1a4941ce | ||
|
|
e4f75c36e1 | ||
|
|
f79a59f56a | ||
|
|
006c6e890a | ||
|
|
2d3375e9f6 | ||
|
|
58c445b616 | ||
|
|
c2b51c7dfe | ||
|
|
a80c4c46bd | ||
|
|
5444e4ec4d | ||
|
|
d2f5d1f47b | ||
|
|
4f780424e8 | ||
|
|
72dd5128fb | ||
|
|
19d4c8e038 | ||
|
|
2b5e116717 | ||
|
|
21203501a9 | ||
|
|
73bc0cbb94 | ||
|
|
d9790b707a | ||
|
|
eeece86b4e | ||
|
|
8622ef6fe6 | ||
|
|
95b27f6f85 | ||
|
|
2401a34031 | ||
|
|
680a175a32 | ||
|
|
2849913d1b | ||
|
|
ee0df08cfb | ||
|
|
595eeeff6d | ||
|
|
3e6cfaf9ac | ||
|
|
4619949678 | ||
|
|
54721652b3 | ||
|
|
694ccecf4a | ||
|
|
2ae25e6d7a | ||
|
|
668c84fed5 | ||
|
|
f6a0ea6282 | ||
|
|
63615f1f09 | ||
|
|
5f47a3d41d | ||
|
|
931d89468f | ||
|
|
222125c1a2 | ||
|
|
e7d2a9a7d6 | ||
|
|
8211934d97 | ||
|
|
c44015671a | ||
|
|
ef89b2df7a | ||
|
|
ea5194f206 | ||
|
|
27b439a052 | ||
|
|
92bb6b3403 | ||
|
|
d96938f6cd | ||
|
|
2d1b8a21db | ||
|
|
cd5df6b2c0 | ||
|
|
3a59a68779 | ||
|
|
1bb7862114 | ||
|
|
390b65f2ab | ||
|
|
76caebdd8a | ||
|
|
4866c467dc | ||
|
|
ecd6c66750 | ||
|
|
d73a6f8a11 | ||
|
|
3df1a9b812 | ||
|
|
d8eae4cd3b | ||
|
|
a054831a3a | ||
|
|
7dc68209a5 | ||
|
|
29fa2f7073 | ||
|
|
cc3bdb59c1 | ||
|
|
16ae145d6c | ||
|
|
c270069639 | ||
|
|
2dfb243924 | ||
|
|
df8a4799e1 | ||
|
|
78507161df | ||
|
|
c7d816783b | ||
|
|
6942506eba | ||
|
|
20e9f20580 | ||
|
|
5a6b1a9f76 | ||
|
|
7f372fdd42 | ||
|
|
87f7a6a7bd | ||
|
|
d5bb667fb3 | ||
|
|
f6b47987e9 | ||
|
|
4eb4741795 | ||
|
|
10b248d68d | ||
|
|
c52ca2ee32 | ||
|
|
a2dc0f7e37 | ||
|
|
ce0b364571 | ||
|
|
0861710245 | ||
|
|
38b0b3a69a | ||
|
|
4ca92adb89 | ||
|
|
ca5ea08e2b | ||
|
|
cd43e95b85 | ||
|
|
9c519948bc | ||
|
|
a9c5c1bfa5 | ||
|
|
621435be68 | ||
|
|
173f4c491e | ||
|
|
09aad7b075 | ||
|
|
6dfd8965f1 | ||
|
|
aaac18ced6 | ||
|
|
42d4064bac | ||
|
|
6757c586ea | ||
|
|
764e75a39a | ||
|
|
c61892e4b6 | ||
|
|
c384fef867 | ||
|
|
a612c1227e | ||
|
|
b9f0d26cee | ||
|
|
3c6625f3cf | ||
|
|
b78938e773 | ||
|
|
6b5b47a83a | ||
|
|
bb3d9ccf8f | ||
|
|
3231e24bd5 | ||
|
|
3f45def928 | ||
|
|
d188857e06 | ||
|
|
936044b01f | ||
|
|
13812f46b4 | ||
|
|
24b5f2efb4 | ||
|
|
310e741a01 | ||
|
|
fad3e25278 | ||
|
|
ecfc217ce9 | ||
|
|
e00b754fce | ||
|
|
b7244998a1 | ||
|
|
f8a8f694b4 | ||
|
|
30890b322a | ||
|
|
8d8ffd52b5 | ||
|
|
06127d84da | ||
|
|
4d3b36efd3 | ||
|
|
e7e7e4d230 | ||
|
|
a532cfb475 | ||
|
|
f4d428cb16 | ||
|
|
338afc2b80 | ||
|
|
f829d7c43e | ||
|
|
f7d7625c1c | ||
|
|
e7ddf810c0 | ||
|
|
49d3bae256 | ||
|
|
137a1ddcc0 | ||
|
|
639b4b5623 | ||
|
|
dab423e857 | ||
|
|
2c74b0279d | ||
|
|
d2fda98bcb | ||
|
|
50e2250fe0 | ||
|
|
17539404b2 | ||
|
|
3aaf3432da | ||
|
|
9f4b15bbb7 | ||
|
|
d33a904207 | ||
|
|
6b79b5849e | ||
|
|
3363cb448a | ||
|
|
5d197e4b12 | ||
|
|
44d9530ecf | ||
|
|
fe47cbe805 | ||
|
|
88743682c3 | ||
|
|
f59a4da7f0 | ||
|
|
1d33b68761 | ||
|
|
569225897d | ||
|
|
b0e617e968 | ||
|
|
c0c00a00e7 | ||
|
|
50a037ecdc | ||
|
|
e3a831a68b | ||
|
|
98066b1bc5 | ||
|
|
85a15175ae | ||
|
|
249c5b8d12 | ||
|
|
7f84716c7e | ||
|
|
4af4212360 | ||
|
|
92206d30f6 | ||
|
|
be2ae2c1d7 | ||
|
|
e86458f11b | ||
|
|
5cc6631fd3 | ||
|
|
c826805bca | ||
|
|
88221d5fc7 | ||
|
|
4522704a77 | ||
|
|
d306fa9142 | ||
|
|
71f83c0a35 | ||
|
|
4e719e0d0c | ||
|
|
4f7b43747a | ||
|
|
f30d8f07d5 | ||
|
|
0f0fec0c64 | ||
|
|
a81701d7e7 | ||
|
|
5a45717270 | ||
|
|
70d52277b1 | ||
|
|
c07a13fcfe | ||
|
|
094b8157af | ||
|
|
1354371cc6 | ||
|
|
c9d60999d8 | ||
|
|
eca5f6bea1 | ||
|
|
56980080ad | ||
|
|
4d7c641f7b | ||
|
|
5539bd50ce | ||
|
|
94f061b0ec | ||
|
|
a6076ce76c | ||
|
|
845f11b1da | ||
|
|
8eedfd4a14 | ||
|
|
7eb4c1f6f6 | ||
|
|
fab20327a5 | ||
|
|
191d112aad | ||
|
|
b20926aa75 | ||
|
|
aa9198bafc | ||
|
|
43779b5e26 | ||
|
|
066eda7315 | ||
|
|
d6d9979f19 | ||
|
|
5c1f6d065d | ||
|
|
709281db02 | ||
|
|
e7c7367509 | ||
|
|
6ecfc7e34d | ||
|
|
79fa160e43 | ||
|
|
c4dbf19446 | ||
|
|
6b4cac1fb5 | ||
|
|
5ebd6c4141 | ||
|
|
4a9ce6b82b | ||
|
|
14a0a8ab24 | ||
|
|
08ffa64abf | ||
|
|
e96426d18c | ||
|
|
97c37de7f7 | ||
|
|
24ca4e44fa | ||
|
|
4067514a7e | ||
|
|
044e228a49 | ||
|
|
7056513b77 | ||
|
|
08706332f9 | ||
|
|
81edd1ee1c | ||
|
|
a7ae98c4c8 | ||
|
|
fe3dae2d15 | ||
|
|
a3857cb5e0 | ||
|
|
a15e185318 | ||
|
|
c8cf38cdf1 | ||
|
|
17255e4f5b | ||
|
|
f906fee819 | ||
|
|
bbde79818f | ||
|
|
2776d21ba0 | ||
|
|
b68957debe | ||
|
|
81954d74d1 | ||
|
|
3176516b79 | ||
|
|
92bb96ac49 | ||
|
|
e20b02c124 | ||
|
|
9325f773cc | ||
|
|
721f54fe49 | ||
|
|
debe5590f2 | ||
|
|
59afef6c2e | ||
|
|
101e6d55d5 | ||
|
|
d24b923542 | ||
|
|
6d71b2f6e4 | ||
|
|
d5cbb0fa03 | ||
|
|
9de70613a8 | ||
|
|
2071a7c4cf | ||
|
|
fe01113935 | ||
|
|
c6799bc3c2 | ||
|
|
1394381257 | ||
|
|
03be938444 | ||
|
|
eed7acff08 | ||
|
|
7fa7cf310e | ||
|
|
1f322cddb8 | ||
|
|
14c6d26f20 | ||
|
|
47bf4de08a | ||
|
|
90634fc5c8 | ||
|
|
bc64f06352 | ||
|
|
f9dc083771 | ||
|
|
95d5a54174 | ||
|
|
a3b1558f00 | ||
|
|
cd0ec45dc8 | ||
|
|
126d12905b | ||
|
|
f6ee160186 | ||
|
|
b4c5c5d539 | ||
|
|
c7159a5fa6 | ||
|
|
5be5ca9416 | ||
|
|
834ee0ff6c | ||
|
|
1bf0fd7d57 | ||
|
|
1e990f3ca0 | ||
|
|
f1d8a1c289 | ||
|
|
bc47ee46c8 | ||
|
|
9a23031c12 | ||
|
|
1e3ebc082e | ||
|
|
4fc8850f1e | ||
|
|
8b083aa426 | ||
|
|
91c0c28b5d | ||
|
|
07e8f0a01d | ||
|
|
0c8d3f0829 | ||
|
|
c47617c809 | ||
|
|
e1f1003318 | ||
|
|
bb146328b8 | ||
|
|
8f065d9f1f | ||
|
|
f0c578effa | ||
|
|
099c8e9958 | ||
|
|
c94c0bae8f | ||
|
|
9eabc169c4 | ||
|
|
7091fa3a58 | ||
|
|
31616af2af | ||
|
|
5dae581ad3 | ||
|
|
9783cc57c4 | ||
|
|
be1c890051 | ||
|
|
c01b3ae270 | ||
|
|
ffef57eed1 | ||
|
|
59b1d75b98 | ||
|
|
8278140492 | ||
|
|
85f58cc97d | ||
|
|
8f2bf50cec | ||
|
|
9ab42c5c65 | ||
|
|
634e27c621 | ||
|
|
19ab6b6643 | ||
|
|
387210e139 | ||
|
|
655575eb77 | ||
|
|
f1cf1b1a2b | ||
|
|
bd9048861c | ||
|
|
de9e7ff962 | ||
|
|
14ea68c819 | ||
|
|
e414e6029b | ||
|
|
5f8ea3af9c | ||
|
|
9b7d3edbb3 | ||
|
|
0cd868ec87 | ||
|
|
8e7d9927ef | ||
|
|
120d4cfacd | ||
|
|
a473002663 | ||
|
|
7f993a1528 | ||
|
|
13c96c6520 | ||
|
|
7e225c4517 | ||
|
|
e7b792e2d5 | ||
|
|
82107beaa9 | ||
|
|
99d977be3f | ||
|
|
4a0bb2df52 | ||
|
|
debcb9944d | ||
|
|
04748ec9a6 | ||
|
|
729b5a2082 | ||
|
|
adaa61f2cf | ||
|
|
9f453b55ad | ||
|
|
fa647459ac | ||
|
|
63012a816f | ||
|
|
638efad3eb | ||
|
|
d5194f234d | ||
|
|
a5acf02264 | ||
|
|
6db62c6705 | ||
|
|
dc06c699ec | ||
|
|
da1eb6fda9 | ||
|
|
4fe7d6fa0e | ||
|
|
c32a352ecc | ||
|
|
302d8e925e | ||
|
|
472ee72093 | ||
|
|
b9a93faabb | ||
|
|
1626ecf48e | ||
|
|
54382475be | ||
|
|
3ec1a64a6b | ||
|
|
81ed1f6ebb | ||
|
|
41726fef84 | ||
|
|
53f685ca76 | ||
|
|
7afbdd2150 | ||
|
|
a5393ca0e5 | ||
|
|
1c05dafedd | ||
|
|
f609578250 | ||
|
|
627f840c4b | ||
|
|
3a7145f4d5 | ||
|
|
fbfe4b2dfa | ||
|
|
12b6645a1f | ||
|
|
0077c3f07a | ||
|
|
19f0e9369a | ||
|
|
60fd0829b0 | ||
|
|
784ccdd996 | ||
|
|
d815476a14 | ||
|
|
fde33e7100 | ||
|
|
5d760c9304 | ||
|
|
25b9c677e3 | ||
|
|
91054acfea | ||
|
|
5d580f049a | ||
|
|
704d90cd83 | ||
|
|
9ffb430207 | ||
|
|
8b13f717b4 | ||
|
|
c9fc68658b | ||
|
|
e516fc8354 | ||
|
|
a7b5648733 | ||
|
|
ad1cfa7c98 | ||
|
|
91104ebe46 | ||
|
|
3e30ae1797 | ||
|
|
dfaa0ce129 | ||
|
|
1dbbb708a7 | ||
|
|
76a9b58914 | ||
|
|
6d93ab1e71 | ||
|
|
5d263e2f4c | ||
|
|
07de63be35 | ||
|
|
402538457e | ||
|
|
ff3c249b6d | ||
|
|
9d49d4623d | ||
|
|
5bef61b748 | ||
|
|
f7dc68c7f4 | ||
|
|
2835d6fe83 | ||
|
|
816aaca380 | ||
|
|
451cb8109a | ||
|
|
e2b72944be | ||
|
|
80ac628d98 | ||
|
|
e2970f242c | ||
|
|
4fe0ebc63b | ||
|
|
c9561f1041 | ||
|
|
76b7f4be4f | ||
|
|
363f97325f | ||
|
|
d4905854eb | ||
|
|
687ba53afd | ||
|
|
86ee56cfac | ||
|
|
cdacc42fd2 | ||
|
|
df014bfb0b | ||
|
|
c6e5850e1c | ||
|
|
c7c3784413 | ||
|
|
2e8073ab9d | ||
|
|
fc648a949a | ||
|
|
860e2ce7ca | ||
|
|
210d815173 | ||
|
|
c31c091cb0 | ||
|
|
d236058351 | ||
|
|
45fbf8bb12 | ||
|
|
c031e1fbbd | ||
|
|
b029e561f3 | ||
|
|
ba32c764a2 | ||
|
|
b3b0f04214 | ||
|
|
b814d0f4c8 | ||
|
|
68596148b0 | ||
|
|
9421e09e84 | ||
|
|
4432f88f1d | ||
|
|
91bc1a3e2d | ||
|
|
7f573d7717 | ||
|
|
f7a3f80d43 | ||
|
|
117197e11d | ||
|
|
5263c79ea8 | ||
|
|
35f5b19ffd | ||
|
|
5099da355c | ||
|
|
6ebb15778b | ||
|
|
14586d72b0 | ||
|
|
5681954f39 | ||
|
|
b44757ad3c | ||
|
|
80357b1938 | ||
|
|
bef389e110 | ||
|
|
df3b9fa425 | ||
|
|
70d999291b | ||
|
|
398454f85b | ||
|
|
878fc20cec | ||
|
|
7f492529a8 | ||
|
|
d21fc40115 | ||
|
|
914a8d8956 | ||
|
|
02a48c5a84 | ||
|
|
1951c95e6b | ||
|
|
fcc366abe2 | ||
|
|
61db9ff0cc | ||
|
|
1811c77f85 | ||
|
|
b17d1429bf | ||
|
|
128a540af6 | ||
|
|
0da1702589 | ||
|
|
81eb0b51bc | ||
|
|
ecea550a37 | ||
|
|
49923780ca | ||
|
|
8b37a9889a | ||
|
|
03d0ea4366 | ||
|
|
d654daae28 | ||
|
|
56c3635214 | ||
|
|
591132a2d9 | ||
|
|
db19e52547 | ||
|
|
38dc364f57 | ||
|
|
b443508b2f | ||
|
|
91cd9814e1 | ||
|
|
66fa9fdc51 | ||
|
|
86bb8f06cb | ||
|
|
8b30f08db8 | ||
|
|
13754fe32c | ||
|
|
b3d07a5ddf | ||
|
|
a9e57541cf | ||
|
|
bcf8d72b0b | ||
|
|
78c0a3d050 | ||
|
|
20d6cde85f | ||
|
|
c6256402e4 | ||
|
|
1201cc5eb6 | ||
|
|
77f3be2bda | ||
|
|
b9de90c485 | ||
|
|
4d05367f1d | ||
|
|
808fe9b665 | ||
|
|
6f8a109574 | ||
|
|
9e5831a0bf | ||
|
|
5f076dfeea | ||
|
|
09eb9b4e77 | ||
|
|
e8df3c29dd | ||
|
|
34d857d310 | ||
|
|
9df39c941b | ||
|
|
1f5aca9c31 | ||
|
|
124b64f3a2 | ||
|
|
ad661e9c8d | ||
|
|
5242851421 | ||
|
|
0f6cae891d | ||
|
|
009f2a5607 | ||
|
|
0b04a518e7 | ||
|
|
db5db03c9c | ||
|
|
423393c78b | ||
|
|
35aaa013ed | ||
|
|
c16f5d1524 | ||
|
|
38287cec07 | ||
|
|
29c0460930 | ||
|
|
a78d1c3876 | ||
|
|
669574b484 | ||
|
|
ff28541245 | ||
|
|
2a114cef9b | ||
|
|
751457268b | ||
|
|
ee6b9d7af7 | ||
|
|
db499fdf2b | ||
|
|
7bf0aa4958 | ||
|
|
8bf8bfe804 | ||
|
|
eeefd1cc0d | ||
|
|
72168a27ec | ||
|
|
5d150958de | ||
|
|
982d087987 | ||
|
|
95f6d2aa72 | ||
|
|
e1411982b2 | ||
|
|
f86d1e1d07 | ||
|
|
a45be190ea | ||
|
|
b9aced95c3 | ||
|
|
26bfe3dbdc | ||
|
|
38e4fea455 | ||
|
|
0d9a34ba28 | ||
|
|
4ece2fdd19 | ||
|
|
1ae4d12a39 | ||
|
|
56e02b3cad | ||
|
|
5b1f2f4f90 | ||
|
|
4e912b84c0 | ||
|
|
1b646fb6e2 | ||
|
|
0f61646e26 | ||
|
|
4407c24329 | ||
|
|
849ffe0133 | ||
|
|
2ec6c7c72e | ||
|
|
8cd2c41e25 | ||
|
|
89320a7ee4 | ||
|
|
98ed686212 | ||
|
|
61ef16b9b7 | ||
|
|
2f4a232c41 | ||
|
|
a92358bdd1 | ||
|
|
d56181622e | ||
|
|
75aade6422 | ||
|
|
dca7dcccab | ||
|
|
7276b8c50d | ||
|
|
d57df7b583 | ||
|
|
7ea2709116 | ||
|
|
c133fcb8e4 | ||
|
|
e51739e1d4 | ||
|
|
f7ac2a348f | ||
|
|
0e14c9b3b3 | ||
|
|
9d5a706344 | ||
|
|
a110e86cff | ||
|
|
bda096a26f | ||
|
|
42724d13f7 | ||
|
|
64489b243f | ||
|
|
41acf4c737 | ||
|
|
b34859d882 | ||
|
|
b2ad17d604 | ||
|
|
827bcd704d | ||
|
|
b42e412c4f | ||
|
|
cd3fda98d1 | ||
|
|
349ae52b9c | ||
|
|
8cb0c58b60 | ||
|
|
506482551d | ||
|
|
2f49999a0f | ||
|
|
07b2e1d310 | ||
|
|
1b12b66e48 | ||
|
|
cd5a9852d5 | ||
|
|
9be7337112 | ||
|
|
2d3bc12ca0 | ||
|
|
48858fe07f | ||
|
|
5f37ae4ab1 | ||
|
|
87297f8d29 | ||
|
|
f4a33cc2e1 | ||
|
|
62e8e97e7c | ||
|
|
dd745ed1aa | ||
|
|
28f4857592 | ||
|
|
c8d49e76e5 | ||
|
|
d8919d29f7 | ||
|
|
fcb96c775e | ||
|
|
990e740afb | ||
|
|
6854ad814b | ||
|
|
5ca626c143 | ||
|
|
de42dce16e | ||
|
|
0c5479f033 | ||
|
|
5730bf690e | ||
|
|
03d414f3bd | ||
|
|
32793b80ae | ||
|
|
f38506bccb | ||
|
|
65a7bf7fc0 | ||
|
|
92dfca2dc9 | ||
|
|
b6a597a7f9 | ||
|
|
ef75f59037 | ||
|
|
95caebde2b | ||
|
|
920461cd9d | ||
|
|
5a8a7ebccc | ||
|
|
33db3c28fc | ||
|
|
d026d9684f | ||
|
|
f472ee6a4c | ||
|
|
13ab3bd87f | ||
|
|
e76c6c6a1a | ||
|
|
c36f40735c | ||
|
|
95d577beb6 | ||
|
|
2051f08b4c | ||
|
|
c0aab70e03 | ||
|
|
676c1d85aa | ||
|
|
1cd01e8dc0 | ||
|
|
45bd374530 | ||
|
|
0f8dce630d | ||
|
|
37a6df4ccb | ||
|
|
f9e25675f0 | ||
|
|
489cee6b24 | ||
|
|
63f54d3184 | ||
|
|
54b9ff6e8a | ||
|
|
4f0e9bb9bb | ||
|
|
abeef79a29 | ||
|
|
a7044db15e | ||
|
|
37ac6f9058 | ||
|
|
a0658b5ada | ||
|
|
65db66eb33 | ||
|
|
750f53aa53 | ||
|
|
bef7ecd409 | ||
|
|
ff96de8723 | ||
|
|
054a7526d3 | ||
|
|
19f4509075 | ||
|
|
0419c33e3d | ||
|
|
51d77d5699 | ||
|
|
4f5c1c90af | ||
|
|
a50b7ef04a | ||
|
|
aef07afd32 | ||
|
|
0e087c8441 | ||
|
|
cee1e3a596 | ||
|
|
6d02076a1c | ||
|
|
1eaff8110c | ||
|
|
3dc37183b4 | ||
|
|
f144f3a725 | ||
|
|
e5dd25fbd5 | ||
|
|
eb2ef8a2d1 | ||
|
|
e07ac555af | ||
|
|
95cfc4be13 | ||
|
|
f8d59d14bc | ||
|
|
8e5732cf9c | ||
|
|
e7f899c09d | ||
|
|
c31a40c749 | ||
|
|
5489b6cc4b | ||
|
|
844fd98c72 | ||
|
|
92a04fcffa | ||
|
|
e08c34b497 | ||
|
|
f0db826b72 | ||
|
|
edb9a06910 | ||
|
|
d2dc9dd3c0 | ||
|
|
16fa1ac893 | ||
|
|
d0299a1acc | ||
|
|
633bee45af | ||
|
|
af1aab3f0a | ||
|
|
0478e66a47 | ||
|
|
d688ebc10f | ||
|
|
ac196a5944 | ||
|
|
1ca23fedb2 | ||
|
|
ba86e9b4c9 | ||
|
|
23da0d70b0 | ||
|
|
337f54ac03 | ||
|
|
b047f3d903 | ||
|
|
ea63780600 | ||
|
|
9e78957c72 | ||
|
|
19b12b613b | ||
|
|
ae441c6db1 | ||
|
|
352f71e32e | ||
|
|
55c5fd2783 | ||
|
|
5e10e627c3 | ||
|
|
b8fa54ecce | ||
|
|
8f8c0d0795 | ||
|
|
cbe75f1de4 | ||
|
|
1a48e4d3f6 | ||
|
|
368e94fbb1 | ||
|
|
e1538d9f10 | ||
|
|
50331b9a04 | ||
|
|
ea1b18881c | ||
|
|
59fbdf6048 | ||
|
|
6327e55599 | ||
|
|
31fc4dc950 | ||
|
|
98fc32a65e | ||
|
|
f7cb5f89a7 | ||
|
|
3b30c5821a | ||
|
|
5f0e3d550b | ||
|
|
bbab56837e | ||
|
|
cb420fb570 | ||
|
|
0ace47f742 | ||
|
|
a443bc066f | ||
|
|
0007d077cc | ||
|
|
5dcaf65757 | ||
|
|
cffb5cdd4b | ||
|
|
52856ae696 | ||
|
|
6095ee91ff | ||
|
|
965149fe0f | ||
|
|
a7d59a90d3 | ||
|
|
b1333d0e9d | ||
|
|
ae8cbdf3b7 | ||
|
|
93536a1592 | ||
|
|
efd7ec6dc2 | ||
|
|
26fd57398c | ||
|
|
b15fb36f1b | ||
|
|
07296b4506 | ||
|
|
69d9b01b6e | ||
|
|
71a85e4d06 | ||
|
|
38a42d3c91 | ||
|
|
64b8c7b250 | ||
|
|
130a72af1b | ||
|
|
35a324b65b | ||
|
|
2918e5d1a4 | ||
|
|
c9b639b311 | ||
|
|
91e1c6ca30 | ||
|
|
1f599283df | ||
|
|
24cb38cfc8 | ||
|
|
826774b1f7 | ||
|
|
1b751d675b | ||
|
|
61d3c5c85c | ||
|
|
294835b995 | ||
|
|
5940b63908 | ||
|
|
009a2ca38a | ||
|
|
d47ed5f747 | ||
|
|
abe8def0f1 | ||
|
|
f548efde15 | ||
|
|
fbc82f687d | ||
|
|
ba5d34876e | ||
|
|
0dfe276d9b | ||
|
|
43d9d604a6 | ||
|
|
6dae7037e1 | ||
|
|
beb7b51cb3 | ||
|
|
34b389d118 | ||
|
|
f729172bdd | ||
|
|
872e7b2427 | ||
|
|
6a39980a97 | ||
|
|
0aea17581e | ||
|
|
d852185950 | ||
|
|
4a91df1b1d | ||
|
|
90282b3739 | ||
|
|
527fa5b12f | ||
|
|
bf17e5162e | ||
|
|
88482bd776 | ||
|
|
fc5aa1a6ba | ||
|
|
579106c3af | ||
|
|
2665090aa9 | ||
|
|
ceb1dd7da3 | ||
|
|
e69ce9b86c | ||
|
|
15d5dcaaee | ||
|
|
147ed028df | ||
|
|
5f5ceb9d87 | ||
|
|
4b3f61d8ca | ||
|
|
3a2cd70684 | ||
|
|
42a994cce1 | ||
|
|
de89e82e75 | ||
|
|
f29f87ad5b | ||
|
|
6486c509ad | ||
|
|
3acef799f5 | ||
|
|
a74c86d948 | ||
|
|
4a3a80b4f8 | ||
|
|
c10dabcbba | ||
|
|
6b1940cebb | ||
|
|
af79e9c405 | ||
|
|
b8c1b7c139 | ||
|
|
fa6e6f9458 | ||
|
|
a33603d496 | ||
|
|
7344b8bb46 | ||
|
|
9823b1199a | ||
|
|
41ccbc90a0 | ||
|
|
6efbf4c2ec | ||
|
|
aee38791a7 | ||
|
|
8bcf1d446a | ||
|
|
0985362829 | ||
|
|
8a9df4a1b3 | ||
|
|
3adc0ef814 | ||
|
|
ebd3d7a988 | ||
|
|
7094945dff | ||
|
|
493c3add8a | ||
|
|
f8108aca45 | ||
|
|
a4c09ed701 | ||
|
|
ab5def98a7 | ||
|
|
0e251b4975 | ||
|
|
7944253bed | ||
|
|
3f348e3340 | ||
|
|
a4c75df182 | ||
|
|
a23b5310e6 | ||
|
|
1375de4ba2 | ||
|
|
a12c032ab9 | ||
|
|
b3cf2ac67e | ||
|
|
83491c14bb | ||
|
|
9edfcba9a9 | ||
|
|
e68b9b80ad | ||
|
|
41294e0ff7 | ||
|
|
418ec5cfc0 | ||
|
|
b534639d4e | ||
|
|
630eccf72f | ||
|
|
3a3a81b0ed | ||
|
|
d606644a78 | ||
|
|
5eb0ed109b | ||
|
|
0045cd1b7a | ||
|
|
452ee3a55b | ||
|
|
ee9e11a3eb | ||
|
|
6eebbe32f4 | ||
|
|
8275970df9 | ||
|
|
7f993167b4 | ||
|
|
00ca99ae86 | ||
|
|
1cc5c1ce2e | ||
|
|
25d9524c6a | ||
|
|
c21c5632c2 | ||
|
|
9151fb3558 | ||
|
|
f7fe38b94b | ||
|
|
d116d8d0b7 | ||
|
|
eb0988537e | ||
|
|
63c532398b | ||
|
|
665f812bd1 | ||
|
|
7fe01d6c03 | ||
|
|
f990cb3f4b | ||
|
|
69054bea4a | ||
|
|
1a82ae5c3b | ||
|
|
608b732fbb | ||
|
|
873c87956c | ||
|
|
a1134255ee | ||
|
|
2b50536775 | ||
|
|
c2cc5e1935 | ||
|
|
4f73ea0cfa | ||
|
|
3472d6cabe | ||
|
|
613a907f3e | ||
|
|
620b35ab78 | ||
|
|
ed8e3f142b | ||
|
|
580d1df086 | ||
|
|
3bdcf34a89 | ||
|
|
8aa77fd5c8 | ||
|
|
7f58873e0b | ||
|
|
f59ee25fd7 | ||
|
|
d375b1c78b | ||
|
|
1159f9b54c | ||
|
|
1d8baa635a | ||
|
|
ccfc3127ba | ||
|
|
61cca0fc69 | ||
|
|
11fc1ebd8e | ||
|
|
b8f2aaafa9 | ||
|
|
832a6f3eff | ||
|
|
0d0aee559b | ||
|
|
db4d7d5838 | ||
|
|
0cd7a52dc0 | ||
|
|
1c343ee820 | ||
|
|
86947d7154 | ||
|
|
6ac35a580f | ||
|
|
3ac8f803c9 | ||
|
|
a0ab7783ee | ||
|
|
b9deeb1b15 | ||
|
|
f468245caf | ||
|
|
c208325aeb | ||
|
|
c549a96834 | ||
|
|
03be35426c | ||
|
|
71d6e219bd | ||
|
|
ee514f2fd5 | ||
|
|
a8916b797e | ||
|
|
29bfbbf4f1 | ||
|
|
174e5cb5c9 | ||
|
|
6f466b25bd | ||
|
|
91876e4185 | ||
|
|
f084b8c8ad | ||
|
|
ac7cc34485 | ||
|
|
b66ac0d493 | ||
|
|
4a096665a0 | ||
|
|
be3d7c95f9 | ||
|
|
afcbc24362 | ||
|
|
05747f050a | ||
|
|
074f8b1c69 | ||
|
|
982289b484 | ||
|
|
2f9a12c2da | ||
|
|
a54ed665bf | ||
|
|
c514f92f9b | ||
|
|
d99ad84d4c | ||
|
|
f0de6d0d57 | ||
|
|
0734808774 | ||
|
|
7497226de2 | ||
|
|
701c76aa3f | ||
|
|
b30e975379 | ||
|
|
37d2b41778 | ||
|
|
40cc55757b | ||
|
|
63e492261d | ||
|
|
1d662b9fef | ||
|
|
6e651271e8 | ||
|
|
fbbe9625fc | ||
|
|
6948252e32 | ||
|
|
8e3abd8706 | ||
|
|
482e436203 | ||
|
|
b24d7d8f44 | ||
|
|
b391b6ca21 | ||
|
|
f2bf40a314 | ||
|
|
fbd8db3c8e | ||
|
|
99b0411857 | ||
|
|
301058cf9d | ||
|
|
57a1214eaa | ||
|
|
2624770cea | ||
|
|
49fe2b98d9 | ||
|
|
ac2a4d0ee3 | ||
|
|
e1f026b037 | ||
|
|
b2ce3d4a5c | ||
|
|
365e97ba1e | ||
|
|
3e489b5f00 | ||
|
|
0c089efd8a | ||
|
|
61a5704dd4 | ||
|
|
b34d0d2acc | ||
|
|
3b9afcc500 | ||
|
|
3338b4b285 | ||
|
|
b6d5a52417 | ||
|
|
1427e3e324 | ||
|
|
8e4fd75f1d | ||
|
|
3073137d39 | ||
|
|
99ab42a674 | ||
|
|
2c97a7a03e | ||
|
|
0f0badea27 | ||
|
|
6cb50c3ca4 | ||
|
|
e6dc493b27 | ||
|
|
c5346d08b9 | ||
|
|
6e7c80d97b | ||
|
|
a81f0884ed | ||
|
|
ee5106939c | ||
|
|
f039124312 | ||
|
|
d00fc7ca22 | ||
|
|
3603254d35 | ||
|
|
607f9814a0 | ||
|
|
034dd40eea | ||
|
|
6af4605bd0 | ||
|
|
2a5d713f98 | ||
|
|
9a0a15abbe | ||
|
|
f44cc548f9 | ||
|
|
424afb9af6 | ||
|
|
13acfe8c05 | ||
|
|
cf241447ab | ||
|
|
fc7f8b199e | ||
|
|
d06ad5c14a | ||
|
|
786a48c995 | ||
|
|
30b4577283 | ||
|
|
6ac6c2582d | ||
|
|
2963b86176 | ||
|
|
aa10c71dba | ||
|
|
58958d26f4 | ||
|
|
6836bde339 | ||
|
|
5ae6f88b15 | ||
|
|
f4d3ef94e7 | ||
|
|
2ab1bf6e11 | ||
|
|
ef1f64058e | ||
|
|
4490da93ca | ||
|
|
9960483527 | ||
|
|
667ea83f4b | ||
|
|
e4837168b9 | ||
|
|
761c8a1bd4 | ||
|
|
9a5a8cf107 | ||
|
|
f938445271 | ||
|
|
64b8068504 | ||
|
|
0d37d2752c | ||
|
|
ba19324723 | ||
|
|
5167ac2d6f | ||
|
|
0f4a9e1482 | ||
|
|
ecf1595998 | ||
|
|
b2e4c9bdeb | ||
|
|
1e793a37a8 | ||
|
|
d44b869420 | ||
|
|
5b1fd4b628 | ||
|
|
cae1bf3ab0 | ||
|
|
af97b3e66f | ||
|
|
d128329cfb | ||
|
|
bfec26f3cf | ||
|
|
1f3c65a504 | ||
|
|
741ed9b98c | ||
|
|
7d68f75d03 | ||
|
|
75b1747d1d | ||
|
|
784f877fbd | ||
|
|
15cfdb8317 | ||
|
|
6a855f5c8f | ||
|
|
8888fa6dcb | ||
|
|
318de52dc5 | ||
|
|
7df21ed14c | ||
|
|
a9eb79a45b | ||
|
|
d8a00610da | ||
|
|
ef062b9a8d | ||
|
|
8573cd785f | ||
|
|
7d1f58ce5e | ||
|
|
32bfc267a7 | ||
|
|
56cef1d504 | ||
|
|
90b3c2206b | ||
|
|
a9d30b7e8a | ||
|
|
743597bc47 | ||
|
|
8c0116d1db | ||
|
|
a2e8294389 | ||
|
|
87d344e5f8 | ||
|
|
bdc5f71990 | ||
|
|
7507e24998 | ||
|
|
7325642aa0 | ||
|
|
9f8e3f1521 | ||
|
|
691e5d8cc1 | ||
|
|
fca87eff9c | ||
|
|
ccdd6c08ba | ||
|
|
f0c9e42a8e | ||
|
|
9a07c8cb2e | ||
|
|
9892601153 | ||
|
|
d62c9e217b | ||
|
|
0facc521b2 | ||
|
|
b15313fc3e | ||
|
|
0f60207287 | ||
|
|
1b9f7424eb | ||
|
|
d85f04a408 | ||
|
|
13de06cd52 | ||
|
|
553d1f6b3c | ||
|
|
55b97cd397 | ||
|
|
527c30b8c1 | ||
|
|
a3dec4be45 | ||
|
|
b649a1a953 | ||
|
|
133fb3ad23 | ||
|
|
d021433979 | ||
|
|
583c6328a0 | ||
|
|
beaf03197e | ||
|
|
f9a2f2f3e0 | ||
|
|
fb26921e11 | ||
|
|
843d23bbd2 | ||
|
|
c6505d3e39 | ||
|
|
0b81fef457 | ||
|
|
e7e477fcdb | ||
|
|
1ce70262e1 | ||
|
|
695e7f7975 | ||
|
|
91ec79401d | ||
|
|
8b5047f992 | ||
|
|
16f66227bd | ||
|
|
b18a47b0d2 | ||
|
|
df80c7573a | ||
|
|
db5863fa0a | ||
|
|
55415607bb | ||
|
|
472593c400 | ||
|
|
c40807909d | ||
|
|
c8c3856214 | ||
|
|
a8016b1b2f | ||
|
|
7ca6a7a37b | ||
|
|
687a6c5091 | ||
|
|
f5f475f738 | ||
|
|
2a16c3c161 | ||
|
|
16cadf1de7 | ||
|
|
ba0475810c | ||
|
|
360f65e8c2 | ||
|
|
df0c2e2fd2 | ||
|
|
bd067df4f6 | ||
|
|
a2e034c921 | ||
|
|
f454e110ec | ||
|
|
632870683b | ||
|
|
e04ef87929 | ||
|
|
44ff2b1764 | ||
|
|
ce1bdba37a | ||
|
|
51b615c54c | ||
|
|
524560799f | ||
|
|
6724ff8378 | ||
|
|
c78739bf2f | ||
|
|
e4b329bffc | ||
|
|
c16a2d4b05 | ||
|
|
b2eed77914 | ||
|
|
c50a3a8615 | ||
|
|
dacfe68a28 | ||
|
|
ef608c094a | ||
|
|
9b80d9def5 | ||
|
|
4a15b2633a | ||
|
|
a8a1b8fe06 | ||
|
|
19b78e2b20 | ||
|
|
cc9d58e6be | ||
|
|
97996310ea | ||
|
|
663c1e62fd | ||
|
|
f67efc90f1 | ||
|
|
8627e92cb4 | ||
|
|
cec0592e14 | ||
|
|
82a9aee21c | ||
|
|
f5be1b26f4 | ||
|
|
60dedf7d95 | ||
|
|
bf72c9d828 | ||
|
|
374b5337d8 | ||
|
|
d16abb1a15 | ||
|
|
077214a327 | ||
|
|
a7fe2130ce | ||
|
|
f8a6b82c63 | ||
|
|
7da00957ef | ||
|
|
464c37e66f | ||
|
|
7fe5f0145d | ||
|
|
9ff76d2dd9 | ||
|
|
ff115b0873 | ||
|
|
ce64147aa8 | ||
|
|
54ce9e8b3c | ||
|
|
a68424658a | ||
|
|
fe6fdd3ff6 | ||
|
|
71af85adb3 | ||
|
|
6bc97a6af6 | ||
|
|
17f758d0cf | ||
|
|
810402c9c7 | ||
|
|
d2694bfba7 | ||
|
|
a2f259d14c | ||
|
|
200e1d7564 | ||
|
|
3f91729141 | ||
|
|
78d82d22cc | ||
|
|
8b9d8b1be5 | ||
|
|
c6ad31ca0a | ||
|
|
c7286194f8 | ||
|
|
03d10f7de7 | ||
|
|
61f9d65552 | ||
|
|
1dd3812e00 | ||
|
|
d6e5da403c | ||
|
|
be4ecb31bc | ||
|
|
c3d45a8a29 | ||
|
|
5c337808ab | ||
|
|
a37dd2462a | ||
|
|
ac7eb87632 | ||
|
|
21e50add60 | ||
|
|
7811d78cb0 | ||
|
|
4d7ad51593 | ||
|
|
9a6b35b962 | ||
|
|
b03dbee3e8 | ||
|
|
8b7c0433e8 | ||
|
|
80abafbe5b | ||
|
|
6b996d4f99 | ||
|
|
071bf06995 | ||
|
|
03432718e3 | ||
|
|
8b77c96e97 | ||
|
|
c9b4daf152 | ||
|
|
5536f8d2bd | ||
|
|
b31f66ddbd | ||
|
|
3cb12a2ad3 | ||
|
|
32ba987c28 | ||
|
|
8243553260 | ||
|
|
172fe371dd | ||
|
|
f4284a3579 | ||
|
|
969031a374 | ||
|
|
9971f15e61 | ||
|
|
5a0f369f0b | ||
|
|
8a66fc02fe | ||
|
|
0f447c87dc | ||
|
|
8a620c3a7c | ||
|
|
2f8e536f2b | ||
|
|
daa98de2cc | ||
|
|
6254c3fbdd | ||
|
|
04b87e4db7 | ||
|
|
52c219c8b9 | ||
|
|
3eb1c3fb4f | ||
|
|
58c6bdf504 | ||
|
|
436b19d64c | ||
|
|
9d710ea135 | ||
|
|
7027c08f1a | ||
|
|
2c50749ab3 | ||
|
|
de9abdae39 | ||
|
|
6f6b4152f3 | ||
|
|
94070e1b7c | ||
|
|
7c5600913b | ||
|
|
cdc59e6a29 | ||
|
|
835542bb6f | ||
|
|
feac973ec2 | ||
|
|
38081fa4b8 | ||
|
|
b6d8571860 | ||
|
|
f1373652e6 | ||
|
|
8239d04d5e | ||
|
|
5efd181e5b | ||
|
|
1bb6722c4c | ||
|
|
0cab24fb89 | ||
|
|
52a394374f | ||
|
|
bf478392ce | ||
|
|
f1203f0fb3 | ||
|
|
47e55286f7 | ||
|
|
4266df4d3a | ||
|
|
ec464a048a | ||
|
|
b71012689f | ||
|
|
fe752fd937 | ||
|
|
011dabd372 | ||
|
|
3b9d0ac1bb | ||
|
|
f012a348af | ||
|
|
f94d6da876 | ||
|
|
7e82cc5ffd | ||
|
|
c27bac2ad6 | ||
|
|
fc088bc1f3 | ||
|
|
a1f6821fe1 | ||
|
|
64a78412c9 | ||
|
|
195ea69b19 | ||
|
|
5e634f57f0 | ||
|
|
03fcba3b71 | ||
|
|
f803c0cc4e | ||
|
|
918b1645aa | ||
|
|
e3c64fb047 | ||
|
|
2db19ad4ca | ||
|
|
aef49da233 | ||
|
|
bbfc6ed817 | ||
|
|
79ef266f2f | ||
|
|
c45405190a | ||
|
|
399baf0d73 | ||
|
|
f28873382d | ||
|
|
9779c70915 | ||
|
|
220eba8c63 | ||
|
|
a8ccab78f5 | ||
|
|
f8c3a3a31e | ||
|
|
98c1a6ca1b | ||
|
|
540a174dab | ||
|
|
309e56df06 | ||
|
|
6740b2644d | ||
|
|
24ae341045 | ||
|
|
0b583cc644 | ||
|
|
189df44ec6 | ||
|
|
667f940a6c | ||
|
|
1b23838d37 | ||
|
|
0e5359d43e | ||
|
|
8d825f641a | ||
|
|
78fe68164f | ||
|
|
96652ea9e8 | ||
|
|
40b30f2b63 | ||
|
|
87286ca776 | ||
|
|
8d93fd4c8c | ||
|
|
f688183878 | ||
|
|
ad676adbbb | ||
|
|
b91ae86079 | ||
|
|
e1def9971c | ||
|
|
ecba25be0f | ||
|
|
647e45c115 | ||
|
|
b4c3c0c7f9 | ||
|
|
b918ad2892 | ||
|
|
794e89d307 | ||
|
|
b72894d874 | ||
|
|
ae1c8bd059 | ||
|
|
85cade3fb2 | ||
|
|
b79e0b3d71 | ||
|
|
6cd44f19fe | ||
|
|
075457be45 | ||
|
|
e3a6508134 | ||
|
|
bdea76024b | ||
|
|
1aa25964ba | ||
|
|
8f4cb5002a | ||
|
|
8125b62108 | ||
|
|
fe10897bda | ||
|
|
17aedbc5af | ||
|
|
30c70a6ecd | ||
|
|
38d0750dd3 | ||
|
|
4f19b1d13e | ||
|
|
4dbd52782c | ||
|
|
3eef4284d1 | ||
|
|
b05ef8ed04 | ||
|
|
3ef1f09927 | ||
|
|
fb96cd595d | ||
|
|
17daf9fe8d | ||
|
|
7b26dab2f2 | ||
|
|
edcacfa92b | ||
|
|
367ecb66c3 | ||
|
|
437e2bd920 | ||
|
|
dcca56d6c3 | ||
|
|
9dd182e9ca | ||
|
|
c4eb9df716 | ||
|
|
69ba2310a2 | ||
|
|
5e27a75010 | ||
|
|
3b04c012b3 | ||
|
|
8f6af79280 | ||
|
|
e83a8dba0e | ||
|
|
879109336a | ||
|
|
838a3090fd | ||
|
|
4ac3128b17 | ||
|
|
f0e1da23bc | ||
|
|
ae8ed58383 | ||
|
|
1af3d702d3 | ||
|
|
5d2514b09f | ||
|
|
ed52c7d7ef | ||
|
|
278f2de7bd | ||
|
|
827edccfbd | ||
|
|
07e4d68760 | ||
|
|
a167b6932b | ||
|
|
7e481e3e5f | ||
|
|
38b9457ea9 | ||
|
|
caee5f29ca | ||
|
|
deb6acaab1 | ||
|
|
2ef560f7d8 | ||
|
|
cab0fa93e7 | ||
|
|
2869d5869b | ||
|
|
80da0fbb56 | ||
|
|
b0b11cfcf5 | ||
|
|
80e04ad4b1 | ||
|
|
e031509966 | ||
|
|
c62ed29de9 | ||
|
|
fed4749a46 | ||
|
|
f18411c151 | ||
|
|
12fde2dd4a | ||
|
|
d575e3a71d | ||
|
|
46d066394f | ||
|
|
7e28973f3a | ||
|
|
b8194129da | ||
|
|
b408b43394 | ||
|
|
5d8dd7cdf4 | ||
|
|
3c08604770 | ||
|
|
17deb16779 | ||
|
|
e199f35006 | ||
|
|
3443d065a3 | ||
|
|
1740e5f1aa | ||
|
|
0ee54b4a7e | ||
|
|
bdb444371f | ||
|
|
6a4715c324 | ||
|
|
db6ff88ad1 | ||
|
|
e8c5c22d05 | ||
|
|
7fa05bc463 | ||
|
|
9d2d655039 | ||
|
|
7791779289 | ||
|
|
98fceea06d | ||
|
|
52cbffbd79 | ||
|
|
674f91389a | ||
|
|
24ff98b88a | ||
|
|
a729297f6b | ||
|
|
61f21f48e8 | ||
|
|
a7f1235fd1 | ||
|
|
ba1b1b0639 | ||
|
|
d6547bab34 | ||
|
|
1d89360765 | ||
|
|
60f8d11c2d | ||
|
|
d975450ae1 | ||
|
|
52e698fdbc | ||
|
|
3105bb9ff3 | ||
|
|
110f29b766 | ||
|
|
572cd3655e | ||
|
|
0134ebefc2 | ||
|
|
f5381403c0 | ||
|
|
378277206a | ||
|
|
3be3d8ebef | ||
|
|
681cdd809f | ||
|
|
19382a061f | ||
|
|
88d39ec04a | ||
|
|
4e3977e9ce | ||
|
|
d32b061c95 | ||
|
|
af91173734 | ||
|
|
fcc68d6d80 | ||
|
|
251da0a148 | ||
|
|
3a43a98f10 | ||
|
|
9b0ce9558c | ||
|
|
e44e3edef9 | ||
|
|
07309d7c25 | ||
|
|
1ca34261d3 | ||
|
|
9303b22661 | ||
|
|
fb4f55e809 | ||
|
|
b261d10b89 | ||
|
|
4b16269b7f | ||
|
|
836c8718b0 | ||
|
|
76c1db33e9 | ||
|
|
345bbcf50c | ||
|
|
ef7916b320 | ||
|
|
6dcc70f531 | ||
|
|
8a7f3645bc | ||
|
|
02198b12fe | ||
|
|
f01fe2801d | ||
|
|
cbece42fb9 | ||
|
|
7036073ed1 | ||
|
|
e271b4e494 | ||
|
|
16547f64c2 | ||
|
|
00683732d8 | ||
|
|
0d70925816 | ||
|
|
987b7ea952 | ||
|
|
be1ab236c8 | ||
|
|
a376ad8762 | ||
|
|
6a2fcd6898 | ||
|
|
5c26fe15d8 | ||
|
|
a1f49e11d5 | ||
|
|
d96afa4499 | ||
|
|
630c6d0d97 | ||
|
|
fb59345637 | ||
|
|
ed2cae9236 | ||
|
|
d95c10e06c | ||
|
|
c89590c7b7 | ||
|
|
676f820f87 | ||
|
|
f8b4d186a8 | ||
|
|
1217710234 | ||
|
|
5aaf368149 | ||
|
|
f4f9712bc9 | ||
|
|
2fad3d89ff | ||
|
|
97235d2dea | ||
|
|
0ba766f2e0 | ||
|
|
96e2510165 | ||
|
|
590460cea4 | ||
|
|
51c70eb925 | ||
|
|
75c46e1e5c | ||
|
|
d968e8ec33 | ||
|
|
d3502b22f2 | ||
|
|
1b30c8b2b5 | ||
|
|
f61826281b | ||
|
|
9599d1712c | ||
|
|
e37eaac8d1 | ||
|
|
c425f71ac4 | ||
|
|
65fe50d11f | ||
|
|
838152155e | ||
|
|
dc321ce643 | ||
|
|
0cd94555d5 | ||
|
|
d7449b4d78 | ||
|
|
e5d25f3d66 | ||
|
|
2aa34a6346 | ||
|
|
a0cdf11096 | ||
|
|
02ba9ca7f0 | ||
|
|
5928147f26 | ||
|
|
0186e6330a | ||
|
|
ae4587226c | ||
|
|
8d3f874e64 | ||
|
|
4b7a1e8607 | ||
|
|
b98efe0b67 | ||
|
|
071162f914 | ||
|
|
af892e5cbd | ||
|
|
b6d0ad3e05 | ||
|
|
89adf56eed | ||
|
|
cb14034c46 | ||
|
|
81ec8287f8 | ||
|
|
4a8935eefd | ||
|
|
94cd2f6e92 | ||
|
|
21c05bb8d7 | ||
|
|
fb3466b392 | ||
|
|
cb5ef83f0a | ||
|
|
7c25ab536f | ||
|
|
a2e8be2af5 | ||
|
|
8017b2ab1b | ||
|
|
2db13c2494 | ||
|
|
49eda8861e | ||
|
|
04496fadcd | ||
|
|
13571f9fd2 | ||
|
|
aca86967bf | ||
|
|
1a850d58c4 | ||
|
|
b60fb28313 | ||
|
|
1766f8bb53 | ||
|
|
fcb30b5e5d | ||
|
|
f447a4953a | ||
|
|
1274f5f602 | ||
|
|
abfe96fcaa | ||
|
|
65048fd624 | ||
|
|
9b6d6c109c | ||
|
|
3454c321e7 | ||
|
|
f8d8fb5e11 | ||
|
|
4b581ad07b | ||
|
|
14f7d3acad | ||
|
|
00651d670d | ||
|
|
f1003a1d1e | ||
|
|
d868143fc9 | ||
|
|
f62cef9c12 | ||
|
|
c7304b9fb0 | ||
|
|
a49b58ba87 | ||
|
|
0a94e8fdf0 | ||
|
|
ffdfc73d47 | ||
|
|
b7626a1baa | ||
|
|
c37e327330 | ||
|
|
1a2950ae34 | ||
|
|
885ef28a0d | ||
|
|
2277c73891 | ||
|
|
9668270017 | ||
|
|
6efa55ffdf | ||
|
|
e3e607a6d4 | ||
|
|
c124ca9738 | ||
|
|
4273448b5d | ||
|
|
1c9ca88280 | ||
|
|
2639981dda | ||
|
|
30624c6aba | ||
|
|
75df7bcbdd | ||
|
|
ffd6a988e1 | ||
|
|
027060ba86 | ||
|
|
6106e379c9 | ||
|
|
a28b949dc1 | ||
|
|
bb85e11a92 | ||
|
|
785dcb30c3 | ||
|
|
5e41b3ab4d | ||
|
|
d077388616 | ||
|
|
ea1e28c7b7 | ||
|
|
77682cb45a | ||
|
|
fd7cf71043 | ||
|
|
086399da33 | ||
|
|
0de1305665 | ||
|
|
afaf0b4968 | ||
|
|
d5a584c28b | ||
|
|
7c902d40a9 | ||
|
|
f966662911 | ||
|
|
773a89b0f3 | ||
|
|
77241d1c71 | ||
|
|
fda0fda7ac | ||
|
|
fd50a5b65e | ||
|
|
889a812fdc | ||
|
|
cd20df8d74 | ||
|
|
d14d281e7c | ||
|
|
febcf2568e | ||
|
|
3f739fc1b4 | ||
|
|
b2b768cd4b | ||
|
|
4cfe682367 | ||
|
|
42572efca9 | ||
|
|
a4c3f5267b | ||
|
|
76b7fd0dc1 | ||
|
|
117dbe1fe0 | ||
|
|
6e2ec2300d | ||
|
|
feb12fafe8 | ||
|
|
6405997723 | ||
|
|
91fec9024c | ||
|
|
4ca4278635 | ||
|
|
794b27c1ad | ||
|
|
087a9859b4 | ||
|
|
26068a855c | ||
|
|
722287b81a | ||
|
|
744e73bfdb | ||
|
|
0b1d958a86 | ||
|
|
14875c962b | ||
|
|
9da76eab43 | ||
|
|
0734f6d55b | ||
|
|
f5433f04e6 | ||
|
|
ab7d916e0d | ||
|
|
caa1036da2 | ||
|
|
fd6ea99967 | ||
|
|
61749d39a6 | ||
|
|
04a44cfbaa | ||
|
|
8440501ad2 | ||
|
|
f9dab9b041 | ||
|
|
478dcc4f0f | ||
|
|
522de4ad92 | ||
|
|
de154ab407 | ||
|
|
39b8a33166 | ||
|
|
0c3d8eeb6f | ||
|
|
66623b945e | ||
|
|
840a98ff40 | ||
|
|
55fe6f33f5 | ||
|
|
9622fcccdb | ||
|
|
5d0c1f38ef | ||
|
|
08213eb8fb | ||
|
|
4eb951c977 | ||
|
|
879da4feef | ||
|
|
c653449cc0 | ||
|
|
54d56f468b | ||
|
|
4a68c04891 | ||
|
|
1e78025726 | ||
|
|
c0bc796fce | ||
|
|
30f6cd44d8 | ||
|
|
8dd1db9839 | ||
|
|
d9f86a6293 | ||
|
|
ee07d603b1 | ||
|
|
2097822872 | ||
|
|
90d5e1e551 | ||
|
|
db4a79838b | ||
|
|
ff43d1877e | ||
|
|
874a45ed1c | ||
|
|
dec508542d | ||
|
|
82a00b1f7b | ||
|
|
2e50c3856e | ||
|
|
8a4d305843 | ||
|
|
39fa35ae12 | ||
|
|
cc65ca032e | ||
|
|
eecd85a1c2 | ||
|
|
33ac72ebac | ||
|
|
6261640a92 | ||
|
|
a30e63eee1 | ||
|
|
ff51aad139 | ||
|
|
4695b156e0 | ||
|
|
19265d4e98 | ||
|
|
7482c2b4ec | ||
|
|
f299692de7 | ||
|
|
b51a30ed99 | ||
|
|
75eeac1d41 | ||
|
|
3d7ce028e9 | ||
|
|
3ba6fbf0f7 | ||
|
|
598689c9bc | ||
|
|
99cec416b7 | ||
|
|
05fd1601ad | ||
|
|
b8c9bfcc34 | ||
|
|
8cf7993af5 | ||
|
|
6a14e8a376 | ||
|
|
27ccff636b | ||
|
|
08a508b750 | ||
|
|
fa31956d28 | ||
|
|
942986c6b6 | ||
|
|
659c131de6 | ||
|
|
bbcfe50e0d | ||
|
|
fa28228acb | ||
|
|
93f009e9d8 | ||
|
|
725e5ac0f0 | ||
|
|
b568585f44 | ||
|
|
508cd0a64c | ||
|
|
8c37865c07 | ||
|
|
b30f97dad5 | ||
|
|
ddbcc32bd8 | ||
|
|
371bcfea81 | ||
|
|
87c71f74a0 | ||
|
|
84f74e5db0 | ||
|
|
43373b77ec | ||
|
|
2dc08a0dfb | ||
|
|
2e0f7062c3 | ||
|
|
f21ca49d83 | ||
|
|
4974532276 | ||
|
|
5a75c59bf2 | ||
|
|
fc48025629 | ||
|
|
00703c0b8f | ||
|
|
969b782fd0 | ||
|
|
328de1e790 | ||
|
|
4c283d88c7 | ||
|
|
7ee5dd564c | ||
|
|
c62b95a9a2 | ||
|
|
15674daeae | ||
|
|
febc2fcc7d | ||
|
|
e6776fd922 | ||
|
|
2dc5eecfac | ||
|
|
296c0142f2 | ||
|
|
2f6f2feade | ||
|
|
0858960d33 | ||
|
|
b80b19d3da | ||
|
|
4ec357bb26 | ||
|
|
adf2d92471 | ||
|
|
c326a6c971 | ||
|
|
79ef3e3571 | ||
|
|
78cc8cc8c9 | ||
|
|
3905f9d5b3 | ||
|
|
9a5275b92a | ||
|
|
a497f501e9 | ||
|
|
26dade03f2 | ||
|
|
8fc94a5560 | ||
|
|
7e6af7f541 | ||
|
|
e46ae13a5a | ||
|
|
95455dbd83 | ||
|
|
4a77bc4be0 | ||
|
|
dbefdaac2c | ||
|
|
46d0ce3cbf | ||
|
|
fa143f1ea4 | ||
|
|
5f631ff0af | ||
|
|
ed224dce34 | ||
|
|
82b4943d13 | ||
|
|
07acfb444a | ||
|
|
2c995c913e | ||
|
|
b6522ae3f5 | ||
|
|
787002bf7d | ||
|
|
43ba4c3620 | ||
|
|
f95a6d0f0a | ||
|
|
3ba78e28bb | ||
|
|
42f87597cf | ||
|
|
59ca0731b8 | ||
|
|
2e081ce8d2 | ||
|
|
57a60c1946 | ||
|
|
b6b6bbc3ee | ||
|
|
a34a11b200 | ||
|
|
2bc4c38f01 | ||
|
|
395d0c231b | ||
|
|
a8c30362a1 | ||
|
|
842f474939 | ||
|
|
947fa2b558 | ||
|
|
eaef035062 | ||
|
|
144dbf8af0 | ||
|
|
6000d605f1 | ||
|
|
15151acb3e | ||
|
|
3d0896f1b6 | ||
|
|
9236d65215 | ||
|
|
a542db8e50 | ||
|
|
3693674fc9 | ||
|
|
c55ef8714b | ||
|
|
1ab041ef55 | ||
|
|
257a2280c1 | ||
|
|
7ae79bbb98 | ||
|
|
f5fcc9ee7b | ||
|
|
fb2b874614 | ||
|
|
a3d7b58b83 | ||
|
|
ae0091fbae | ||
|
|
c07eccb468 | ||
|
|
fb2d35c765 | ||
|
|
4a30dd2e4f | ||
|
|
c7d30ebde4 | ||
|
|
78a81f321a | ||
|
|
6217cc9e89 | ||
|
|
1ec37ebcbf | ||
|
|
f57c462b85 | ||
|
|
8e46e2a4c1 | ||
|
|
7774cb7ffb | ||
|
|
a9937740c5 | ||
|
|
83527d27fb | ||
|
|
50e780ad57 | ||
|
|
a47a17852e | ||
|
|
b222bbcccb | ||
|
|
096a3c5f2f | ||
|
|
348083d287 | ||
|
|
2397940292 | ||
|
|
44f283c4a2 | ||
|
|
40fd9e8759 | ||
|
|
085a271b6c | ||
|
|
2796e6c80a | ||
|
|
d1ae009f57 | ||
|
|
b99e581929 | ||
|
|
c81391b5b6 | ||
|
|
033733122a | ||
|
|
893ad2bf62 | ||
|
|
0612a9e6f5 | ||
|
|
b2947aede0 | ||
|
|
667058204d | ||
|
|
4b99b2715d | ||
|
|
fd744fb526 | ||
|
|
49b7e43c81 | ||
|
|
d701b8db11 | ||
|
|
9a68867d42 | ||
|
|
01b9a3c268 | ||
|
|
33ef7b1641 | ||
|
|
cadfca7475 | ||
|
|
b33d3ec799 | ||
|
|
8e6f33f045 | ||
|
|
6440a23f96 | ||
|
|
e6e424836d | ||
|
|
5880d62000 | ||
|
|
e747c089fc | ||
|
|
72ec5c64d9 | ||
|
|
48f7830558 | ||
|
|
6a85dd2c5e | ||
|
|
80c2f233d4 | ||
|
|
1db153b66b | ||
|
|
593b4fd515 | ||
|
|
8b2362a84e | ||
|
|
6372d3c01b | ||
|
|
db856014aa | ||
|
|
fdcb12df92 | ||
|
|
16ef1c476e | ||
|
|
d420ab34eb | ||
|
|
6d5ce578e4 | ||
|
|
d22e6cde6b | ||
|
|
8ce059bb46 | ||
|
|
79fa3c7b0f | ||
|
|
5e2507041d | ||
|
|
a6042d3958 | ||
|
|
96022847d7 | ||
|
|
a6a69605c6 | ||
|
|
e10fc538d0 | ||
|
|
9b938f2236 | ||
|
|
197d8d1f3b | ||
|
|
80bdf51ecb | ||
|
|
1923085068 | ||
|
|
4b523555d6 | ||
|
|
05e9523cba | ||
|
|
4060acae41 | ||
|
|
8e04c077ca | ||
|
|
db74640993 | ||
|
|
5d44089214 | ||
|
|
fcf3cec0fc | ||
|
|
4af158bf56 | ||
|
|
f694f87d49 | ||
|
|
da80ae1f89 | ||
|
|
aea1303119 | ||
|
|
16411422c8 | ||
|
|
94c5717052 | ||
|
|
d9b16c15f7 | ||
|
|
ab2e163234 | ||
|
|
2131a1e4ee | ||
|
|
68a6441b16 | ||
|
|
3530545eb9 | ||
|
|
430118f071 | ||
|
|
e27c1b5335 | ||
|
|
6ac13e3281 | ||
|
|
1aa82094f1 | ||
|
|
e3cfeee813 | ||
|
|
d6a9b43515 | ||
|
|
94f5f7a3c4 | ||
|
|
8e13fc0e2a | ||
|
|
c580d7fc5e | ||
|
|
ac93a30933 | ||
|
|
2e6fe3ddf1 | ||
|
|
6b819e259c | ||
|
|
bd9a40562f | ||
|
|
3a0731a024 | ||
|
|
988a443974 | ||
|
|
88ce834385 | ||
|
|
3eeac6f8b0 | ||
|
|
1af3142c52 | ||
|
|
d0e177055d | ||
|
|
fe89ad5a51 | ||
|
|
8469a2485b | ||
|
|
ca2b84af8f | ||
|
|
2b3ee82d56 | ||
|
|
c30a648edf | ||
|
|
5b08eec813 | ||
|
|
8f87a74398 | ||
|
|
8512402eca | ||
|
|
01611cbb07 | ||
|
|
fc572ba2a6 | ||
|
|
c65e8f1621 | ||
|
|
5ea43bd65c | ||
|
|
2820add3d1 | ||
|
|
6117221cbc | ||
|
|
13cc393840 | ||
|
|
b1595cdd1d | ||
|
|
0ba81a1a92 | ||
|
|
c675150305 | ||
|
|
b4d534c02d | ||
|
|
c048460c22 | ||
|
|
0627ee0cb6 | ||
|
|
53ace4876e | ||
|
|
730677a918 | ||
|
|
95f2e40434 | ||
|
|
fd85411e26 | ||
|
|
e18624e4b5 | ||
|
|
429970ad30 | ||
|
|
ba06db2e19 | ||
|
|
2c9e9f8a11 | ||
|
|
411167ab58 | ||
|
|
e659e042b0 | ||
|
|
504e932d88 | ||
|
|
f49a6bf807 | ||
|
|
55b17c2b7e | ||
|
|
cfbfcf20bf | ||
|
|
bcfdaaabab | ||
|
|
3813456e2b | ||
|
|
bac87cbc42 | ||
|
|
c6bcc2572c | ||
|
|
3be8abeae2 | ||
|
|
a78860f092 | ||
|
|
382bde0fc2 | ||
|
|
c0c1d011fa | ||
|
|
8272989171 | ||
|
|
4865f8afca | ||
|
|
786d3db880 | ||
|
|
3d4b93c86a | ||
|
|
bb5fe45f31 | ||
|
|
7e0b898765 | ||
|
|
b6edaea54c | ||
|
|
c7da16f07d | ||
|
|
6a1f0251cd | ||
|
|
437b457134 | ||
|
|
ffc8088ccd | ||
|
|
7e7e8b88a2 | ||
|
|
959e868126 | ||
|
|
83792757de | ||
|
|
699e46c2f5 | ||
|
|
fc8a037d12 | ||
|
|
e46ffaf84b | ||
|
|
bad4597a86 | ||
|
|
32b6e0a485 | ||
|
|
da075fb215 | ||
|
|
c12e5659ab | ||
|
|
75aa17f169 | ||
|
|
e7fa5d7f9d | ||
|
|
45e0340787 | ||
|
|
7b7bded5f0 | ||
|
|
e59bcd2b64 | ||
|
|
76f2f0c783 | ||
|
|
ca1f83e9c9 | ||
|
|
16eac5040b | ||
|
|
f98ab3b0a6 | ||
|
|
b561aff94f | ||
|
|
4fa208d4d7 | ||
|
|
350a5d2cbb | ||
|
|
7e4e66b54d | ||
|
|
e8356de3c1 | ||
|
|
4b09edfa42 | ||
|
|
4dbb2d88b9 | ||
|
|
90cf3c9049 | ||
|
|
5a82aa952d | ||
|
|
7ffc509ee6 | ||
|
|
c6df0b586c | ||
|
|
b5862ba780 | ||
|
|
1f0a721101 | ||
|
|
0e4cdda8c7 | ||
|
|
48d81c7d47 | ||
|
|
00b387afc2 | ||
|
|
74492e40c4 | ||
|
|
93bba41dd5 | ||
|
|
ed46d8c53c | ||
|
|
039142e50d | ||
|
|
a7b605f0cc | ||
|
|
b6591dba5a | ||
|
|
318ec4074e | ||
|
|
e789872efe | ||
|
|
cda0e0cf6d | ||
|
|
177da5937e | ||
|
|
eaeb144c3b | ||
|
|
56229136be | ||
|
|
26f1d6125b | ||
|
|
249fbfad15 | ||
|
|
1116b05f1d | ||
|
|
9cc2993e70 | ||
|
|
3af5976aa2 | ||
|
|
e4b290a394 | ||
|
|
76f844da2f | ||
|
|
ac8db7a376 | ||
|
|
1aebad3c19 | ||
|
|
b5ce8b655a | ||
|
|
cbb1ebad33 | ||
|
|
228e8407a7 | ||
|
|
8e59e49d29 | ||
|
|
4722366b42 | ||
|
|
7a45047f8f | ||
|
|
59cb33d231 | ||
|
|
06b23cca94 | ||
|
|
d658e05363 | ||
|
|
57916c032f | ||
|
|
9869eb4bc8 | ||
|
|
d850a8be7d | ||
|
|
c6448bd9c1 | ||
|
|
146d50c8d1 | ||
|
|
c51cb88c97 | ||
|
|
a95a2937c1 | ||
|
|
da7c73b662 | ||
|
|
09f0f74104 | ||
|
|
3a77eb85ed | ||
|
|
fe016edf33 | ||
|
|
ff3a74064b | ||
|
|
454a2c186b | ||
|
|
03ba306018 | ||
|
|
ce3266e036 | ||
|
|
0d1b194b6b | ||
|
|
19558a425b | ||
|
|
a28908f0b4 | ||
|
|
87a567122e | ||
|
|
ee67c848d7 | ||
|
|
93666d310e | ||
|
|
ccc94e7b45 | ||
|
|
f81a81cb74 | ||
|
|
c1bb910d1c | ||
|
|
f9a0622c30 | ||
|
|
ac165cfc14 | ||
|
|
961e5b955d | ||
|
|
81c6c8deff | ||
|
|
23a6af128b | ||
|
|
bde157b085 | ||
|
|
367090614d | ||
|
|
f030190fb7 | ||
|
|
568b88e342 | ||
|
|
9be51a5cb0 | ||
|
|
7276223a90 | ||
|
|
5f9e8f5b7e | ||
|
|
ecd0e50ac4 | ||
|
|
3a26f6eb6f | ||
|
|
8db82c1022 | ||
|
|
35cbbeeea4 | ||
|
|
b851e66ec8 | ||
|
|
a5c17f3abe | ||
|
|
13d22a2dbc | ||
|
|
384d4ace7e | ||
|
|
aa1aac6adb | ||
|
|
03de28a7b7 | ||
|
|
b24a7cf529 | ||
|
|
f8837ae58b | ||
|
|
acfbbebd85 | ||
|
|
ef5e80d4dc | ||
|
|
bcb4220d00 | ||
|
|
0bbad7a2db | ||
|
|
5ef9a3116c | ||
|
|
b8966f7878 | ||
|
|
fe391a1026 | ||
|
|
7e8d9c55ac | ||
|
|
47c939561c | ||
|
|
817ca999e3 | ||
|
|
4f10c00c71 | ||
|
|
d758d41e56 | ||
|
|
d1f1c4afea | ||
|
|
d484d16128 | ||
|
|
764d1b006e | ||
|
|
61c0dfee38 | ||
|
|
03f05c8afa | ||
|
|
6d5c3c042e | ||
|
|
f40b215753 | ||
|
|
03532e1289 | ||
|
|
76ff32098f | ||
|
|
e0ccce4072 | ||
|
|
afac621611 | ||
|
|
542a6adf84 | ||
|
|
acc4d2a81b | ||
|
|
dda60995a3 | ||
|
|
35d5c2633d | ||
|
|
e955583d2c | ||
|
|
7cd57cd9e4 | ||
|
|
500f187a60 | ||
|
|
82b53fee87 | ||
|
|
531f8fe24d | ||
|
|
169db42cf6 | ||
|
|
223f44fdfd | ||
|
|
7829a0dfdc | ||
|
|
52e8fa8995 | ||
|
|
88869f43ae | ||
|
|
a63c634e3f | ||
|
|
e81b43be98 | ||
|
|
39e45221b1 | ||
|
|
497d6376c8 | ||
|
|
f70ec29881 | ||
|
|
018e534383 | ||
|
|
ca894c3416 | ||
|
|
dbbc6a2f44 | ||
|
|
20aa40c5d2 | ||
|
|
94392fce96 | ||
|
|
df9d8d593c | ||
|
|
9f9dde511e | ||
|
|
7317b61425 | ||
|
|
9d584152f0 | ||
|
|
74051576dd | ||
|
|
04120099fb | ||
|
|
75a080b7cb | ||
|
|
80385ff893 | ||
|
|
dbc65faecb | ||
|
|
5d6ad703c1 | ||
|
|
286381d0dd | ||
|
|
11b0afc0bd | ||
|
|
a4f802806c | ||
|
|
aa50bf24aa | ||
|
|
0fe394082c | ||
|
|
00b24f85c9 | ||
|
|
63864f2f86 | ||
|
|
b646073dfa | ||
|
|
09ba429723 | ||
|
|
4f0b07505a | ||
|
|
92095314c6 | ||
|
|
c2254f3783 | ||
|
|
d653ec817c | ||
|
|
85e13dc3ee | ||
|
|
0655d4350e | ||
|
|
170f1962ad | ||
|
|
454368e3d3 | ||
|
|
cff02b04a0 | ||
|
|
0695154661 | ||
|
|
5103d904f3 | ||
|
|
e9e1add9b8 | ||
|
|
22b00c33de | ||
|
|
40ae2e3246 | ||
|
|
8ca7356489 | ||
|
|
0eaf5887ea | ||
|
|
f5f49c7b1d | ||
|
|
f7b8d25e75 | ||
|
|
d3d6a6be48 | ||
|
|
402dc286d1 | ||
|
|
c3ee588bfe | ||
|
|
eca253d4a3 | ||
|
|
6cd1a41a32 | ||
|
|
b03657add3 | ||
|
|
676abca671 | ||
|
|
d546caca4c | ||
|
|
344a10421a | ||
|
|
30197a09d2 | ||
|
|
fc86bdb55c | ||
|
|
26069a580a | ||
|
|
9ab813ebdc | ||
|
|
333cf8cc2a | ||
|
|
4f52eb9be3 | ||
|
|
d1550a3fd5 | ||
|
|
d6909ec8e5 | ||
|
|
2dd54fddf4 | ||
|
|
c90f8415b3 | ||
|
|
ebacb83563 | ||
|
|
7eab91a160 | ||
|
|
df5bde79e5 | ||
|
|
57b91a0add | ||
|
|
678a6101b3 | ||
|
|
72d4cdd3a3 | ||
|
|
098886bcb6 | ||
|
|
9190eb8f34 | ||
|
|
1f9e518581 | ||
|
|
63148dff3b | ||
|
|
d595b3f195 | ||
|
|
44ef4cd35a | ||
|
|
b02ad0dc83 | ||
|
|
1955427d62 | ||
|
|
3ba78dec78 | ||
|
|
66f5647069 | ||
|
|
f46c0986d3 | ||
|
|
a33775d2a1 | ||
|
|
e83a7e49e0 | ||
|
|
54a7211a45 | ||
|
|
1e5fd2d551 | ||
|
|
8bce2b1fdd | ||
|
|
393b1f8369 | ||
|
|
e6a2a12d6e | ||
|
|
1ea65a09b5 | ||
|
|
7089ce8fc7 | ||
|
|
bd18339797 | ||
|
|
221aa25e00 | ||
|
|
4ab154c4bf | ||
|
|
fcb63465ac | ||
|
|
612fec8961 | ||
|
|
d3942ad1f0 | ||
|
|
d747da7c65 | ||
|
|
9dc8995ba8 | ||
|
|
e25ec0d981 | ||
|
|
3ab661b628 | ||
|
|
cba70856b7 | ||
|
|
5620dc96bd | ||
|
|
74f00e60c7 | ||
|
|
2c11aadc57 | ||
|
|
c4c940722b | ||
|
|
7b247e73df | ||
|
|
b18967fba4 | ||
|
|
90179caa72 | ||
|
|
cac0e7ee50 | ||
|
|
387e4dd958 | ||
|
|
fea99bf8f8 | ||
|
|
92a1a43cbb | ||
|
|
a7c5f78107 | ||
|
|
9acf1ac42e | ||
|
|
141258d564 | ||
|
|
c9400c565c | ||
|
|
4b86c2a3fd | ||
|
|
5f6d6da154 | ||
|
|
01dc397afd | ||
|
|
ca3e048b78 | ||
|
|
b9f4a7835a | ||
|
|
31f78989d2 | ||
|
|
b5bdae3d6d | ||
|
|
5920c5d3e5 | ||
|
|
9c6d7abc76 | ||
|
|
4de31ebb85 | ||
|
|
3ff650f046 | ||
|
|
9feb2fc6cf | ||
|
|
1937220099 | ||
|
|
48ad6dcb99 | ||
|
|
3fb9e2162e | ||
|
|
56151a4198 | ||
|
|
c8cc97dd97 | ||
|
|
011b60af61 | ||
|
|
3481def4f6 | ||
|
|
d14700606d | ||
|
|
6828e24481 | ||
|
|
bfc61a69ba | ||
|
|
44e8a372e5 | ||
|
|
1687d4caad | ||
|
|
f88cc8b988 | ||
|
|
266ea99a77 | ||
|
|
b1c2b9e005 | ||
|
|
65318a442e | ||
|
|
8d2745dfc5 | ||
|
|
fdff93a961 | ||
|
|
5eecc3fc54 | ||
|
|
cb2594f53f | ||
|
|
b98a5e0545 | ||
|
|
477dd69d54 | ||
|
|
82eb701ea7 | ||
|
|
139d92054f | ||
|
|
7d3e95e050 | ||
|
|
8d75f37548 | ||
|
|
db600cb5b9 | ||
|
|
78b0055206 | ||
|
|
ef33731490 | ||
|
|
cd296b1f37 | ||
|
|
1315d02b2c | ||
|
|
1ecc0b113b | ||
|
|
cb14564174 | ||
|
|
57abea5416 | ||
|
|
4e6fe4d119 | ||
|
|
1c36406b1e | ||
|
|
361a83c378 | ||
|
|
53a09bb912 | ||
|
|
51f9150410 | ||
|
|
e82e808f2b | ||
|
|
e6256d60ec | ||
|
|
080ada78ee | ||
|
|
fbc2583433 | ||
|
|
7a22458ed4 | ||
|
|
581f4bdf7b | ||
|
|
617ede481a | ||
|
|
c7fc98dff6 | ||
|
|
64155bf58f | ||
|
|
27841acb83 | ||
|
|
d4cd382092 | ||
|
|
f8ac57bdb1 | ||
|
|
d018133e9b | ||
|
|
812511e31b | ||
|
|
bcf62e688f | ||
|
|
1ecb12048c | ||
|
|
41907975b0 | ||
|
|
dc0b2ceb8b | ||
|
|
808375d5e3 | ||
|
|
37a6cc4de4 | ||
|
|
aeef51bc76 | ||
|
|
1a8057aba1 | ||
|
|
26a2398399 | ||
|
|
8bfc42e8d8 | ||
|
|
7b10182e4a | ||
|
|
744837cce7 | ||
|
|
5e6dc290b6 | ||
|
|
14f79018ad | ||
|
|
db3aa5248c | ||
|
|
8ff75607a5 | ||
|
|
6f8c5d7c51 | ||
|
|
083e3c7a36 | ||
|
|
fba349b144 | ||
|
|
5f8a5056f1 | ||
|
|
5c6837c1fc | ||
|
|
916627b590 | ||
|
|
dc96c1a175 | ||
|
|
ea67ccc81a | ||
|
|
ab6b683d90 | ||
|
|
9a8e78aaf4 | ||
|
|
bc41c3b7b0 | ||
|
|
abe19b9435 | ||
|
|
0983ffbef2 | ||
|
|
137c82c690 | ||
|
|
8face792c0 | ||
|
|
b78b9cad1f | ||
|
|
97786bfa77 | ||
|
|
f81b4b071f | ||
|
|
8b7d959781 | ||
|
|
4fcde6c8c5 | ||
|
|
41f54624b1 | ||
|
|
1eb9718b6b | ||
|
|
9c837b3361 | ||
|
|
8681e8ffe9 | ||
|
|
00e46443a6 | ||
|
|
6295050fa6 | ||
|
|
f0aef79c7a | ||
|
|
a654ad291f | ||
|
|
a8c4e0637b | ||
|
|
89587e6b76 | ||
|
|
0120877623 | ||
|
|
3805f901cf | ||
|
|
f827b9ef50 | ||
|
|
587ae6ba7e | ||
|
|
563f91bf18 | ||
|
|
3743c179e1 | ||
|
|
bbdcb92042 | ||
|
|
20945f60c9 | ||
|
|
6297d0862f | ||
|
|
789a8a5fe9 | ||
|
|
6e43d2cd4e | ||
|
|
3a5c24b6f1 | ||
|
|
54529ab461 | ||
|
|
96f6b871ce | ||
|
|
842e100b73 | ||
|
|
d0c1a1f600 | ||
|
|
5b879f75c5 | ||
|
|
b3077182d2 | ||
|
|
30f636274b | ||
|
|
5bc1b6ad81 | ||
|
|
be3b245dbe | ||
|
|
df3e7a600e | ||
|
|
dfff86df72 | ||
|
|
8f7a160ba1 | ||
|
|
f8aa14d431 | ||
|
|
fa2ad2f234 | ||
|
|
408453c9e9 | ||
|
|
eb67adb257 | ||
|
|
4a3ff46bd7 | ||
|
|
d2dbf959b6 | ||
|
|
9c69f73de5 | ||
|
|
a48ebe2dd7 | ||
|
|
a60e46dd5c | ||
|
|
dd3385ec67 | ||
|
|
d90334e883 | ||
|
|
2b41b0127c | ||
|
|
13adfd131c | ||
|
|
1dd24f7082 | ||
|
|
6a2949be8a | ||
|
|
7f748b2620 | ||
|
|
41dd75af8a | ||
|
|
0dd088e98d | ||
|
|
730e86d661 | ||
|
|
5d08359dc9 | ||
|
|
3c9dcea46b | ||
|
|
0e1a16b96b | ||
|
|
c31df4ae6b | ||
|
|
f454944f8c | ||
|
|
cb3d4b1800 | ||
|
|
cd17c90f2e | ||
|
|
ac9e882bda | ||
|
|
7dd60abb11 | ||
|
|
097d423275 | ||
|
|
3eb65eef4f | ||
|
|
5924753fd1 | ||
|
|
64c652ea06 | ||
|
|
9a2e98360a | ||
|
|
e537018e71 | ||
|
|
1b324f9bd1 | ||
|
|
1e25e2ac4c | ||
|
|
a7bc25b553 | ||
|
|
08089d6120 | ||
|
|
2e5388af5b | ||
|
|
7e55ea59bb | ||
|
|
b9f3bea8c3 | ||
|
|
1b74befd64 | ||
|
|
d3555228b2 | ||
|
|
59d5013952 | ||
|
|
496f34117c | ||
|
|
1ef40d9423 | ||
|
|
307701788f | ||
|
|
ed572df563 | ||
|
|
f05d6fe0e0 | ||
|
|
e26fd18450 | ||
|
|
0079fbdb08 | ||
|
|
db0ac723fa | ||
|
|
4a1812e5ba | ||
|
|
1fbed10375 | ||
|
|
89dd6faa2b | ||
|
|
5ac4bc6d8b | ||
|
|
27e5e3ca29 | ||
|
|
4a856b94cc | ||
|
|
3566d1fc1f | ||
|
|
8b76bf6e65 | ||
|
|
7aa3bde170 | ||
|
|
eb5f2978cc | ||
|
|
32c0d228cc | ||
|
|
c2ce5c7596 | ||
|
|
5d96f9960a | ||
|
|
fdd73d4ada | ||
|
|
02bcb1712c | ||
|
|
29b270e761 | ||
|
|
195dd379d9 | ||
|
|
87decd0f8d | ||
|
|
300af4477f | ||
|
|
a2215cb8f6 | ||
|
|
1a1a5924da | ||
|
|
7adb8fd150 | ||
|
|
eae9a4447d | ||
|
|
7b4c4e528c | ||
|
|
e99a0d4515 | ||
|
|
29bc36c02a | ||
|
|
9bf61f9914 | ||
|
|
d6e0c90baa | ||
|
|
948b09a27f | ||
|
|
09ec5b1fde | ||
|
|
547311ff26 | ||
|
|
4c21a42b53 | ||
|
|
5f24b2dc98 | ||
|
|
8dae561557 | ||
|
|
49a9c2dba9 | ||
|
|
60606a8528 | ||
|
|
9e93007355 | ||
|
|
4eb405d405 | ||
|
|
da9154d811 | ||
|
|
88afb2c495 | ||
|
|
d6875e1182 | ||
|
|
9b3d7a32e3 | ||
|
|
248847b775 | ||
|
|
7c458b9bd3 | ||
|
|
bc68b6e9fe | ||
|
|
63634eed02 | ||
|
|
d797734b38 | ||
|
|
516c76a4ab | ||
|
|
909d68eac3 | ||
|
|
2e26703b50 | ||
|
|
172c2da2cc | ||
|
|
758c3187fc | ||
|
|
280a1265c8 | ||
|
|
10a801fcc7 | ||
|
|
a16e0620d2 | ||
|
|
65658b16e6 | ||
|
|
77015336a4 | ||
|
|
c82af749ac | ||
|
|
4f5b7bbccb | ||
|
|
002132bc4b | ||
|
|
ebc511f418 | ||
|
|
f8e10f80cc | ||
|
|
13b9837524 | ||
|
|
9222b939ab | ||
|
|
31677dd296 | ||
|
|
f91bf49aae | ||
|
|
1714351cc9 | ||
|
|
b49b8ad140 | ||
|
|
9e9ecc7dcf | ||
|
|
f4675c02df | ||
|
|
d838bc952a | ||
|
|
c7c61f72c9 | ||
|
|
7ee40c4682 | ||
|
|
8075c2d938 | ||
|
|
753824a7e2 | ||
|
|
a54da965a7 | ||
|
|
26c4bea4fd | ||
|
|
0717612b4b | ||
|
|
260c110d05 | ||
|
|
3c6f0b26af | ||
|
|
87f2716da8 | ||
|
|
abfa09df51 | ||
|
|
59fd8247b4 | ||
|
|
d635fdda41 | ||
|
|
66a60eea64 | ||
|
|
94c7e0674d | ||
|
|
3a77abc8d2 | ||
|
|
004d5db2c3 | ||
|
|
fb8984c947 | ||
|
|
e98a80c803 | ||
|
|
46a52b3e3e | ||
|
|
5d72d896b8 | ||
|
|
6d5b2c3d12 | ||
|
|
bbecb4d0bd | ||
|
|
3454705825 | ||
|
|
1bb99a6bc8 | ||
|
|
b6f5d7183f | ||
|
|
ee78dd308b | ||
|
|
3f64310d45 | ||
|
|
dd2ff63019 | ||
|
|
993320655e | ||
|
|
03242e8984 | ||
|
|
ccbc785499 |
3695 changed files with 468729 additions and 113636 deletions
6
.babelrc
6
.babelrc
|
|
@ -9,16 +9,10 @@
|
||||||
"chrome/content/zotero/xpcom/citeproc.js",
|
"chrome/content/zotero/xpcom/citeproc.js",
|
||||||
"chrome/content/ace/*",
|
"chrome/content/ace/*",
|
||||||
"chrome/content/scaffold/templates/*",
|
"chrome/content/scaffold/templates/*",
|
||||||
"resource/react.js",
|
|
||||||
"resource/react-dom.js",
|
|
||||||
"resource/react-virtualized.js",
|
"resource/react-virtualized.js",
|
||||||
"test/resource/*.js"
|
"test/resource/*.js"
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@babel/plugin-proposal-class-properties",
|
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
|
||||||
"@babel/plugin-proposal-optional-chaining",
|
|
||||||
"@babel/plugin-proposal-unicode-property-regex",
|
|
||||||
[
|
[
|
||||||
"transform-es2015-modules-commonjs",
|
"transform-es2015-modules-commonjs",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
build/*
|
|
||||||
chrome/content/zotero/xpcom/citeproc.js
|
|
||||||
chrome/content/zotero/xpcom/isbn.js
|
|
||||||
chrome/content/zotero/xpcom/rdf/*
|
|
||||||
chrome/content/zotero/xpcom/xregexp/*
|
|
||||||
chrome/content/zotero/xpcom/translation/tlds.js
|
|
||||||
chrome/skin/default/zotero/timeline/bundle.js
|
|
||||||
chrome/skin/default/zotero/timeline/timeline-api.js
|
|
||||||
resource/bluebird/*
|
|
||||||
resource/classnames.js
|
|
||||||
resource/csl-validator.js
|
|
||||||
resource/jspath.js
|
|
||||||
resource/prop-types.js
|
|
||||||
resource/react*
|
|
||||||
resource/schema/connectorTypeSchemaData.js
|
|
||||||
resource/tinymce/*
|
|
||||||
test/resource/*
|
|
||||||
translators/*
|
|
||||||
44
.eslintrc
44
.eslintrc
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"Zotero": false,
|
|
||||||
"ZOTERO_CONFIG": false,
|
|
||||||
"AddonManager": false,
|
|
||||||
"Cc": false,
|
|
||||||
"Ci": false,
|
|
||||||
"Components": false,
|
|
||||||
"ConcurrentCaller": false,
|
|
||||||
"ctypes": false,
|
|
||||||
"OS": false,
|
|
||||||
"PluralForm": false,
|
|
||||||
"Services": false,
|
|
||||||
"XPCOMUtils": false,
|
|
||||||
"XRegExp": false
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"@zotero",
|
|
||||||
"plugin:react/recommended"
|
|
||||||
],
|
|
||||||
"parser": "@babel/eslint-parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2018,
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
},
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"react",
|
|
||||||
"@babel"
|
|
||||||
],
|
|
||||||
"settings": {
|
|
||||||
"react": {
|
|
||||||
"version": "17.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rules": {}
|
|
||||||
}
|
|
||||||
4
.gitattributes
vendored
4
.gitattributes
vendored
|
|
@ -1 +1,5 @@
|
||||||
*.sql text eol=lf
|
*.sql text eol=lf
|
||||||
|
app/win/zotero.exe.tar.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
app/mac/updater.tar.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
app/win/updater.exe.tar.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
app/linux/updater.tar.xz filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
|
||||||
9
.github/ISSUE_TEMPLATE.md
vendored
9
.github/ISSUE_TEMPLATE.md
vendored
|
|
@ -1,9 +0,0 @@
|
||||||
**READ THIS BEFORE CREATING AN ISSUE**
|
|
||||||
|
|
||||||
Zotero does not use GitHub Issues for bug reports or feature requests.
|
|
||||||
|
|
||||||
Please post all such requests to the Zotero Forums at https://forums.zotero.org, where Zotero developers and many others can help. For confirmed bugs or agreed-upon changes, Zotero developers will create new issues in the relevant repositories.
|
|
||||||
|
|
||||||
Development questions involving code, APIs, or other technical topics can be posted to the zotero-dev mailing list at http://groups.google.com/group/zotero-dev.
|
|
||||||
|
|
||||||
See https://www.zotero.org/support/zotero_support for more information on how Zotero support works.
|
|
||||||
447
.github/workflows/ci.yml
vendored
447
.github/workflows/ci.yml
vendored
|
|
@ -1,85 +1,364 @@
|
||||||
name: CI
|
name: CI
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
# Monthly, to catch runner image and OS changes
|
||||||
|
- cron: '0 6 1 * *'
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
# Decide whether to run the network-filesystem and Windows tests: always for manual and
|
||||||
name: Build, Upload, Test
|
# scheduled runs, and otherwise only when the changes touch the Gecko version, the files
|
||||||
|
# responsible for network-filesystem database handling, or (for Windows) the files that
|
||||||
|
# make up the Windows build
|
||||||
|
changes:
|
||||||
|
name: Detect changes
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: >
|
||||||
|
github.event_name != 'pull_request'
|
||||||
|
|| github.event.pull_request.head.repo.full_name != github.repository
|
||||||
|
outputs:
|
||||||
|
network: ${{ steps.check.outputs.network }}
|
||||||
|
windows: ${{ steps.check.outputs.windows }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- name: Check for network-filesystem-related changes
|
||||||
|
id: check
|
||||||
|
env:
|
||||||
|
EVENT: ${{ github.event_name }}
|
||||||
|
REPO: ${{ github.repository }}
|
||||||
|
SHA: ${{ github.sha }}
|
||||||
|
BEFORE: ${{ github.event.before }}
|
||||||
|
BASE: ${{ github.event.pull_request.base.sha }}
|
||||||
|
run: |
|
||||||
|
network=false
|
||||||
|
windows=false
|
||||||
|
if [[ "$EVENT" == "workflow_dispatch" || "$EVENT" == "schedule" ]]; then
|
||||||
|
network=true
|
||||||
|
windows=true
|
||||||
|
else
|
||||||
|
base="$BASE"
|
||||||
|
[[ -z "$base" ]] && base="$BEFORE"
|
||||||
|
git init -q repo && cd repo
|
||||||
|
git remote add origin "https://github.com/$REPO"
|
||||||
|
git fetch -q --depth 1 origin "$SHA"
|
||||||
|
# Run the tests if the base of the change can't be determined (e.g., a new
|
||||||
|
# branch or an unfetchable pre-force-push commit)
|
||||||
|
if [[ -z "$base" || "$base" == 0000000000000000000000000000000000000000 ]] \
|
||||||
|
|| ! git fetch -q --depth 1 origin "$base" 2>/dev/null; then
|
||||||
|
network=true
|
||||||
|
windows=true
|
||||||
|
else
|
||||||
|
files=$(git diff --name-only "$base" "$SHA")
|
||||||
|
if grep -qE '^(app/config\.sh|chrome/content/zotero/xpcom/(db|file)\.js|\.github/workflows/ci\.yml)$' <<< "$files"; then
|
||||||
|
network=true
|
||||||
|
windows=true
|
||||||
|
fi
|
||||||
|
if grep -qE '^app/(win/|build\.sh$|scripts/(dir_build|fetch_xulrunner|prepare_build)$)' <<< "$files"; then
|
||||||
|
windows=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "network=$network" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "windows=$windows" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test (${{ matrix.shard }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
|
needs: changes
|
||||||
|
# Same-repo PRs are covered by the push run, so run pull_request jobs only for forks
|
||||||
|
if: >
|
||||||
|
github.event_name != 'pull_request'
|
||||||
|
|| github.event.pull_request.head.repo.full_name != github.repository
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
# Numbered shards split the full suite. 'smb' and 'nfs' run the db and file tests
|
||||||
|
# with the test data directory on a loopback CIFS or NFS mount, so that connection
|
||||||
|
# initialization itself runs against a network filesystem, which is where
|
||||||
|
# network-filesystem failures (startup crashes and hangs) occur. The network shards
|
||||||
|
# run only when the 'changes' job detects relevant changes.
|
||||||
|
shard: ${{ fromJSON(needs.changes.outputs.network == 'true'
|
||||||
|
&& '["1", "2", "3", "4", "smb", "nfs"]'
|
||||||
|
|| '["1", "2", "3", "4"]') }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
lfs: true
|
||||||
|
|
||||||
- name: Install Node
|
- name: Install Node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 24
|
||||||
#cache: npm
|
#cache: npm
|
||||||
|
|
||||||
# On GitHub
|
|
||||||
- name: Install xvfb
|
|
||||||
if: env.ACT != 'true'
|
|
||||||
run: sudo apt update && sudo apt install -y xvfb
|
|
||||||
|
|
||||||
# Local via act
|
# Local via act
|
||||||
- name: Install packages for act
|
- name: Install packages for act
|
||||||
if: env.ACT == 'true'
|
if: env.ACT == 'true'
|
||||||
run: apt update && apt install -y zstd xvfb dbus-x11 libgtk-3-0 libx11-xcb1 libdbus-glib-1-2 libxt6
|
run: apt update && apt install -y zstd xvfb dbus-x11 libgtk-3-0 libx11-xcb1 libdbus-glib-1-2 libxt6
|
||||||
|
|
||||||
- name: Cache Firefox
|
- name: Cache xulrunner
|
||||||
id: firefox-cache
|
id: xulrunner-cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: firefox-x86_64
|
path: app/xulrunner/firefox-x86_64
|
||||||
key: firefox-60.9.0esr
|
key: xulrunner-${{ hashFiles('app/config.sh', 'app/scripts/fetch_xulrunner') }}
|
||||||
|
|
||||||
- name: Download Firefox
|
- name: Fetch xulrunner
|
||||||
if: steps.firefox-cache.outputs.cache-hit != 'true'
|
if: steps.xulrunner-cache.outputs.cache-hit != 'true'
|
||||||
run: wget -O tarball "https://zotero-download.s3.us-east-1.amazonaws.com/dev/firefox-60.9.0esr-x86_64-modified.tar.gz"
|
run: app/scripts/fetch_xulrunner -p l
|
||||||
|
|
||||||
- name: Extract Firefox
|
|
||||||
if: steps.firefox-cache.outputs.cache-hit != 'true'
|
|
||||||
run: tar xvf tarball
|
|
||||||
|
|
||||||
- name: Cache Node modules
|
- name: Cache Node modules
|
||||||
id: node-cache
|
id: node-cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: node_modules
|
path: node_modules
|
||||||
key: node-modules-${{ hashFiles('package-lock.json') }}
|
key: node-modules-24-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
- name: Install Node modules
|
- name: Install Node modules
|
||||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Build Zotero
|
- name: Build Zotero
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
# Currently necessary for document-worker Webpack: https://stackoverflow.com/a/69746937
|
||||||
- name: Upload deployment ZIP
|
|
||||||
if: |
|
|
||||||
env.ACT != 'true'
|
|
||||||
&& github.repository == 'zotero/zotero'
|
|
||||||
&& github.event_name == 'push'
|
|
||||||
&& (github.ref == 'refs/heads/master' || endsWith(github.ref, '-hotfix') || github.ref == 'refs/heads/gh-actions-ci-test')
|
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
NODE_OPTIONS: --openssl-legacy-provider
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
||||||
|
# Create deployment ZIP from the build output, then replace build/ with the
|
||||||
|
# unzipped contents so that tests run against the same artifact that gets
|
||||||
|
# deployed. This catches problems that only manifest after a zip round-trip
|
||||||
|
# (e.g., resolved symlinks, missing files).
|
||||||
|
- name: Create deployment ZIP
|
||||||
run: |
|
run: |
|
||||||
mkdir build-zip
|
|
||||||
cd build
|
cd build
|
||||||
zip -r ../build-zip/$GITHUB_SHA.zip *
|
zip -r ../build.zip *
|
||||||
cd ..
|
cd ..
|
||||||
sudo gem install --no-document dpl dpl-s3
|
|
||||||
dpl --provider=s3 --bucket=zotero-download --local-dir=build-zip --upload-dir=ci/client --acl=public-read --skip_cleanup=true
|
- name: Replace build with ZIP contents
|
||||||
|
run: |
|
||||||
|
rm -rf build
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
unzip ../build.zip
|
||||||
|
|
||||||
|
- name: Set up SMB share
|
||||||
|
if: matrix.shard == 'smb'
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: |
|
||||||
|
sudo apt install -y --no-install-recommends samba cifs-utils
|
||||||
|
sudo mkdir -p /srv/zotero-smb /mnt/zotero-smb
|
||||||
|
sudo chown $(whoami) /srv/zotero-smb
|
||||||
|
sudo tee -a /etc/samba/smb.conf > /dev/null <<EOF
|
||||||
|
[ztest]
|
||||||
|
path = /srv/zotero-smb
|
||||||
|
read only = no
|
||||||
|
EOF
|
||||||
|
(echo smbtestpass; echo smbtestpass) | sudo smbpasswd -s -a $(whoami)
|
||||||
|
sudo systemctl restart smbd
|
||||||
|
sudo mount -t cifs //127.0.0.1/ztest /mnt/zotero-smb \
|
||||||
|
-o user=$(whoami),pass=smbtestpass,vers=3.0,uid=$(id -u),gid=$(id -g)
|
||||||
|
|
||||||
|
- name: Set up NFS share
|
||||||
|
if: matrix.shard == 'nfs'
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: |
|
||||||
|
sudo apt install -y --no-install-recommends nfs-kernel-server
|
||||||
|
sudo mkdir -p /srv/zotero-nfs /mnt/zotero-nfs
|
||||||
|
sudo chown $(whoami) /srv/zotero-nfs
|
||||||
|
echo "/srv/zotero-nfs localhost(rw,no_subtree_check,insecure)" | sudo tee -a /etc/exports
|
||||||
|
sudo exportfs -ra
|
||||||
|
sudo mount -t nfs4 localhost:/srv/zotero-nfs /mnt/zotero-nfs
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: xvfb-run test/runtests.sh -x firefox-x86_64/firefox -f
|
if: matrix.shard != 'smb' && matrix.shard != 'nfs'
|
||||||
|
run: xvfb-run test/runtests.sh -f -r 3 -p ${{ matrix.shard }}/4
|
||||||
|
|
||||||
|
# The step timeout turns a startup hang into a failure
|
||||||
|
- name: Run tests on network share
|
||||||
|
if: matrix.shard == 'smb' || matrix.shard == 'nfs'
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TMPDIR=/mnt/zotero-${{ matrix.shard }} xvfb-run test/runtests.sh -f -r 3 -b db file
|
||||||
|
|
||||||
|
# Run the db and file tests on macOS with the test data directory on a loopback NFS
|
||||||
|
# mount. On macOS, SQLite selects locking methods without shared-memory support on
|
||||||
|
# network filesystems, which is what the network-filesystem database handling has to
|
||||||
|
# detect and handle, so this runs the real code path that crashed on SMB/NFS/sshfs
|
||||||
|
# data directories.
|
||||||
|
test-mac:
|
||||||
|
name: Test (macOS NFS)
|
||||||
|
runs-on: macos-15
|
||||||
|
timeout-minutes: 30
|
||||||
|
needs: changes
|
||||||
|
if: >
|
||||||
|
needs.changes.outputs.network == 'true'
|
||||||
|
&& (github.event_name != 'pull_request'
|
||||||
|
|| github.event.pull_request.head.repo.full_name != github.repository)
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
lfs: true
|
||||||
|
|
||||||
|
- name: Install Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
|
||||||
|
- name: Cache xulrunner
|
||||||
|
id: xulrunner-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: app/xulrunner/Firefox.app
|
||||||
|
key: xulrunner-mac-${{ hashFiles('app/config.sh', 'app/scripts/fetch_xulrunner') }}
|
||||||
|
|
||||||
|
- name: Fetch xulrunner
|
||||||
|
if: steps.xulrunner-cache.outputs.cache-hit != 'true'
|
||||||
|
run: app/scripts/fetch_xulrunner -p m
|
||||||
|
|
||||||
|
- name: Cache Node modules
|
||||||
|
id: node-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: node_modules
|
||||||
|
key: node-modules-mac-24-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
|
- name: Install Node modules
|
||||||
|
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Build Zotero
|
||||||
|
run: npm run build
|
||||||
|
# Currently necessary for document-worker Webpack: https://stackoverflow.com/a/69746937
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --openssl-legacy-provider
|
||||||
|
|
||||||
|
- name: Set up NFS share
|
||||||
|
run: |
|
||||||
|
sudo mkdir -p /private/var/zotero-nfs
|
||||||
|
sudo chown $(whoami) /private/var/zotero-nfs
|
||||||
|
echo "/private/var/zotero-nfs -mapall=$(whoami) localhost" | sudo tee /etc/exports
|
||||||
|
sudo nfsd enable || sudo nfsd start
|
||||||
|
sleep 2
|
||||||
|
showmount -e localhost
|
||||||
|
mkdir -p "$HOME/zotero-nfs"
|
||||||
|
sudo mount_nfs -o vers=3 localhost:/private/var/zotero-nfs "$HOME/zotero-nfs"
|
||||||
|
|
||||||
|
# The step timeout turns a startup hang into a failure
|
||||||
|
- name: Run tests on network share
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TMPDIR="$HOME/zotero-nfs" test/runtests.sh -f -r 3 -b db file
|
||||||
|
|
||||||
|
# Boot the Windows build -- which uses custom-built Firefox components (xul.dll) rather
|
||||||
|
# than stock Mozilla binaries -- and run the db and file tests. A Gecko bump commit
|
||||||
|
# updates the custom-component hashes in config.sh along with the version, so this
|
||||||
|
# tests each new set of custom components.
|
||||||
|
test-win:
|
||||||
|
name: Test (Windows ${{ matrix.arch }})
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 40
|
||||||
|
needs: changes
|
||||||
|
if: >
|
||||||
|
needs.changes.outputs.windows == 'true'
|
||||||
|
&& (github.event_name != 'pull_request'
|
||||||
|
|| github.event.pull_request.head.repo.full_name != github.repository)
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: x64
|
||||||
|
os: windows-latest
|
||||||
|
- arch: arm64
|
||||||
|
os: windows-11-arm
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
steps:
|
||||||
|
# The repository contains symlinks, which Git checks out as plain files on Windows
|
||||||
|
# by default, breaking the build
|
||||||
|
- name: Enable symlinks
|
||||||
|
run: git config --global core.symlinks true
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
lfs: true
|
||||||
|
|
||||||
|
- name: Install Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
|
||||||
|
# Git Bash has unzip but not zip, which fetch_xulrunner needs to repack omni.ja
|
||||||
|
- name: Install zip
|
||||||
|
run: choco install zip --no-progress -y
|
||||||
|
|
||||||
|
- name: Cache xulrunner
|
||||||
|
id: xulrunner-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: app/xulrunner/firefox-win-${{ matrix.arch }}
|
||||||
|
key: xulrunner-win-${{ matrix.arch }}-${{ hashFiles('app/config.sh', 'app/scripts/fetch_xulrunner') }}
|
||||||
|
|
||||||
|
- name: Fetch xulrunner
|
||||||
|
if: steps.xulrunner-cache.outputs.cache-hit != 'true'
|
||||||
|
run: app/scripts/fetch_xulrunner -p w -a ${{ matrix.arch }}
|
||||||
|
|
||||||
|
- name: Cache Node modules
|
||||||
|
id: node-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: node_modules
|
||||||
|
key: node-modules-win-24-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
|
- name: Install Node modules
|
||||||
|
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
# Committed symlinks point into node_modules, which doesn't exist at checkout time,
|
||||||
|
# so Git creates the directory ones with the wrong symlink type on Windows. Recreate
|
||||||
|
# them now that the targets exist.
|
||||||
|
- name: Recreate symlinks
|
||||||
|
run: |
|
||||||
|
git ls-files -s | awk '$1 == 120000 { print $4 }' | xargs rm
|
||||||
|
git checkout -- .
|
||||||
|
|
||||||
|
- name: Build Zotero
|
||||||
|
run: npm run build
|
||||||
|
# Currently necessary for document-worker Webpack: https://stackoverflow.com/a/69746937
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --openssl-legacy-provider
|
||||||
|
|
||||||
|
# The step timeout turns a startup hang into a failure
|
||||||
|
- name: Run tests
|
||||||
|
timeout-minutes: 15
|
||||||
|
run: test/runtests.sh -f -r 3 -b -x app/staging/Zotero_win-${{ matrix.arch }}/zotero.exe db file
|
||||||
|
|
||||||
|
utilities:
|
||||||
|
name: Utilities Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: >
|
||||||
|
github.event_name != 'pull_request'
|
||||||
|
|| github.event.pull_request.head.repo.full_name != github.repository
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
|
||||||
- name: Cache utilities Node modules
|
- name: Cache utilities Node modules
|
||||||
id: utilities-node-cache
|
id: utilities-node-cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: chrome/content/zotero/xpcom/utilities/node_modules
|
path: chrome/content/zotero/xpcom/utilities/node_modules
|
||||||
key: utilities-node-modules-${{ hashFiles('chrome/content/zotero/xpcom/utilities/package-lock.json') }}
|
key: utilities-node-modules-24-${{ hashFiles('chrome/content/zotero/xpcom/utilities/package-lock.json') }}
|
||||||
|
|
||||||
- name: Install utilities Node modules
|
- name: Install utilities Node modules
|
||||||
if: steps.utilities-node-cache.outputs.cache-hit != 'true'
|
if: steps.utilities-node-cache.outputs.cache-hit != 'true'
|
||||||
|
|
@ -88,3 +367,73 @@ jobs:
|
||||||
- name: Run utilities tests
|
- name: Run utilities tests
|
||||||
run: |
|
run: |
|
||||||
npm test --prefix chrome/content/zotero/xpcom/utilities -- -j resource/schema/global/schema.json
|
npm test --prefix chrome/content/zotero/xpcom/utilities -- -j resource/schema/global/schema.json
|
||||||
|
|
||||||
|
# Build deployment ZIPs from main, version branches (e.g., 9.0, 10.0), and *-hotfix branches
|
||||||
|
deploy:
|
||||||
|
name: Build, Upload
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'push' && github.repository == 'zotero/zotero'
|
||||||
|
steps:
|
||||||
|
- name: Check if deployment branch
|
||||||
|
id: check-deploy
|
||||||
|
if: env.ACT != 'true'
|
||||||
|
run: |
|
||||||
|
branch="${GITHUB_REF#refs/heads/}"
|
||||||
|
if [[ "$branch" == "main" || "$branch" =~ ^[0-9]+\.[0-9]+$ || "$branch" == *-hotfix ]]; then
|
||||||
|
echo "deploy=true" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
lfs: true
|
||||||
|
|
||||||
|
- name: Install Node
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 24
|
||||||
|
|
||||||
|
- name: Cache Node modules
|
||||||
|
id: node-cache
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: node_modules
|
||||||
|
key: node-modules-24-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
|
- name: Install Node modules
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true' && steps.node-cache.outputs.cache-hit != 'true'
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Build Zotero
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
run: npm run build
|
||||||
|
# Currently necessary for document-worker Webpack: https://stackoverflow.com/a/69746937
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: --openssl-legacy-provider
|
||||||
|
|
||||||
|
- name: Create deployment ZIP
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
zip -r ../build.zip *
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
- uses: ruby/setup-ruby@v1
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
with:
|
||||||
|
ruby-version: '3.3'
|
||||||
|
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||||
|
|
||||||
|
- name: Upload deployment ZIP
|
||||||
|
if: steps.check-deploy.outputs.deploy == 'true'
|
||||||
|
env:
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
run: |
|
||||||
|
mkdir build-zip
|
||||||
|
cp build.zip build-zip/$GITHUB_SHA.zip
|
||||||
|
gem install --no-document dpl -v '>= 2.0'
|
||||||
|
dpl s3 --bucket zotero-download --local_dir build-zip --upload_dir ci/client --acl public_read
|
||||||
|
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
build
|
build/
|
||||||
.signatures.json
|
.signatures.json
|
||||||
tmp
|
tmp
|
||||||
|
app/win/codesign
|
||||||
|
|
|
||||||
21
.gitmodules
vendored
21
.gitmodules
vendored
|
|
@ -18,10 +18,6 @@
|
||||||
path = test/resource/mocha
|
path = test/resource/mocha
|
||||||
url = https://github.com/mochajs/mocha.git
|
url = https://github.com/mochajs/mocha.git
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "test/resource/chai-as-promised"]
|
|
||||||
path = test/resource/chai-as-promised
|
|
||||||
url = https://github.com/domenic/chai-as-promised.git
|
|
||||||
branch = master
|
|
||||||
[submodule "resource/schema/global"]
|
[submodule "resource/schema/global"]
|
||||||
path = resource/schema/global
|
path = resource/schema/global
|
||||||
url = https://github.com/zotero/zotero-schema.git
|
url = https://github.com/zotero/zotero-schema.git
|
||||||
|
|
@ -30,12 +26,12 @@
|
||||||
path = resource/SingleFile
|
path = resource/SingleFile
|
||||||
url = https://github.com/gildas-lormeau/SingleFile.git
|
url = https://github.com/gildas-lormeau/SingleFile.git
|
||||||
[submodule "pdf-reader"]
|
[submodule "pdf-reader"]
|
||||||
path = pdf-reader
|
path = reader
|
||||||
url = https://github.com/zotero/pdf-reader.git
|
url = https://github.com/zotero/reader.git
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "pdf-worker"]
|
[submodule "pdf-worker"]
|
||||||
path = pdf-worker
|
path = document-worker
|
||||||
url = https://github.com/zotero/pdf-worker.git
|
url = https://github.com/zotero/document-worker.git
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "note-editor"]
|
[submodule "note-editor"]
|
||||||
path = note-editor
|
path = note-editor
|
||||||
|
|
@ -47,3 +43,12 @@
|
||||||
[submodule "chrome/content/zotero/xpcom/translate"]
|
[submodule "chrome/content/zotero/xpcom/translate"]
|
||||||
path = chrome/content/zotero/xpcom/translate
|
path = chrome/content/zotero/xpcom/translate
|
||||||
url = https://github.com/zotero/translate.git
|
url = https://github.com/zotero/translate.git
|
||||||
|
[submodule "app/modules/zotero-word-for-mac-integration"]
|
||||||
|
path = app/modules/zotero-word-for-mac-integration
|
||||||
|
url = https://github.com/zotero/zotero-word-for-mac-integration.git
|
||||||
|
[submodule "app/modules/zotero-word-for-windows-integration"]
|
||||||
|
path = app/modules/zotero-word-for-windows-integration
|
||||||
|
url = https://github.com/zotero/zotero-word-for-windows-integration.git
|
||||||
|
[submodule "app/modules/zotero-libreoffice-integration"]
|
||||||
|
path = app/modules/zotero-libreoffice-integration
|
||||||
|
url = https://github.com/zotero/zotero-libreoffice-integration.git
|
||||||
|
|
|
||||||
110
CLAUDE.md
Normal file
110
CLAUDE.md
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Zotero is a Firefox-based desktop research management application. It runs as a XUL/XHTML application on a Mozilla platform (not Electron, not a web app). The UI uses a mix of XUL/XHTML, custom elements (Web Components), and React components.
|
||||||
|
|
||||||
|
## Build & Development Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install # Install dependencies
|
||||||
|
npm run build # Full build (Babel transpile JS/JSX, compile SCSS, browserify, symlink)
|
||||||
|
npm run clean-build # Clean build output and rebuild
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
Tests run inside a built Zotero application instance via `test/runtests.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test/runtests.sh # Run all tests
|
||||||
|
test/runtests.sh item # Run a single test file (omit "Test" and .js extension)
|
||||||
|
test/runtests.sh item collections # Run multiple test files
|
||||||
|
test/runtests.sh -g "pattern" # Run only tests matching a grep pattern
|
||||||
|
test/runtests.sh -f # Stop after first failure
|
||||||
|
test/runtests.sh -s item # Start at a specific test file
|
||||||
|
test/runtests.sh -e item # End at a specific test file
|
||||||
|
test/runtests.sh -c # Open JS console, don't quit on completion
|
||||||
|
test/runtests.sh -b # Skip bundled translator/style installation (for faster startup when not necessary)
|
||||||
|
test/runtests.sh -d 5 # Enable debug logging (level 1-5; default is 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests use Mocha + Chai (assert style) + Sinon. Test files live in `test/tests/` and follow the naming convention `<module>Test.js`. Test helpers are in `test/content/support.js`.
|
||||||
|
|
||||||
|
The test runner automatically triggers `npm run build` if the watch process isn't running, so it's not necessary to manually run a build before running tests.
|
||||||
|
|
||||||
|
Tips:
|
||||||
|
|
||||||
|
- Pass flags before test names (e.g., `test/runtests.sh -f item`).
|
||||||
|
- `-f` should almost always be used, since test failures can cause later spurious test failures.
|
||||||
|
- To view debug logging for a specific test when running multiple tests, add `Zotero.Debug.init(1)` at the beginning of the test and run with `-d 5`.
|
||||||
|
|
||||||
|
|
||||||
|
### Linting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx eslint <file> # Lint a specific file
|
||||||
|
```
|
||||||
|
|
||||||
|
ESLint v9 flat config is in `eslint.config.mjs`. Uses `@zotero/eslint-config`, Babel parser, and React plugin. Currently, the code base is not fully linted, so only worry about issues with new or modified code lines.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Core Layers
|
||||||
|
|
||||||
|
- **XPCOM modules** (`chrome/content/zotero/xpcom/`) -- Core business logic. Loaded sequentially by `chrome/content/zotero/zotero.mjs`. All modules attach to the global `Zotero` namespace (e.g., `Zotero.Items`, `Zotero.Sync.Runner`).
|
||||||
|
|
||||||
|
- **Data model** (`chrome/content/zotero/xpcom/data/`) -- ORM-like classes for database entities. `Zotero.DataObject` is the base class; `Zotero.Item`, `Zotero.Collection`, `Zotero.Search`, `Zotero.Library`, etc. extend it. Plural classes (`Zotero.Items`, `Zotero.Collections`) manage object caches and queries. Data objects use an async `saveTx()` pattern for persistence.
|
||||||
|
|
||||||
|
- **Database** (`chrome/content/zotero/xpcom/db.js`) -- SQLite via Mozilla's mozStorage API. Accessed through `Zotero.DB.queryAsync()`, `Zotero.DB.executeTransaction()`.
|
||||||
|
|
||||||
|
- **Sync system** (`chrome/content/zotero/xpcom/sync/`) -- `syncRunner.js` orchestrates sync. `syncEngine.js` handles object-level sync logic. `syncAPIClient.js` communicates with the Zotero API server. `syncLocal.js` manages local sync state. Similar `storage*` files for file syncing, along with zfs.js (Zotero Storage) and webdav.js (WebDAV).
|
||||||
|
|
||||||
|
- **HTTP server** (`chrome/content/zotero/xpcom/server/`) -- Local HTTP server for browser connector integration and local API.
|
||||||
|
|
||||||
|
### UI Layers
|
||||||
|
|
||||||
|
- **Main window**: `chrome/content/zotero/zoteroPane.xhtml` + `zoteroPane.js`
|
||||||
|
- **Custom elements** (`chrome/content/zotero/elements/`) -- XUL custom elements inheriting from `XULElementBase` (defined in `elements/base.js`), which provides lifecycle helpers (`init()`, `destroy()`, `content` getter for templates). Registered via `customElements.define()`.
|
||||||
|
- **React components** (`chrome/content/zotero/components/`) -- Used for complex interactive UI (tag selector, virtualized table, item tree, collection tree). Major tree views are `itemTree.jsx` and `collectionTree.jsx`.
|
||||||
|
- **SCSS styles** (`scss/`) -- Compiled to CSS. Platform-specific overrides in `scss/mac/`, `scss/win/`, `scss/linux/`.
|
||||||
|
- **Localization** -- Fluent (`.ftl` files) in `chrome/locale/en-US/zotero/`. Accessed via `data-l10n-id` attributes or `Zotero.getString()` for legacy `.properties` strings. All new strings must be added to `.ftl` files -- do not add new strings to `.properties` or `.dtd` files.
|
||||||
|
|
||||||
|
### Submodules
|
||||||
|
|
||||||
|
Several features are developed in separate repos and included as Git submodules:
|
||||||
|
|
||||||
|
- `reader/` -- PDF/EPUB/snapshot reader with annotations
|
||||||
|
- `note-editor/` -- Rich text note editor
|
||||||
|
- `document-worker/` -- PDF processing (extraction, manipulation)
|
||||||
|
- `translators/` -- 760+ web translators for importing metadata from websites
|
||||||
|
- `styles/` -- CSL citation styles
|
||||||
|
- `chrome/content/zotero/xpcom/utilities/` -- Shared utility library
|
||||||
|
- `chrome/content/zotero/xpcom/translate/` -- Translation framework
|
||||||
|
- `resource/SingleFile/` -- Web page archiving
|
||||||
|
|
||||||
|
### Build System (`js-build/`)
|
||||||
|
|
||||||
|
Custom Node.js build system (not Webpack). `js-build/config.js` defines what gets built:
|
||||||
|
- **JS/JSX files** in `chrome/`, `components/`, `defaults/`, `test/` are transpiled via Babel (React JSX, CommonJS modules)
|
||||||
|
- **SCSS files** in `scss/` and `chrome/skin/` are compiled with Dart Sass
|
||||||
|
- **Browserify** bundles select npm packages (react-select, sinon, url) for use in the XUL environment
|
||||||
|
- **Symlinks** connect source files and submodules into the `build/` directory
|
||||||
|
- The built app reads from `build/`, not directly from source
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
- Tabs for indentation, not spaces
|
||||||
|
- Use `let` instead of `const` except for true scalar constants (e.g., `const MAX_SECONDS = 5 * 60;`)
|
||||||
|
- No cuddled braces (opening brace on same line, but `else`/`catch`/etc. on their own line)
|
||||||
|
- Use two hyphens `--` in comments, not an em dash
|
||||||
|
- Indent blank lines to match surrounding indentation level
|
||||||
|
- Objects attach to the `Zotero` global namespace rather than using ES module exports
|
||||||
|
- Async code uses `async`/`await` throughout
|
||||||
|
- Mozilla/XPCOM APIs are available globally: `Cc`, `Ci`, `Cu`, `Cr`, `Services`, `ChromeUtils`, `IOUtils`, `PathUtils`
|
||||||
|
|
||||||
|
## Translators
|
||||||
|
|
||||||
|
See `translators/CLAUDE.md` for guidelines. Key rules: **never** generate translators from scratch, **never** generate UUIDs, **never** generate test cases -- all of these must be done through Zotero's Scaffold tool.
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
## Bug Reports and Feature Requests
|
## Bug Reports and Feature Requests
|
||||||
|
|
||||||
Zotero does not use GitHub Issues for bug reports or feature requests. Please post all such requests to the [Zotero Forums](https://forums.zotero.org), where Zotero developers and many others can help. See [How Zotero Support Works](https://www.zotero.org/support/zotero_support) for more information.
|
Zotero does not use GitHub Issues for bug reports, feature requests, or support questions. Please post all such requests to the [Zotero Forums](https://forums.zotero.org), where Zotero developers and many others can help. See [How Zotero Support Works](https://www.zotero.org/support/zotero_support) for more information.
|
||||||
|
|
||||||
For confirmed bugs or agreed-upon changes, Zotero developers will create new issues in the relevant repositories.
|
For confirmed bugs or agreed-upon changes, Zotero developers will create new issues in the relevant repositories.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@ Zotero
|
||||||
|
|
||||||
Please post feature requests or bug reports to the [Zotero Forums](https://forums.zotero.org/). If you're having trouble with Zotero, see [Getting Help](https://www.zotero.org/support/getting_help).
|
Please post feature requests or bug reports to the [Zotero Forums](https://forums.zotero.org/). If you're having trouble with Zotero, see [Getting Help](https://www.zotero.org/support/getting_help).
|
||||||
|
|
||||||
For more information on how to use this source code, see the [Zotero wiki](https://www.zotero.org/support/dev/source_code).
|
For more information on how to use this source code, see the [Zotero documentation](https://www.zotero.org/support/dev/source_code).
|
||||||
|
|
|
||||||
12
app/.gitignore
vendored
Normal file
12
app/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
*~
|
||||||
|
cache
|
||||||
|
config-custom.sh
|
||||||
|
dist
|
||||||
|
lastrev
|
||||||
|
staging
|
||||||
|
tmp
|
||||||
|
xulrunner
|
||||||
|
win/resource_hacker
|
||||||
|
win/firefox-*.win32.zip
|
||||||
|
win/firefox-*.win64.zip
|
||||||
|
win/firefox-*.win64-aarch64.zip
|
||||||
4
app/README.md
Normal file
4
app/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Zotero Standalone build utility
|
||||||
|
These files are used to bundle the [Zotero core](https://github.com/zotero/zotero) into distributable bundles for Mac, Windows, and Linux.
|
||||||
|
|
||||||
|
Instructions for building and packaging are available on the [Zotero wiki](https://www.zotero.org/support/dev/client_coding/building_the_standalone_client).
|
||||||
18
app/assets/application.ini
Normal file
18
app/assets/application.ini
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[App]
|
||||||
|
Vendor=Zotero
|
||||||
|
Name=Zotero
|
||||||
|
Version={{VERSION}}
|
||||||
|
BuildID={{BUILDID}}
|
||||||
|
Copyright=Copyright (c) 2006-2025 Contributors
|
||||||
|
ID=zotero@zotero.org
|
||||||
|
|
||||||
|
[Gecko]
|
||||||
|
MinVersion=153.0
|
||||||
|
MaxVersion=153.99.*
|
||||||
|
|
||||||
|
[XRE]
|
||||||
|
EnableExtensionManager=1
|
||||||
|
EnableProfileMigrator=1
|
||||||
|
|
||||||
|
[AppUpdate]
|
||||||
|
URL=https://www.zotero.org/download/client/update/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/update.xml
|
||||||
1
app/assets/branding/locale/brand.dtd
Normal file
1
app/assets/branding/locale/brand.dtd
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<!ENTITY brandShortName "Zotero">
|
||||||
8
app/assets/branding/locale/brand.ftl
Normal file
8
app/assets/branding/locale/brand.ftl
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
-brand-shorter-name = Zotero
|
||||||
|
-brand-short-name = Zotero
|
||||||
|
-brand-full-name = Zotero
|
||||||
|
-brand-product-name = Zotero
|
||||||
|
-vendor-short-name = Zotero
|
||||||
|
-app-name = Zotero
|
||||||
|
-subscription-name = Zotero Storage
|
||||||
|
trademarkInfo = Zotero is a trademark of the Corporation for Digital Scholarship.
|
||||||
3
app/assets/branding/locale/brand.properties
Normal file
3
app/assets/branding/locale/brand.properties
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
brandShorterName=Zotero
|
||||||
|
brandShortName=Zotero
|
||||||
|
brandFullName=Zotero
|
||||||
3
app/assets/chrome.manifest
Normal file
3
app/assets/chrome.manifest
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
locale branding en-US chrome/en-US/locale/branding/
|
||||||
|
content branding chrome/branding/content/
|
||||||
|
skin browser preferences chrome/skin/
|
||||||
104
app/assets/commandLineHandler.js
Normal file
104
app/assets/commandLineHandler.js
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
let { CommandLineOptions, TestOptions } = ChromeUtils.importESModule("chrome://zotero/content/modules/commandLineOptions.mjs");
|
||||||
|
|
||||||
|
// Only allow BrowserContentHandler to open a new window if this is the initial launch,
|
||||||
|
// meaning our CLH isn't registered yet.
|
||||||
|
if (cmdLine.state != Ci.nsICommandLine.STATE_INITIAL_LAUNCH) {
|
||||||
|
cmdLine.preventDefault = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force debug output to window
|
||||||
|
if (cmdLine.handleFlag("ZoteroDebug", false)) {
|
||||||
|
CommandLineOptions.forceDebugLog = 2;
|
||||||
|
}
|
||||||
|
// Force debug output to text console
|
||||||
|
else if (cmdLine.handleFlag("ZoteroDebugText", false)) {
|
||||||
|
CommandLineOptions.forceDebugLog = 1;
|
||||||
|
}
|
||||||
|
// Pressing Ctrl-C via the terminal is interpreted as a crash, and after three crashes
|
||||||
|
// Firefox starts up in automatic safe mode (troubleshooting mode). To avoid this, we clear the crash
|
||||||
|
// counter when using one of the debug-logging flags, which generally imply terminal usage.
|
||||||
|
if (CommandLineOptions.forceDebugLog) {
|
||||||
|
Services.prefs.getBranch("toolkit.startup.").clearUserPref("recent_crashes");
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandLineOptions.forceDataDir = cmdLine.handleFlagWithParam("datadir", false);
|
||||||
|
// Set here, to be acted upon in xpcom/commandLineHandler.js
|
||||||
|
CommandLineOptions.file = cmdLine.handleFlagWithParam("file", false);
|
||||||
|
CommandLineOptions.url = cmdLine.handleFlagWithParam("url", false);
|
||||||
|
if (CommandLineOptions.url) {
|
||||||
|
CommandLineOptions.url = cmdLine.resolveURI(CommandLineOptions.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
var processTestOptions = false;
|
||||||
|
if (cmdLine.handleFlag("ZoteroTest", false)) {
|
||||||
|
CommandLineOptions.test = true;
|
||||||
|
processTestOptions = true;
|
||||||
|
}
|
||||||
|
if (cmdLine.handleFlag("ZoteroAutomatedTest", false)) {
|
||||||
|
CommandLineOptions.automatedTest = true;
|
||||||
|
}
|
||||||
|
if (cmdLine.handleFlag("ZoteroSkipBundledFiles", false)) {
|
||||||
|
CommandLineOptions.skipBundledFiles = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processTestOptions) {
|
||||||
|
TestOptions.tests = cmdLine.handleFlagWithParam("test", false);
|
||||||
|
TestOptions.noquit = cmdLine.handleFlag("noquit", false);
|
||||||
|
TestOptions.makeTestData = cmdLine.handleFlag("makeTestData", false);
|
||||||
|
TestOptions.noquit = !TestOptions.makeTestData && TestOptions.noquit;
|
||||||
|
TestOptions.runTests = !TestOptions.makeTestData;
|
||||||
|
TestOptions.bail = cmdLine.handleFlag("bail", false);
|
||||||
|
TestOptions.startAt = cmdLine.handleFlagWithParam("startAtTestFile", false);
|
||||||
|
TestOptions.stopAt = cmdLine.handleFlagWithParam("stopAtTestFile", false);
|
||||||
|
TestOptions.shard = cmdLine.handleFlagWithParam("shard", false);
|
||||||
|
TestOptions.grep = cmdLine.handleFlagWithParam("grep", false);
|
||||||
|
TestOptions.timeout = cmdLine.handleFlagWithParam("ZoteroTestTimeout", false);
|
||||||
|
TestOptions.retries = cmdLine.handleFlagWithParam("retries", false) || 0;
|
||||||
|
|
||||||
|
Services.ww.openWindow(
|
||||||
|
null,
|
||||||
|
"chrome://zotero-unit/content/runtests.html",
|
||||||
|
"_blank",
|
||||||
|
"chrome,dialog=no,all",
|
||||||
|
Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray)
|
||||||
|
);
|
||||||
|
cmdLine.preventDefault = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdLine.handleFlag("debugger", false)) {
|
||||||
|
(async function () {
|
||||||
|
try {
|
||||||
|
let portOrPath = Services.prefs.getBranch('').getIntPref('devtools.debugger.remote-port');
|
||||||
|
|
||||||
|
const { DevToolsLoader } = ChromeUtils.importESModule(
|
||||||
|
"resource://devtools/shared/loader/Loader.sys.mjs"
|
||||||
|
);
|
||||||
|
const loader = new DevToolsLoader({
|
||||||
|
freshCompartment: true,
|
||||||
|
});
|
||||||
|
const { DevToolsServer } = loader.require("devtools/server/devtools-server");
|
||||||
|
const { SocketListener } = loader.require("devtools/shared/security/socket");
|
||||||
|
|
||||||
|
if (DevToolsServer.initialized) {
|
||||||
|
dump("Debugger server already initialized\n\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevToolsServer.init();
|
||||||
|
DevToolsServer.registerAllActors();
|
||||||
|
DevToolsServer.allowChromeProcess = true;
|
||||||
|
const socketOptions = { portOrPath };
|
||||||
|
const listener = new SocketListener(DevToolsServer, socketOptions);
|
||||||
|
await listener.open();
|
||||||
|
if (!DevToolsServer.listeningSockets) {
|
||||||
|
throw new Error("No listening sockets");
|
||||||
|
}
|
||||||
|
|
||||||
|
dump(`Debugger server started on ${portOrPath}\n\n`);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
dump(e + "\n\n");
|
||||||
|
Components.utils.reportError(e);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
242
app/assets/mac/chrome/skin/preferences/preferences.css
Normal file
242
app/assets/mac/chrome/skin/preferences/preferences.css
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
# http://www.mozilla.org/MPL/
|
||||||
|
#
|
||||||
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
# for the specific language governing rights and limitations under the
|
||||||
|
# License.
|
||||||
|
#
|
||||||
|
# The Original Code is the Firefox Preferences System.
|
||||||
|
#
|
||||||
|
# The Initial Developer of the Original Code is
|
||||||
|
# Ben Goodger.
|
||||||
|
# Portions created by the Initial Developer are Copyright (C) 2005
|
||||||
|
# the Initial Developer. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Contributor(s):
|
||||||
|
# Ben Goodger <ben@mozilla.org>
|
||||||
|
# Kevin Gerich <webmail@kmgerich.com>
|
||||||
|
#
|
||||||
|
# Alternatively, the contents of this file may be used under the terms of
|
||||||
|
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
# of those above. If you wish to allow use of your version of this file only
|
||||||
|
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
# use your version of this file under the terms of the MPL, indicate your
|
||||||
|
# decision by deleting the provisions above and replace them with the notice
|
||||||
|
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
# the provisions above, a recipient may use your version of this file under
|
||||||
|
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
#
|
||||||
|
# ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
.windowDialog {
|
||||||
|
padding: 12px;
|
||||||
|
font: -moz-dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paneSelector {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- GENERAL BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneGeneral],
|
||||||
|
radio[pane=paneMain] {
|
||||||
|
-moz-image-region: rect(0px, 32px, 32px, 0px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- TABS BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneTabs] {
|
||||||
|
-moz-image-region: rect(0px, 64px, 32px, 32px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- CONTENT BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneContent] {
|
||||||
|
-moz-image-region: rect(0px, 96px, 32px, 64px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- APPLICATIONS BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneApplications] {
|
||||||
|
-moz-image-region: rect(0px, 128px, 32px, 96px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- PRIVACY BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=panePrivacy] {
|
||||||
|
-moz-image-region: rect(0px, 160px, 32px, 128px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- SECURITY BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneSecurity] {
|
||||||
|
-moz-image-region: rect(0px, 192px, 32px, 160px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- ADVANCED BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneAdvanced] {
|
||||||
|
-moz-image-region: rect(0px, 224px, 32px, 192px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----- SYNC BUTTON ----- */
|
||||||
|
|
||||||
|
radio[pane=paneSync] {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- APPLICATIONS PREFPANE ----- */
|
||||||
|
#BrowserPreferences[animated="true"] #handlersView {
|
||||||
|
height: 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#BrowserPreferences[animated="false"] #handlersView {
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
description {
|
||||||
|
font: small-caption;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 1.3em;
|
||||||
|
margin-bottom: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefpane .groupbox-body {
|
||||||
|
-moz-appearance: none;
|
||||||
|
padding: 8px 4px 4px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paneTabs > groupbox {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabPrefsBox {
|
||||||
|
margin: 12px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefpane .groupbox-title {
|
||||||
|
background: url("chrome://global/skin/50pct_transparent_grey.png") repeat-x bottom left;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tabpanels {
|
||||||
|
padding: 20px 7px 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
caption {
|
||||||
|
-moz-padding-start: 5px;
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paneMain description,
|
||||||
|
#paneContent description,
|
||||||
|
#paneAdvanced description,
|
||||||
|
#paneSecurity description {
|
||||||
|
font: -moz-dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paneContent {
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paneContent row {
|
||||||
|
padding: 2px 4px;
|
||||||
|
-moz-box-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popupPolicyRow,
|
||||||
|
#enableSoftwareInstallRow,
|
||||||
|
#enableImagesRow {
|
||||||
|
margin-bottom: 4px !important;
|
||||||
|
padding-bottom: 4px !important;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#browserUseCurrent,
|
||||||
|
#browserUseBookmark,
|
||||||
|
#browserUseBlank {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#advancedPrefs {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#privacyPrefs {
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#privacyPrefs > tabpanels {
|
||||||
|
padding: 18px 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#OCSPDialogPane {
|
||||||
|
font: message-box !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Privacy Pane
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* styles for the link elements copied from .text-link in global.css */
|
||||||
|
.inline-link {
|
||||||
|
color: LinkText;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-link:not(:focus) {
|
||||||
|
outline: 1px dotted transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update Preferences
|
||||||
|
*/
|
||||||
|
#autoInstallOptions {
|
||||||
|
-moz-margin-start: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.updateControls {
|
||||||
|
-moz-margin-start: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear Private Data
|
||||||
|
*/
|
||||||
|
#SanitizeDialogPane > groupbox {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----- SYNC PANE ----- */
|
||||||
|
|
||||||
|
#syncDesc {
|
||||||
|
padding: 0 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#accountCaptionImage {
|
||||||
|
list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#syncAddDeviceLabel {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#syncEnginesList {
|
||||||
|
height: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
1
app/assets/multilocale.txt
Normal file
1
app/assets/multilocale.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
en-US,ar,bg-BG,br,ca-AD,cs-CZ,da-DK,de,el-GR,en-AU,en-CA,en-GB,en-NZ,es-ES,et-EE,eu-ES,fa,fi-FI,fr-FR,gl-ES,hu-HU,id-ID,is-IS,it-IT,ja-JP,km,ko-KR,lt-LT,nb-NO,nl-NL,pl-PL,pt-BR,pt-PT,ro-RO,ru-RU,sk-SK,sl-SI,sr-RS,sv-SE,ta,th-TH,tr-TR,uk-UA,vi-VN,zh-CN,zh-TW
|
||||||
172
app/assets/prefs.js
Normal file
172
app/assets/prefs.js
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
// We only want a single window, I think
|
||||||
|
pref("toolkit.singletonWindowType", "navigator:browser");
|
||||||
|
|
||||||
|
// For debugging purposes, show errors in console by default
|
||||||
|
pref("javascript.options.showInConsole", true);
|
||||||
|
|
||||||
|
// Don't retrieve unrequested links when performing standalone translation
|
||||||
|
pref("network.prefetch-next", false);
|
||||||
|
// Don't make DNS requests for links in snapshots
|
||||||
|
pref("network.dns.disablePrefetch", true);
|
||||||
|
// Don't open TCP connection when clicking on a link in a snapshot
|
||||||
|
pref("network.http.speculative-parallel-limit", 0);
|
||||||
|
|
||||||
|
// Let operations run as long as necessary
|
||||||
|
pref("dom.max_chrome_script_run_time", 0);
|
||||||
|
|
||||||
|
pref("intl.locale.requested", '');
|
||||||
|
pref("intl.regional_prefs.use_os_locales", false);
|
||||||
|
|
||||||
|
// Fix error initializing login manager after this was changed in Firefox 57
|
||||||
|
// Could also disable this with MOZ_LOADER_SHARE_GLOBAL, supposedly
|
||||||
|
pref("jsloader.shareGlobal", false);
|
||||||
|
|
||||||
|
// Needed due to https://bugzilla.mozilla.org/show_bug.cgi?id=1181977
|
||||||
|
pref("browser.hiddenWindowChromeURL", "chrome://zotero/content/standalone/hiddenWindow.xhtml");
|
||||||
|
// Use basicViewer for opening new DOM windows from content (for TinyMCE)
|
||||||
|
pref("browser.chromeURL", "chrome://zotero/content/standalone/basicViewer.xhtml");
|
||||||
|
// We need these to get the save dialog working with contentAreaUtils.js
|
||||||
|
pref("browser.download.useDownloadDir", false);
|
||||||
|
pref("browser.download.manager.showWhenStarting", false);
|
||||||
|
pref("browser.download.folderList", 1);
|
||||||
|
|
||||||
|
// Don't show add-on selection dialog
|
||||||
|
pref("extensions.shownSelectionUI", true);
|
||||||
|
pref("extensions.autoDisableScope", 11);
|
||||||
|
|
||||||
|
pref("network.protocol-handler.expose-all", false);
|
||||||
|
pref("network.protocol-handler.expose.zotero", true);
|
||||||
|
pref("network.protocol-handler.expose.http", true);
|
||||||
|
pref("network.protocol-handler.expose.https", true);
|
||||||
|
|
||||||
|
// Never go offline
|
||||||
|
pref("offline.autoDetect", false);
|
||||||
|
pref("network.manage-offline-status", false);
|
||||||
|
|
||||||
|
// Without this, we will throw up dialogs if asked to translate strange pages
|
||||||
|
pref("browser.xul.error_pages.enabled", true);
|
||||||
|
|
||||||
|
// Without this, scripts may decide to open popups
|
||||||
|
pref("dom.disable_open_during_load", true);
|
||||||
|
|
||||||
|
// Don't show security warning. The "warn_viewing_mixed" warning just lets the user know that some
|
||||||
|
// page elements were loaded over an insecure connection. This doesn't matter if all we're doing is
|
||||||
|
// scraping the page, since we don't provide any information to the site.
|
||||||
|
pref("security.warn_viewing_mixed", false);
|
||||||
|
|
||||||
|
// Temporarily allow plugins to load their own scripts from jar:file: URIs with loadSubScript()
|
||||||
|
// without passing allowUnsafeURL (Mozilla bug 1974213). This will be disabled once plugins have
|
||||||
|
// had time to update.
|
||||||
|
pref("security.allow_unsafe_subscript_loads", true);
|
||||||
|
|
||||||
|
// We do need synchronous XHR
|
||||||
|
pref("network.xhr.block_sync_system_requests", false);
|
||||||
|
|
||||||
|
// Preferences for add-on discovery
|
||||||
|
pref("extensions.getAddons.cache.enabled", false);
|
||||||
|
//pref("extensions.getAddons.maxResults", 15);
|
||||||
|
//pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/guid:%IDS%?src=thunderbird&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
|
||||||
|
//pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/%APP%/search?q=%TERMS%");
|
||||||
|
//pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%?src=thunderbird");
|
||||||
|
//pref("extensions.webservice.discoverURL", "https://www.zotero.org/support/plugins");
|
||||||
|
|
||||||
|
// Check Windows certificate store for custom CAs
|
||||||
|
pref("security.enterprise_roots.enabled", true);
|
||||||
|
|
||||||
|
// Disable add-on signature checking with unbranded Firefox build
|
||||||
|
pref("xpinstall.signatures.required", false);
|
||||||
|
// Allow legacy extensions (though this might not be necessary)
|
||||||
|
pref("extensions.legacy.enabled", true);
|
||||||
|
// Allow installing XPIs from any host
|
||||||
|
pref("xpinstall.whitelist.required", false);
|
||||||
|
// Allow installing XPIs when using a custom CA
|
||||||
|
pref("extensions.install.requireBuiltInCerts", false);
|
||||||
|
pref("extensions.update.requireBuiltInCerts", false);
|
||||||
|
|
||||||
|
// Don't connect to the Mozilla extensions blocklist
|
||||||
|
pref("extensions.blocklist.enabled", false);
|
||||||
|
// Avoid warning in console when opening Tools -> Add-ons
|
||||||
|
pref("extensions.getAddons.link.url", "");
|
||||||
|
|
||||||
|
// Disable places
|
||||||
|
pref("places.history.enabled", false);
|
||||||
|
|
||||||
|
// Probably not used, but prevent an error in the console
|
||||||
|
pref("app.support.baseURL", "https://www.zotero.org/support/");
|
||||||
|
|
||||||
|
// Disable Telemetry, Health Report, error reporting, and remote settings
|
||||||
|
pref("toolkit.telemetry.unified", false);
|
||||||
|
pref("toolkit.telemetry.enabled", false);
|
||||||
|
pref("datareporting.policy.dataSubmissionEnabled", false);
|
||||||
|
pref("toolkit.crashreporter.enabled", false);
|
||||||
|
pref("extensions.remoteSettings.disabled", true);
|
||||||
|
|
||||||
|
pref("extensions.update.url", "");
|
||||||
|
|
||||||
|
// Don't try to load the "Get Add-ons" tab on first load of Add-ons window
|
||||||
|
pref("extensions.ui.lastCategory", "addons://list/extension");
|
||||||
|
|
||||||
|
// Don't show "Using experimental APIs requires a privileged add-on" warning
|
||||||
|
pref("extensions.experiments.enabled", true);
|
||||||
|
|
||||||
|
// Not set on Windows in Firefox anymore since it's a per-installation pref,
|
||||||
|
// but we override that in fetch_xulrunner
|
||||||
|
pref("app.update.auto", true);
|
||||||
|
|
||||||
|
// URL user can browse to manually if for some reason all update installation
|
||||||
|
// attempts fail.
|
||||||
|
pref("app.update.url.manual", "https://www.zotero.org/download");
|
||||||
|
|
||||||
|
// A default value for the "More information about this update" link
|
||||||
|
// supplied in the "An update is available" page of the update wizard.
|
||||||
|
pref("app.update.url.details", "https://www.zotero.org/support/changelog");
|
||||||
|
|
||||||
|
// Interval: Time between checks for a new version (in seconds)
|
||||||
|
// default=1 day
|
||||||
|
pref("app.update.interval", 86400);
|
||||||
|
|
||||||
|
// The minimum delay in seconds for the timer to fire.
|
||||||
|
// default=2 minutes
|
||||||
|
pref("app.update.timerMinimumDelay", 120);
|
||||||
|
|
||||||
|
// Whether or not we show a dialog box informing the user that the update was
|
||||||
|
// successfully applied. This is off in Firefox by default since we show a
|
||||||
|
// upgrade start page instead! Other apps may wish to show this UI, and supply
|
||||||
|
// a whatsNewURL field in their brand.properties that contains a link to a page
|
||||||
|
// which tells users what's new in this new update.
|
||||||
|
|
||||||
|
// update channel for this build
|
||||||
|
pref("app.update.channel", "default");
|
||||||
|
|
||||||
|
// This should probably not be a preference that's used in toolkit....
|
||||||
|
pref("browser.preferences.instantApply", false);
|
||||||
|
|
||||||
|
// Allow elements to be displayed full-screen
|
||||||
|
pref("full-screen-api.enabled", true);
|
||||||
|
|
||||||
|
// Allow chrome access in DevTools
|
||||||
|
// This enables the input field in the Browser Console tool
|
||||||
|
pref("devtools.chrome.enabled", true);
|
||||||
|
|
||||||
|
// Default mousewheel action with Alt/Option is History Back/Forward in Firefox
|
||||||
|
// We don't have History navigation and users want to scroll the tree with Option
|
||||||
|
// key held down
|
||||||
|
pref("mousewheel.with_alt.action", 1);
|
||||||
|
|
||||||
|
// Use the system print dialog instead of the new tab-based print dialog in Firefox
|
||||||
|
pref("print.prefer_system_dialog", true);
|
||||||
|
|
||||||
|
// Disable libvpx decoding/encoding
|
||||||
|
pref("media.webm.enabled", false);
|
||||||
|
pref("media.encoder.webm.enabled", false);
|
||||||
|
pref("media.mediasource.webm.enabled", false);
|
||||||
|
pref("media.mediasource.webm.audio.enabled", false);
|
||||||
|
pref("media.mediasource.vp9.enabled", false);
|
||||||
|
pref("media.ffvpx.enabled", false);
|
||||||
|
pref("media.ffvpx.mp3.enabled", false);
|
||||||
|
pref("media.rdd-vpx.enabled", false);
|
||||||
|
pref("media.rdd-ffvpx.enabled", false);
|
||||||
|
pref("media.utility-ffvpx.enabled", false);
|
||||||
|
|
||||||
|
// Allow collectionTree scrolling when Control is highlighting collections on win
|
||||||
|
pref("mousewheel.with_control.action", 1);
|
||||||
188
app/assets/unix/skin/preferences/preferences.css
Normal file
188
app/assets/unix/skin/preferences/preferences.css
Normal file
|
|
@ -0,0 +1,188 @@
|
||||||
|
%if 0
|
||||||
|
/*
|
||||||
|
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
# http://www.mozilla.org/MPL/
|
||||||
|
#
|
||||||
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
# for the specific language governing rights and limitations under the
|
||||||
|
# License.
|
||||||
|
#
|
||||||
|
# The Original Code is the Firefox Preferences System.
|
||||||
|
#
|
||||||
|
# The Initial Developer of the Original Code is
|
||||||
|
# Ben Goodger.
|
||||||
|
# Portions created by the Initial Developer are Copyright (C) 2005
|
||||||
|
# the Initial Developer. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Contributor(s):
|
||||||
|
# Ben Goodger <ben@mozilla.org>
|
||||||
|
#
|
||||||
|
# Alternatively, the contents of this file may be used under the terms of
|
||||||
|
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
# of those above. If you wish to allow use of your version of this file only
|
||||||
|
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
# use your version of this file under the terms of the MPL, indicate your
|
||||||
|
# decision by deleting the provisions above and replace them with the notice
|
||||||
|
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
# the provisions above, a recipient may use your version of this file under
|
||||||
|
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
#
|
||||||
|
# ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
%endif
|
||||||
|
|
||||||
|
/* Global Styles */
|
||||||
|
#BrowserPreferences radio[pane] {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneMain] {
|
||||||
|
-moz-image-region: rect(0px, 32px, 32px, 0px)
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneTabs] {
|
||||||
|
-moz-image-region: rect(0px, 64px, 32px, 32px)
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneContent] {
|
||||||
|
-moz-image-region: rect(0px, 96px, 32px, 64px)
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneApplications] {
|
||||||
|
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=panePrivacy] {
|
||||||
|
-moz-image-region: rect(0px, 160px, 32px, 128px)
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneSecurity] {
|
||||||
|
-moz-image-region: rect(0px, 192px, 32px, 160px)
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneAdvanced] {
|
||||||
|
-moz-image-region: rect(0px, 224px, 32px, 192px)
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
radio[pane=paneSync] {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png") !important;
|
||||||
|
}
|
||||||
|
%endif
|
||||||
|
|
||||||
|
/* Applications Pane */
|
||||||
|
#BrowserPreferences[animated="true"] #handlersView {
|
||||||
|
height: 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#BrowserPreferences[animated="false"] #handlersView {
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Privacy Pane */
|
||||||
|
|
||||||
|
/* styles for the link elements copied from .text-link in global.css */
|
||||||
|
.inline-link {
|
||||||
|
color: LinkText;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-link:not(:focus) {
|
||||||
|
outline: 1px dotted transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modeless Window Dialogs */
|
||||||
|
.windowDialog,
|
||||||
|
.windowDialog prefpane {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentPane {
|
||||||
|
margin: 9px 8px 5px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
margin: 0px 3px 6px 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookies Manager */
|
||||||
|
#cookiesChildren::-moz-tree-image(domainCol) {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin: 0px 2px;
|
||||||
|
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#paneApplications {
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#linksOpenInBox {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paneAdvanced {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
#advancedPrefs {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cookiesChildren::-moz-tree-image(domainCol, container) {
|
||||||
|
list-style-image: url("moz-icon://stock/gtk-directory?size=menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
#cookieInfoBox {
|
||||||
|
border: 1px solid ThreeDShadow;
|
||||||
|
border-radius: 0px;
|
||||||
|
margin: 4px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bottom-most box containing a groupbox in a prefpane. Prevents the bottom
|
||||||
|
of the groupbox from being cutoff */
|
||||||
|
.bottomBox {
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear Private Data
|
||||||
|
*/
|
||||||
|
#SanitizeDialogPane > groupbox {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
/* Sync Pane */
|
||||||
|
|
||||||
|
#syncDesc {
|
||||||
|
padding: 0 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#accountCaptionImage {
|
||||||
|
list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#syncAddDeviceLabel {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#syncEnginesList {
|
||||||
|
height: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
%endif
|
||||||
4
app/assets/updater.ini
Normal file
4
app/assets/updater.ini
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
; This file is in the UTF-8 encoding
|
||||||
|
[Strings]
|
||||||
|
Title=Zotero Update
|
||||||
|
Info=Zotero is installing your updates and will start in a few moments…
|
||||||
178
app/assets/win/skin/preferences/preferences.css
Normal file
178
app/assets/win/skin/preferences/preferences.css
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
# http://www.mozilla.org/MPL/
|
||||||
|
#
|
||||||
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
# for the specific language governing rights and limitations under the
|
||||||
|
# License.
|
||||||
|
#
|
||||||
|
# The Original Code is the Firefox Preferences System.
|
||||||
|
#
|
||||||
|
# The Initial Developer of the Original Code is
|
||||||
|
# Ben Goodger.
|
||||||
|
# Portions created by the Initial Developer are Copyright (C) 2005
|
||||||
|
# the Initial Developer. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Contributor(s):
|
||||||
|
# Ben Goodger <ben@mozilla.org>
|
||||||
|
#
|
||||||
|
# Alternatively, the contents of this file may be used under the terms of
|
||||||
|
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
# of those above. If you wish to allow use of your version of this file only
|
||||||
|
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
# use your version of this file under the terms of the MPL, indicate your
|
||||||
|
# decision by deleting the provisions above and replace them with the notice
|
||||||
|
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
# the provisions above, a recipient may use your version of this file under
|
||||||
|
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
#
|
||||||
|
# ***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Global Styles */
|
||||||
|
#BrowserPreferences radio[pane] {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options.png");
|
||||||
|
padding: 5px 3px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneMain] {
|
||||||
|
-moz-image-region: rect(0, 32px, 32px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneTabs] {
|
||||||
|
-moz-image-region: rect(0, 64px, 32px, 32px);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneContent] {
|
||||||
|
-moz-image-region: rect(0, 96px, 32px, 64px);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneApplications] {
|
||||||
|
-moz-image-region: rect(0, 128px, 32px, 96px);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=panePrivacy] {
|
||||||
|
-moz-image-region: rect(0, 160px, 32px, 128px);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneSecurity] {
|
||||||
|
-moz-image-region: rect(0, 192px, 32px, 160px);
|
||||||
|
}
|
||||||
|
|
||||||
|
radio[pane=paneAdvanced] {
|
||||||
|
-moz-image-region: rect(0, 224px, 32px, 192px);
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
radio[pane=paneSync] {
|
||||||
|
list-style-image: url("chrome://browser/skin/preferences/Options-sync.png") !important;
|
||||||
|
}
|
||||||
|
%endif
|
||||||
|
|
||||||
|
/* Applications Pane */
|
||||||
|
#BrowserPreferences[animated="true"] #handlersView {
|
||||||
|
height: 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#BrowserPreferences[animated="false"] #handlersView {
|
||||||
|
-moz-box-flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Privacy Pane */
|
||||||
|
|
||||||
|
/* styles for the link elements copied from .text-link in global.css */
|
||||||
|
.inline-link {
|
||||||
|
color: LinkText;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-link:not(:focus) {
|
||||||
|
outline: 1px dotted transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modeless Window Dialogs */
|
||||||
|
.windowDialog,
|
||||||
|
.windowDialog prefpane {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentPane {
|
||||||
|
margin: 9px 8px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionButtons {
|
||||||
|
margin: 0 3px 6px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookies Manager */
|
||||||
|
#cookiesChildren::-moz-tree-image(domainCol) {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin: 0 2px;
|
||||||
|
list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png") !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cookiesChildren::-moz-tree-image(domainCol, container) {
|
||||||
|
list-style-image: url("chrome://global/skin/icons/folder-item.png") !important;
|
||||||
|
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cookiesChildren::-moz-tree-image(domainCol, container, open) {
|
||||||
|
-moz-image-region: rect(16px, 32px, 32px, 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#cookieInfoBox {
|
||||||
|
border: 1px solid ThreeDShadow;
|
||||||
|
border-radius: 0;
|
||||||
|
margin: 4px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advanced Pane */
|
||||||
|
|
||||||
|
/* Adding padding-bottom prevents the bottom of the tabpanel from being cutoff
|
||||||
|
when browser.preferences.animateFadeIn = true */
|
||||||
|
#advancedPrefs {
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bottom-most box containing a groupbox in a prefpane. Prevents the bottom
|
||||||
|
of the groupbox from being cutoff */
|
||||||
|
.bottomBox {
|
||||||
|
padding-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
%ifdef MOZ_SERVICES_SYNC
|
||||||
|
/* Sync Pane */
|
||||||
|
|
||||||
|
#syncDesc {
|
||||||
|
padding: 0 8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.syncGroupBox {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#accountCaptionImage {
|
||||||
|
list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
#syncAddDeviceLabel {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#syncEnginesList {
|
||||||
|
height: 11em;
|
||||||
|
}
|
||||||
|
|
||||||
|
%endif
|
||||||
1210
app/build.sh
Executable file
1210
app/build.sh
Executable file
File diff suppressed because it is too large
Load diff
73
app/config.sh
Normal file
73
app/config.sh
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
# Version of Gecko to build with
|
||||||
|
GECKO_VERSION_MAC="153.3.0esr"
|
||||||
|
GECKO_VERSION_LINUX="153.3.0esr"
|
||||||
|
GECKO_VERSION_WIN="153.3.0esr"
|
||||||
|
RUST_VERSION=1.94.0
|
||||||
|
|
||||||
|
# URL prefix for custom builds of Firefox components
|
||||||
|
custom_components_url="https://download.zotero.org/dev/firefox-components/"
|
||||||
|
custom_components_hash_mac="6b586ed383a480fed9d9786ad18a6e6d90b140739e5e4491096df291ec887571"
|
||||||
|
custom_components_hash_win_x64="db7c9556bd0f9e36120069391ce66cc199ed1ec4e2fdd3b931f71e35b4586d2b"
|
||||||
|
custom_components_hash_win_arm64="fd0f44b38a471009ce1cdd926f7f48be43ed773dad350c62383b8a7235da8711"
|
||||||
|
custom_components_hash_win32="694944349fdfd91296f272a68ac5d03183f02d47fdaa7ba9f2b1c74747652aa2"
|
||||||
|
|
||||||
|
APP_NAME="Zotero"
|
||||||
|
APP_ID="zotero\@zotero.org"
|
||||||
|
|
||||||
|
# Whether to sign builds
|
||||||
|
SIGN=0
|
||||||
|
|
||||||
|
# OS X Developer ID certificate information
|
||||||
|
DEVELOPER_ID=F0F1FE48DB909B263AC51C8215374D87FDC12121
|
||||||
|
# Keychain and keychain password, if not building via the GUI
|
||||||
|
KEYCHAIN=""
|
||||||
|
KEYCHAIN_PASSWORD=""
|
||||||
|
NOTARIZATION_BUNDLE_ID=""
|
||||||
|
NOTARIZATION_USER=""
|
||||||
|
NOTARIZATION_TEAM_ID=""
|
||||||
|
NOTARIZATION_PASSWORD=""
|
||||||
|
# Name of a notarytool keychain profile (see `xcrun notarytool store-credentials`), e.g., for an
|
||||||
|
# App Store Connect API key -- used instead of the Apple ID settings above if set
|
||||||
|
NOTARIZATION_PROFILE=""
|
||||||
|
|
||||||
|
# Paths for Windows installer build
|
||||||
|
NSIS_DIR='C:\Program Files (x86)\NSIS\'
|
||||||
|
|
||||||
|
SIGNTOOL_DELAY=5
|
||||||
|
|
||||||
|
# Directory for unpacked binaries
|
||||||
|
STAGE_DIR="$DIR/staging"
|
||||||
|
# Directory for packed binaries
|
||||||
|
DIST_DIR="$DIR/dist"
|
||||||
|
|
||||||
|
SOURCE_REPO_URL="https://github.com/zotero/zotero"
|
||||||
|
S3_BUCKET="zotero-download"
|
||||||
|
S3_CI_ZIP_PATH="ci/client"
|
||||||
|
S3_DIST_PATH="client"
|
||||||
|
|
||||||
|
DEPLOY_HOST="deploy.zotero"
|
||||||
|
DEPLOY_PATH="www/www-production/public/download/client"
|
||||||
|
|
||||||
|
BUILD_PLATFORMS=""
|
||||||
|
NUM_INCREMENTALS=6
|
||||||
|
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
shopt -s expand_aliases
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "`uname -o 2> /dev/null`" = "Cygwin" ]; then
|
||||||
|
export WIN_NATIVE=1
|
||||||
|
else
|
||||||
|
export WIN_NATIVE=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make utilities (mar/mbsdiff) available in the path
|
||||||
|
PATH="$DIR/xulrunner/bin:$PATH"
|
||||||
|
|
||||||
|
if [ -f "$DIR/config-custom.sh" ]; then
|
||||||
|
. "$DIR/config-custom.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset DIR
|
||||||
44
app/linux/build
Executable file
44
app/linux/build
Executable file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
echo "Usage: $0 x64|arm64" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
gecko_path=~/src/firefox
|
||||||
|
arch=$1
|
||||||
|
|
||||||
|
if [ ! -d "$gecko_path" ]; then
|
||||||
|
echo "$gecko_path is not a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install required Rust version
|
||||||
|
rustup toolchain install $RUST_VERSION
|
||||||
|
if [ $arch = "x64" ]; then
|
||||||
|
rust_target=x86_64
|
||||||
|
elif [ $arch = "arm64" ]; then
|
||||||
|
rust_target=aarch64
|
||||||
|
else
|
||||||
|
echo "Unknown architecture $arch" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rustup target add $rust_target-unknown-linux-gnu
|
||||||
|
|
||||||
|
rm "$gecko_path/mozconfig"
|
||||||
|
touch "$gecko_path/mozconfig"
|
||||||
|
|
||||||
|
if [ $arch == "arm64" ]; then
|
||||||
|
echo "ac_add_options --target=aarch64-linux-gnu" >> "$gecko_path/mozconfig"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat "$SCRIPT_DIR/mozconfig" >> "$gecko_path/mozconfig"
|
||||||
|
|
||||||
|
cd "$gecko_path"
|
||||||
|
./mach build
|
||||||
|
./mach package
|
||||||
BIN
app/linux/icons/icon128.png
Normal file
BIN
app/linux/icons/icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8 KiB |
BIN
app/linux/icons/icon32.png
Normal file
BIN
app/linux/icons/icon32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
BIN
app/linux/icons/icon64.png
Normal file
BIN
app/linux/icons/icon64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
3
app/linux/icons/symbolic.svg
Normal file
3
app/linux/icons/symbolic.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
|
<polygon style="fill: #000000" points="13.863 2.73 13.027 1 2.137 1 2.137 3.8 2.137 3.921 8.822 3.921 1.289 13.233 2.137 15 13.863 15 13.863 12.142 13.863 12.021 6.448 12.021 13.863 2.73"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 283 B |
25
app/linux/mozconfig
Normal file
25
app/linux/mozconfig
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
ac_add_options --enable-bootstrap
|
||||||
|
|
||||||
|
mk_add_options AUTOCLOBBER=1
|
||||||
|
|
||||||
|
# These don't all affect the stub, but they can't hurt, and we'll want them if
|
||||||
|
# we switch to custom XUL builds
|
||||||
|
ac_add_options MOZ_ENABLE_JS_DUMP=1
|
||||||
|
ac_add_options MOZ_ENABLE_FORKSERVER=
|
||||||
|
ac_add_options MOZ_TELEMETRY_REPORTING=
|
||||||
|
ac_add_options MOZ_DATA_REPORTING=
|
||||||
|
ac_add_options --disable-tests
|
||||||
|
ac_add_options --disable-debug
|
||||||
|
ac_add_options --disable-debug-symbols
|
||||||
|
ac_add_options --disable-webrtc
|
||||||
|
# This causes aarch64 build of 140.0esr to fail
|
||||||
|
#ac_add_options --disable-eme
|
||||||
|
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
export RELEASE_OR_BETA=1
|
||||||
|
MOZ_REQUIRE_SIGNING=
|
||||||
|
|
||||||
|
ac_add_options --enable-official-branding
|
||||||
|
|
||||||
|
# Build updater without MAR signature verification
|
||||||
|
ac_add_options --enable-unverified-updates
|
||||||
13
app/linux/set_launcher_icon
Executable file
13
app/linux/set_launcher_icon
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run this to update the launcher file with the current path to the application icon
|
||||||
|
#
|
||||||
|
|
||||||
|
APPDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if [ -w "$APPDIR"/zotero.desktop ]; then
|
||||||
|
sed -i -e "s@^Icon=.*@Icon=$APPDIR/icons/icon128.png@" "$APPDIR"/zotero.desktop
|
||||||
|
else
|
||||||
|
echo "$APPDIR"/zotero.desktop is not writable
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
43
app/linux/update_updater
Executable file
43
app/linux/update_updater
Executable file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <firefox-version>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version="$1"
|
||||||
|
|
||||||
|
for arch in x86_64 aarch64; do
|
||||||
|
package="firefox-${version}.en-US.linux-${arch}.tar.xz"
|
||||||
|
if [ $arch = 'aarch64' ]; then
|
||||||
|
arch="arm64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$package" ]; then
|
||||||
|
echo "Error: Package not found: $package"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Extracting updater from $package..."
|
||||||
|
tar --extract --xz --file="$package" --to-stdout "firefox/updater" > "updater-$arch"
|
||||||
|
|
||||||
|
# Add missing RUNPATH to custom fx140 builds, which is missing for unclear reasons.
|
||||||
|
# Without this, the updater fails looking for libmozsqlite3.so.
|
||||||
|
patchelf --set-rpath '$ORIGIN' "updater-$arch"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Creating updater.tar.xz..."
|
||||||
|
if [ `uname` = "Darwin" ]; then
|
||||||
|
tar=gtar
|
||||||
|
else
|
||||||
|
tar=tar
|
||||||
|
fi
|
||||||
|
$tar --owner=0 --group=0 --numeric-owner --no-xattrs --mode=0755 -cJvf updater.tar.xz updater-x86_64 updater-arm64
|
||||||
|
|
||||||
|
rm updater-x86_64 updater-arm64
|
||||||
|
|
||||||
|
echo "Done: updater.tar.xz created"
|
||||||
3
app/linux/updater.tar.xz
Normal file
3
app/linux/updater.tar.xz
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a1f368bb36408d61d4b8f9dda561738686e626513346e138d55a0ef58055a6fc
|
||||||
|
size 123776
|
||||||
20
app/linux/zotero
Executable file
20
app/linux/zotero
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Increase open files limit
|
||||||
|
#
|
||||||
|
# Mozilla file functions (OS.File.move()/copy(), NetUtil.asyncFetch/asyncCopy()) can leave file
|
||||||
|
# descriptors open for a few seconds (even with an explicit inputStream.close() in the case of
|
||||||
|
# the latter), so a source installation that copies ~500 translators and styles (with fds for
|
||||||
|
# source and target) can exceed the default 1024 limit.
|
||||||
|
# Current hard-limit on Ubuntu 16.10 is 4096
|
||||||
|
ulimit -n 4096
|
||||||
|
|
||||||
|
# Allow profile downgrade for Zotero
|
||||||
|
export MOZ_ALLOW_DOWNGRADE=1
|
||||||
|
# Don't create dedicated profile (default-esr)
|
||||||
|
export MOZ_LEGACY_PROFILES=1
|
||||||
|
# Use wayland backend when available
|
||||||
|
export MOZ_ENABLE_WAYLAND=1
|
||||||
|
|
||||||
|
CALLDIR="$(dirname "$(readlink -f "$0")")"
|
||||||
|
"$CALLDIR/zotero-bin" -app "$CALLDIR/app/application.ini" "$@"
|
||||||
9
app/linux/zotero.desktop
Executable file
9
app/linux/zotero.desktop
Executable file
|
|
@ -0,0 +1,9 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Zotero
|
||||||
|
Exec=bash -c "$(dirname $(realpath $(echo %k | sed -e 's/^file:\\/\\///')))/zotero -url %U"
|
||||||
|
Icon=zotero.ico
|
||||||
|
Type=Application
|
||||||
|
Terminal=false
|
||||||
|
Categories=Office;
|
||||||
|
MimeType=text/plain;x-scheme-handler/zotero;application/x-research-info-systems;text/x-research-info-systems;text/ris;application/x-endnote-refer;application/x-inst-for-Scientific-info;application/mods+xml;application/rdf+xml;application/x-bibtex;text/x-bibtex;application/marc;application/vnd.citationstyles.style+xml
|
||||||
|
X-GNOME-SingleWindow=true
|
||||||
BIN
app/mac/ChannelPrefs.framework.tar.xz
Normal file
BIN
app/mac/ChannelPrefs.framework.tar.xz
Normal file
Binary file not shown.
204
app/mac/Contents/Info.plist
Normal file
204
app/mac/Contents/Info.plist
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<!-- Import formats -->
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>ris</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/x-research-info-systems</string>
|
||||||
|
<string>text/x-research-info-systems</string>
|
||||||
|
<string>text/ris</string>
|
||||||
|
<string>ris</string>
|
||||||
|
<string>application/x-endnote-refer</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Research Information Systems Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>ciw</string>
|
||||||
|
<string>isi</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/x-inst-for-Scientific-info</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>ISI Common Export Format Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>mods</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/mods+xml</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Metadata Object Description Schema Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>rdf</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/rdf+xml</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Resource Description Framework Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>bib</string>
|
||||||
|
<string>bibtex</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/x-bibtex</string>
|
||||||
|
<string>text/x-bibtex</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>BibTeX Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>mrc</string>
|
||||||
|
<string>marc</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/marc</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>MARC Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
|
||||||
|
<!-- Citation styles -->
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>csl</string>
|
||||||
|
<string>csl.txt</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
|
<array>
|
||||||
|
<string>application/vnd.citationstyles.style+xml</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>CSL Citation Style</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
|
||||||
|
<!-- Hopefully, we don't become the default app for these -->
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>xml</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>XML Document</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeExtensions</key>
|
||||||
|
<array>
|
||||||
|
<string>txt</string>
|
||||||
|
</array>
|
||||||
|
<!--<key>CFBundleTypeIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Text File</string>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>zotero</string>
|
||||||
|
<key>CFBundleGetInfoString</key>
|
||||||
|
<string>Zotero {{VERSION}}, © 2006-2018 Contributors</string>
|
||||||
|
<key>CFBundleIconName</key>
|
||||||
|
<string>AppIcon</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>org.zotero.zotero</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Zotero</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{{VERSION_NUMERIC}}</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>ZOTR</string>
|
||||||
|
<key>CFBundleURLTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<!--<key>CFBundleURLIconFile</key>
|
||||||
|
<string>document.icns</string>-->
|
||||||
|
<key>CFBundleURLName</key>
|
||||||
|
<string>zotero URL</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>zotero</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{{VERSION_NUMERIC}}</string>
|
||||||
|
<key>NSAppleScriptEnabled</key>
|
||||||
|
<true/>
|
||||||
|
<key>CGDisableCoalescedUpdates</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
|
<true/>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.9.0</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
1
app/mac/Contents/PkgInfo
Normal file
1
app/mac/Contents/PkgInfo
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
APPLZOTR
|
||||||
BIN
app/mac/Contents/Resources/Assets.car
Normal file
BIN
app/mac/Contents/Resources/Assets.car
Normal file
Binary file not shown.
BIN
app/mac/DSStore
Normal file
BIN
app/mac/DSStore
Normal file
Binary file not shown.
93
app/mac/build-and-unify
Executable file
93
app/mac/build-and-unify
Executable file
|
|
@ -0,0 +1,93 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
fx_app_name=Firefox.app
|
||||||
|
|
||||||
|
# Get Mozilla source directory from command line
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
echo "Usage: $0 /path/to/firefox" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
GECKO_PATH="$(cd "$1" && pwd)"
|
||||||
|
mach=$GECKO_PATH/mach
|
||||||
|
|
||||||
|
BUILD_DIR=`mktemp -d`
|
||||||
|
function cleanup {
|
||||||
|
rm -rf $BUILD_DIR
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
export MOZ_BUILD_DATE=`date "+%Y%m%d%H%M%S"`
|
||||||
|
|
||||||
|
# Install required Rust version
|
||||||
|
rustup toolchain install $RUST_VERSION
|
||||||
|
rustup target add --toolchain $RUST_VERSION aarch64-apple-darwin x86_64-apple-darwin
|
||||||
|
rustup default $RUST_VERSION
|
||||||
|
|
||||||
|
cp "$SCRIPT_DIR/mozconfig" "$GECKO_PATH"
|
||||||
|
|
||||||
|
# Build Firefox for Intel and Apple Silicon
|
||||||
|
export Z_ARCH=x64
|
||||||
|
$mach build
|
||||||
|
$mach package
|
||||||
|
export Z_ARCH=aarch64
|
||||||
|
$mach build
|
||||||
|
$mach package
|
||||||
|
|
||||||
|
cd $BUILD_DIR
|
||||||
|
|
||||||
|
# Unify into Universal build
|
||||||
|
# From https://searchfox.org/mozilla-central/rev/97c902e8f92b15dc63eb584bfc594ecb041242a4/taskcluster/scripts/misc/unify.sh
|
||||||
|
for i in x86_64 aarch64; do
|
||||||
|
$mach python -m mozbuild.action.unpack_dmg "$GECKO_PATH"/obj-$i-apple-darwin/dist/*.dmg $i
|
||||||
|
done
|
||||||
|
mv x86_64 x64
|
||||||
|
|
||||||
|
$mach python "$GECKO_PATH/toolkit/mozapps/installer/unify.py" x64/*.app aarch64/*.app
|
||||||
|
|
||||||
|
cp x64/$fx_app_name/Contents/MacOS/firefox zotero
|
||||||
|
xz zotero
|
||||||
|
mv zotero.xz "$APP_ROOT_DIR/mac/zotero.xz"
|
||||||
|
|
||||||
|
# Package custom Firefox components for fetch_xulrunner. Add XUL to this list if needed.
|
||||||
|
# Upload the archive to ${custom_components_url}mac/ and set custom_components_hash_mac
|
||||||
|
# in config.sh to the hash printed below.
|
||||||
|
custom_components=(libmozglue.dylib)
|
||||||
|
mkdir MacOS
|
||||||
|
for component in "${custom_components[@]}"; do
|
||||||
|
cp "x64/$fx_app_name/Contents/MacOS/$component" MacOS/
|
||||||
|
done
|
||||||
|
tar cfJ MacOS.tar.xz MacOS
|
||||||
|
components_hash=$(shasum -a 256 MacOS.tar.xz | cut -d ' ' -f 1)
|
||||||
|
components_file="$APP_ROOT_DIR/mac/$components_hash.tar.xz"
|
||||||
|
mv MacOS.tar.xz "$components_file"
|
||||||
|
echo "Custom Firefox components: $components_file"
|
||||||
|
echo "custom_components_hash_mac=\"$components_hash\""
|
||||||
|
|
||||||
|
# Save a copy of ChannelPrefs.framework
|
||||||
|
#
|
||||||
|
# Frameworks need to be signed, and we can't sign source builds, so store a signed copy with
|
||||||
|
# 'default' replaced with 'source'. Deployed builds will then replace 'source' with
|
||||||
|
# 'release'/'beta'/'dev'.
|
||||||
|
rm -rf "$APP_ROOT_DIR/mac/ChannelPrefs.framework"
|
||||||
|
cp -R x64/$fx_app_name/Contents/Frameworks/ChannelPrefs.framework "$APP_ROOT_DIR/mac/ChannelPrefs.framework"
|
||||||
|
pushd "$APP_ROOT_DIR/mac"
|
||||||
|
./set-channel-prefs-channel ChannelPrefs.framework/ChannelPrefs default source
|
||||||
|
security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" ~/Library/Keychains/$KEYCHAIN.keychain-db
|
||||||
|
/usr/bin/codesign --force --options runtime --sign "$DEVELOPER_ID" ChannelPrefs.framework
|
||||||
|
/usr/bin/codesign -vvvv ChannelPrefs.framework
|
||||||
|
tar cfvJ ChannelPrefs.framework.tar.xz ChannelPrefs.framework
|
||||||
|
rm -rf ChannelPrefs.framework
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Uncomment to build updater
|
||||||
|
#cd x64/$fx_app_name/Contents/MacOS/
|
||||||
|
#"$APP_ROOT_DIR/mac/updater_renamer"
|
||||||
|
#cat updater.app/Contents/Resources/English.lproj/InfoPlist.strings
|
||||||
|
#tar cfvJ "$APP_ROOT_DIR/mac/updater.tar.xz" updater.app/
|
||||||
34
app/mac/entitlements.xml
Normal file
34
app/mac/entitlements.xml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<!--
|
||||||
|
Entitlements to apply during codesigning of production builds.
|
||||||
|
-->
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<!-- Firefox needs to create executable pages (without MAP_JIT) -->
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key><true/>
|
||||||
|
|
||||||
|
<!-- Allow loading third party libraries. Needed for Flash and CDMs -->
|
||||||
|
<!-- Disabled for Zotero -->
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key><false/>
|
||||||
|
|
||||||
|
<!-- Firefox needs to access the microphone on sites the user allows -->
|
||||||
|
<!-- Disabled for Zotero -->
|
||||||
|
<key>com.apple.security.device.audio-input</key><false/>
|
||||||
|
|
||||||
|
<!-- Firefox needs to access the camera on sites the user allows -->
|
||||||
|
<!-- Disabled for Zotero -->
|
||||||
|
<key>com.apple.security.device.camera</key><false/>
|
||||||
|
|
||||||
|
<!-- Firefox needs to access the location on sites the user allows -->
|
||||||
|
<!-- Disabled for Zotero -->
|
||||||
|
<key>com.apple.security.personal-information.location</key><false/>
|
||||||
|
|
||||||
|
<!-- For SmartCardServices(7) -->
|
||||||
|
<!-- Disabled for Zotero -->
|
||||||
|
<key>com.apple.security.smartcard</key><false/>
|
||||||
|
|
||||||
|
<!-- Added for Zotero to control Word and bring windows to the front -->
|
||||||
|
<key>com.apple.security.automation.apple-events</key><true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
35
app/mac/mozconfig
Normal file
35
app/mac/mozconfig
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
if [ "$Z_ARCH" == "x64" ]; then
|
||||||
|
ac_add_options --target=x86_64-apple-darwin
|
||||||
|
elif [ "$Z_ARCH" == "aarch64" ]; then
|
||||||
|
ac_add_options --target=aarch64-apple-darwin
|
||||||
|
fi
|
||||||
|
ac_add_options --enable-bootstrap
|
||||||
|
ac_add_options --with-macos-sdk=$HOME/src/MacOSX26.5.sdk
|
||||||
|
|
||||||
|
mk_add_options AUTOCLOBBER=1
|
||||||
|
|
||||||
|
# These don't all affect the stub, but they can't hurt, and we'll want them if
|
||||||
|
# we switch to custom XUL builds
|
||||||
|
ac_add_options MOZ_ENABLE_JS_DUMP=1
|
||||||
|
ac_add_options MOZ_ENABLE_FORKSERVER=
|
||||||
|
ac_add_options MOZ_TELEMETRY_REPORTING=
|
||||||
|
ac_add_options MOZ_DATA_REPORTING=
|
||||||
|
ac_add_options --disable-tests
|
||||||
|
ac_add_options --disable-debug
|
||||||
|
ac_add_options --disable-debug-symbols
|
||||||
|
ac_add_options --disable-webrtc
|
||||||
|
ac_add_options --disable-eme
|
||||||
|
|
||||||
|
export MOZILLA_OFFICIAL=1
|
||||||
|
export RELEASE_OR_BETA=1
|
||||||
|
MOZ_REQUIRE_SIGNING=
|
||||||
|
|
||||||
|
# Official builds require source info, which Mozilla only detects automatically from
|
||||||
|
# Mercurial checkouts
|
||||||
|
export MOZ_SOURCE_REPO=https://github.com/mozilla-firefox/firefox
|
||||||
|
export MOZ_SOURCE_CHANGESET=$(git -C "$topsrcdir" rev-parse HEAD)
|
||||||
|
|
||||||
|
ac_add_options --enable-official-branding
|
||||||
|
|
||||||
|
# Build updater without MAR signature verification
|
||||||
|
ac_add_options --enable-unverified-updates
|
||||||
1508
app/mac/mozilla-115.patch
Normal file
1508
app/mac/mozilla-115.patch
Normal file
File diff suppressed because it is too large
Load diff
242
app/mac/mozilla-153.patch
Normal file
242
app/mac/mozilla-153.patch
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp
|
||||||
|
--- a/browser/app/nsBrowserApp.cpp
|
||||||
|
+++ b/browser/app/nsBrowserApp.cpp
|
||||||
|
@@ -193,19 +193,31 @@ static bool HasFlag(int argc, char* argv[], const char* s) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constinit Bootstrap::UniquePtr gBootstrap;
|
||||||
|
|
||||||
|
static int do_main(int argc, char* argv[], char* envp[]) {
|
||||||
|
+ // Allow profile downgrade for Zotero
|
||||||
|
+ setenv("MOZ_ALLOW_DOWNGRADE", "1", 1);
|
||||||
|
+ // Don't create dedicated profile (default-esr)
|
||||||
|
+ setenv("MOZ_LEGACY_PROFILES", "1", 1);
|
||||||
|
+
|
||||||
|
// Allow firefox.exe to launch XULRunner apps via -app <application.ini>
|
||||||
|
// Note that -app must be the *first* argument.
|
||||||
|
- const char* appDataFile = getenv("XUL_APP_FILE");
|
||||||
|
+ UniqueFreePtr<char> iniPath = BinaryPath::GetApplicationIni();
|
||||||
|
+ if (!iniPath) {
|
||||||
|
+ Output("Couldn't find application.ini.\n");
|
||||||
|
+ return 255;
|
||||||
|
+ }
|
||||||
|
+ char *appDataFile = iniPath.get();
|
||||||
|
+
|
||||||
|
+
|
||||||
|
if ((!appDataFile || !*appDataFile) && (argc > 1 && IsFlag(argv[1], "app"))) {
|
||||||
|
if (argc == 2) {
|
||||||
|
Output("Incorrect number of arguments passed to -app");
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
appDataFile = argv[2];
|
||||||
|
|
||||||
|
char appEnv[MAXPATHLEN];
|
||||||
|
diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h
|
||||||
|
--- a/xpcom/build/BinaryPath.h
|
||||||
|
+++ b/xpcom/build/BinaryPath.h
|
||||||
|
@@ -126,16 +126,56 @@ class BinaryPath {
|
||||||
|
} else {
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRelease(executableURL);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ static nsresult GetApplicationIni(char aResult[MAXPATHLEN])
|
||||||
|
+ {
|
||||||
|
+ // Works even if we're not bundled.
|
||||||
|
+ CFBundleRef appBundle = CFBundleGetMainBundle();
|
||||||
|
+ if (!appBundle) {
|
||||||
|
+ return NS_ERROR_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ CFURLRef iniURL = CFBundleCopyResourceURL(appBundle, CFSTR("application.ini"),
|
||||||
|
+ NULL, CFSTR("app"));
|
||||||
|
+ if (!iniURL) {
|
||||||
|
+ return NS_ERROR_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ nsresult rv;
|
||||||
|
+ if (CFURLGetFileSystemRepresentation(iniURL, false, (UInt8*)aResult,
|
||||||
|
+ MAXPATHLEN)) {
|
||||||
|
+ // Sanitize path in case the app was launched from Terminal via
|
||||||
|
+ // './firefox' for example.
|
||||||
|
+ size_t readPos = 0;
|
||||||
|
+ size_t writePos = 0;
|
||||||
|
+ while (aResult[readPos] != '\0') {
|
||||||
|
+ if (aResult[readPos] == '.' && aResult[readPos + 1] == '/') {
|
||||||
|
+ readPos += 2;
|
||||||
|
+ } else {
|
||||||
|
+ aResult[writePos] = aResult[readPos];
|
||||||
|
+ readPos++;
|
||||||
|
+ writePos++;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ aResult[writePos] = '\0';
|
||||||
|
+ rv = NS_OK;
|
||||||
|
+ } else {
|
||||||
|
+ rv = NS_ERROR_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ CFRelease(iniURL);
|
||||||
|
+ return rv;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
#elif defined(ANDROID)
|
||||||
|
static nsresult Get(char aResult[MAXPATHLEN]) {
|
||||||
|
// On Android, we use the MOZ_ANDROID_LIBDIR variable that is set by the
|
||||||
|
// Java bootstrap code.
|
||||||
|
const char* libDir = getenv("MOZ_ANDROID_LIBDIR");
|
||||||
|
if (!libDir) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
@@ -281,16 +321,29 @@ class BinaryPath {
|
||||||
|
if (NS_FAILED(Get(path))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
UniqueFreePtr<char> result;
|
||||||
|
result.reset(strdup(path));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#if defined(XP_MACOSX)
|
||||||
|
+ static UniqueFreePtr<char> GetApplicationIni()
|
||||||
|
+ {
|
||||||
|
+ char path[MAXPATHLEN];
|
||||||
|
+ if (NS_FAILED(GetApplicationIni(path))) {
|
||||||
|
+ return nullptr;
|
||||||
|
+ }
|
||||||
|
+ UniqueFreePtr<char> result;
|
||||||
|
+ result.reset(strdup(path));
|
||||||
|
+ return result;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
|
static nsresult GetFile(nsIFile** aResult) {
|
||||||
|
nsCOMPtr<nsIFile> lf;
|
||||||
|
# ifdef XP_WIN
|
||||||
|
wchar_t exePath[MAXPATHLEN];
|
||||||
|
nsresult rv = GetW(exePath);
|
||||||
|
# else
|
||||||
|
char exePath[MAXPATHLEN];
|
||||||
|
diff --git a/mozglue/build/AudioQueueSanitizer.cpp b/mozglue/build/AudioQueueSanitizer.cpp
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000000..9efa3255c472
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/mozglue/build/AudioQueueSanitizer.cpp
|
||||||
|
@@ -0,0 +1,91 @@
|
||||||
|
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
+/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
+
|
||||||
|
+// Work around a use-after-free in the macOS 27 system speech synthesizer.
|
||||||
|
+//
|
||||||
|
+// When an utterance finishes, the AudioQueue player in the private
|
||||||
|
+// TextToSpeech framework (used by both NSSpeechSynthesizer and
|
||||||
|
+// AVSpeechSynthesizer) enqueues a short de-click ramp that starts from a
|
||||||
|
+// sample read out of a buffer it has already freed. With the system
|
||||||
|
+// allocator, which zeroes freed memory, that sample is 0 and the ramp is
|
||||||
|
+// silent. mozjemalloc poisons freed memory with 0xE5 instead, which reads
|
||||||
|
+// as -1.36e23 in float32, so every utterance ends with a ~10 ms full-scale
|
||||||
|
+// burst.
|
||||||
|
+//
|
||||||
|
+// We can't fix the framework, so we interpose AudioQueueEnqueueBuffer and
|
||||||
|
+// zero any float samples that are non-finite or far outside the nominal
|
||||||
|
+// [-1, 1] range before they reach CoreAudio. Real audio never gets close
|
||||||
|
+// to kMaxSampleMagnitude, so this only ever affects garbage.
|
||||||
|
+//
|
||||||
|
+// dyld only honors __interpose tuples in images loaded at launch, which is
|
||||||
|
+// why this needs to be in mozglue rather than in XUL (loaded with dlopen)
|
||||||
|
+// alongside OSXSpeechSynthesizerService.
|
||||||
|
+
|
||||||
|
+#include <AudioToolbox/AudioToolbox.h>
|
||||||
|
+#include <math.h>
|
||||||
|
+
|
||||||
|
+namespace {
|
||||||
|
+
|
||||||
|
+constexpr float kMaxSampleMagnitude = 16.0f;
|
||||||
|
+
|
||||||
|
+void SanitizeBuffer(AudioQueueRef aQueue, AudioQueueBufferRef aBuffer) {
|
||||||
|
+ AudioStreamBasicDescription format;
|
||||||
|
+ UInt32 size = sizeof(format);
|
||||||
|
+ if (AudioQueueGetProperty(aQueue, kAudioQueueProperty_StreamDescription,
|
||||||
|
+ &format, &size) != noErr) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (format.mFormatID != kAudioFormatLinearPCM ||
|
||||||
|
+ !(format.mFormatFlags & kAudioFormatFlagIsFloat) ||
|
||||||
|
+ format.mBitsPerChannel != 32) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ float* samples = static_cast<float*>(aBuffer->mAudioData);
|
||||||
|
+ UInt32 count = aBuffer->mAudioDataByteSize / sizeof(float);
|
||||||
|
+ for (UInt32 i = 0; i < count; i++) {
|
||||||
|
+ // Written so that NaN also fails the comparison.
|
||||||
|
+ if (!(fabsf(samples[i]) <= kMaxSampleMagnitude)) {
|
||||||
|
+ samples[i] = 0.0f;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+OSStatus SanitizingEnqueueBuffer(
|
||||||
|
+ AudioQueueRef aQueue, AudioQueueBufferRef aBuffer, UInt32 aNumPackets,
|
||||||
|
+ const AudioStreamPacketDescription* aPacketDescs) {
|
||||||
|
+ SanitizeBuffer(aQueue, aBuffer);
|
||||||
|
+ return AudioQueueEnqueueBuffer(aQueue, aBuffer, aNumPackets, aPacketDescs);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+OSStatus SanitizingEnqueueBufferWithParameters(
|
||||||
|
+ AudioQueueRef aQueue, AudioQueueBufferRef aBuffer, UInt32 aNumPackets,
|
||||||
|
+ const AudioStreamPacketDescription* aPacketDescs, UInt32 aTrimFrames,
|
||||||
|
+ UInt32 aTrimFramesAtEnd, UInt32 aNumParamValues,
|
||||||
|
+ const AudioQueueParameterEvent* aParamValues,
|
||||||
|
+ const AudioTimeStamp* aStartTime, AudioTimeStamp* aActualStartTime) {
|
||||||
|
+ SanitizeBuffer(aQueue, aBuffer);
|
||||||
|
+ return AudioQueueEnqueueBufferWithParameters(
|
||||||
|
+ aQueue, aBuffer, aNumPackets, aPacketDescs, aTrimFrames,
|
||||||
|
+ aTrimFramesAtEnd, aNumParamValues, aParamValues, aStartTime,
|
||||||
|
+ aActualStartTime);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct Interpose {
|
||||||
|
+ const void* mReplacement;
|
||||||
|
+ const void* mReplacee;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+__attribute__((used, section("__DATA,__interpose"))) const Interpose
|
||||||
|
+ kInterposes[] = {
|
||||||
|
+ {reinterpret_cast<const void*>(&SanitizingEnqueueBuffer),
|
||||||
|
+ reinterpret_cast<const void*>(&AudioQueueEnqueueBuffer)},
|
||||||
|
+ {reinterpret_cast<const void*>(&SanitizingEnqueueBufferWithParameters),
|
||||||
|
+ reinterpret_cast<const void*>(
|
||||||
|
+ &AudioQueueEnqueueBufferWithParameters)},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+} // namespace
|
||||||
|
diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build
|
||||||
|
index f8f01e999e54..111fe5af1b0d 100644
|
||||||
|
--- a/mozglue/build/moz.build
|
||||||
|
+++ b/mozglue/build/moz.build
|
||||||
|
@@ -41,6 +41,14 @@ if CONFIG["OS_TARGET"] == "WINNT":
|
||||||
|
"winmm.dll",
|
||||||
|
]
|
||||||
|
|
||||||
|
+if CONFIG["OS_TARGET"] == "Darwin" and FORCE_SHARED_LIB:
|
||||||
|
+ SOURCES += [
|
||||||
|
+ "AudioQueueSanitizer.cpp",
|
||||||
|
+ ]
|
||||||
|
+ OS_LIBS += [
|
||||||
|
+ "-framework AudioToolbox",
|
||||||
|
+ ]
|
||||||
|
+
|
||||||
|
if CONFIG["MOZ_WIDGET_TOOLKIT"]:
|
||||||
|
if CONFIG["MOZ_MEMORY"] and FORCE_SHARED_LIB:
|
||||||
|
pass
|
||||||
1581
app/mac/pkg-dmg
Executable file
1581
app/mac/pkg-dmg
Executable file
File diff suppressed because it is too large
Load diff
69
app/mac/set-channel-prefs-channel
Executable file
69
app/mac/set-channel-prefs-channel
Executable file
|
|
@ -0,0 +1,69 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Replace channel in ChannelPrefs, with appropriate null-byte padding
|
||||||
|
#
|
||||||
|
# ChannelPrefs.framework needs to be signed, which we can't do during normal source builds, so we
|
||||||
|
# use this to replace 'default' in our custom framework with 'source\0' and store that, and then
|
||||||
|
# when making real builds we replace 'source\0' with 'release'/'beta'/'dev'/'test' (padded to 7 chars)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ] || [ -z "${2:-}" ] || [ -z "${3:-}" ]; then
|
||||||
|
echo "Usage: $0 /path/to/ChannelPrefs.framework/ChannelPrefs from_channel to_channel" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
binary=$1
|
||||||
|
from_channel=$2
|
||||||
|
to_channel=$3
|
||||||
|
# `strings` has a 4-character minimum by default, but we need 3 for 'dev'
|
||||||
|
# `-arch all` scans all slices of the universal binary rather than just the host architecture
|
||||||
|
strings_cmd="strings -n 3 -arch all"
|
||||||
|
|
||||||
|
if [ ${#to_channel} -gt 7 ]; then
|
||||||
|
echo "Channel length cannot exceed 7 characters -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $($strings_cmd "$binary" | grep -c "$from_channel") -ne 2 ] ; then
|
||||||
|
echo "$from_channel not found twice in ChannelPrefs" >&2
|
||||||
|
echo >&2
|
||||||
|
$strings_cmd "$binary" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
original_size=$(wc -c "$binary" | awk '{print $1}')
|
||||||
|
|
||||||
|
perl -pi -e '
|
||||||
|
binmode(STDIN);
|
||||||
|
binmode(STDOUT);
|
||||||
|
use bytes;
|
||||||
|
my @channels = qw(release beta dev test source); # List of valid channels
|
||||||
|
# Channels from Bash
|
||||||
|
my $from_channel = "'"$from_channel"'";
|
||||||
|
my $to_channel = "'"$to_channel"'";
|
||||||
|
if (grep { $_ eq $to_channel } @channels) {
|
||||||
|
# Pad channels with null bytes
|
||||||
|
$from_channel .= "\0" x (7 - length($from_channel));
|
||||||
|
$to_channel .= "\0" x (7 - length($to_channel));
|
||||||
|
} else {
|
||||||
|
die "Unknown update channel: $to_channel\n";
|
||||||
|
}
|
||||||
|
s/$from_channel/$to_channel/g;
|
||||||
|
' "$binary"
|
||||||
|
|
||||||
|
new_size=$(wc -c "$binary" | awk '{print $1}')
|
||||||
|
if [ $original_size -ne $new_size ]; then
|
||||||
|
echo "File size of ChannelPrefs has changed -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $($strings_cmd "$binary" | grep -c "$to_channel") -ne 2 ] ; then
|
||||||
|
echo "$to_channel not found twice in ChannelPrefs" >&2
|
||||||
|
$strings_cmd "$binary" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
$strings_cmd "$binary"
|
||||||
3
app/mac/updater.tar.xz
Normal file
3
app/mac/updater.tar.xz
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:361730d7cea854b38c6968143555c5f5fe251e1c95f265a6133514ee72ea2c53
|
||||||
|
size 98904
|
||||||
10
app/mac/updater_renamer
Executable file
10
app/mac/updater_renamer
Executable file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Convert localized app name from "Firefox Software Update" to "Zotero Software Update"
|
||||||
|
#
|
||||||
|
# plist is UTF-16
|
||||||
|
f='updater.app/Contents/Resources/English.lproj/InfoPlist.strings'
|
||||||
|
with open(f, 'r', encoding='utf-16') as inputfile:
|
||||||
|
newText = inputfile.read().replace('Firefox', 'Zotero')
|
||||||
|
with open(f, 'w', encoding='utf-16') as outputfile:
|
||||||
|
outputfile.write(newText)
|
||||||
BIN
app/mac/zotero.xz
Executable file
BIN
app/mac/zotero.xz
Executable file
Binary file not shown.
1
app/modules/zotero-libreoffice-integration
Submodule
1
app/modules/zotero-libreoffice-integration
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 2e78b1010ad49b4dde70ec9f0094b34a7b6f8965
|
||||||
1
app/modules/zotero-word-for-mac-integration
Submodule
1
app/modules/zotero-word-for-mac-integration
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 300886d1984de7a0006d7a48310baa0c8c99bea0
|
||||||
1
app/modules/zotero-word-for-windows-integration
Submodule
1
app/modules/zotero-word-for-windows-integration
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit c0aa6e4bef039d94e17e81cb28b1fe9170c45b96
|
||||||
64
app/scripts/10.0_release_build_and_deploy
Executable file
64
app/scripts/10.0_release_build_and_deploy
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
CHANNEL="release"
|
||||||
|
BRANCH="10.0"
|
||||||
|
BUILD_ONLY=0
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
export SAFARI_APPEX="$ROOT_DIR/../safari-web-extension-builds/ZoteroSafariExtension.appex"
|
||||||
|
export SAFARI_EXT_RESOURCES="$ROOT_DIR/../safari-web-extension-builds/release/safari"
|
||||||
|
export SAFARI_APP_EXTENSION="$ROOT_DIR/../safari-app-extension-builds/release/ZoteroSafariExtension.appex"
|
||||||
|
if [ ! -d "$SAFARI_APPEX" ]; then
|
||||||
|
echo "Safari extension stub not found at $SAFARI_APPEX -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$SAFARI_EXT_RESOURCES/manifest.json" ]; then
|
||||||
|
echo "Safari web extension not found in $SAFARI_EXT_RESOURCES -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -d "$SAFARI_APP_EXTENSION" ]; then
|
||||||
|
echo "Safari App Extension not found at $SAFARI_APP_EXTENSION -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
while getopts "b" opt; do
|
||||||
|
case $opt in
|
||||||
|
b)
|
||||||
|
BUILD_ONLY=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
./check_requirements
|
||||||
|
|
||||||
|
hash=`./get_repo_branch_hash $BRANCH`
|
||||||
|
./check_app_matches_commit $hash
|
||||||
|
source_dir=`./get_commit_files $hash`
|
||||||
|
build_dir=`mktemp -d`
|
||||||
|
|
||||||
|
function cleanup {
|
||||||
|
rm -rf "$source_dir"
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
./prepare_build -s "$source_dir" -o "$build_dir" -c $CHANNEL -m $hash
|
||||||
|
VERSION="`cat \"$build_dir/version\"`"
|
||||||
|
./build_for_deploy -d "$build_dir" -p $BUILD_PLATFORMS -c $CHANNEL
|
||||||
|
|
||||||
|
if [ $BUILD_ONLY -eq 1 ]; then
|
||||||
|
echo
|
||||||
|
echo "Build only -- skipping deploy."
|
||||||
|
echo "To deploy, run on the deploy server:"
|
||||||
|
echo " $DEPLOY_PATH/deploy $CHANNEL $VERSION $BUILD_PLATFORMS"
|
||||||
|
else
|
||||||
|
ssh $DEPLOY_HOST "$DEPLOY_PATH/deploy" $CHANNEL "$VERSION" $BUILD_PLATFORMS
|
||||||
|
fi
|
||||||
55
app/scripts/add_omni_file
Executable file
55
app/scripts/add_omni_file
Executable file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# Zip a file directly into app/omni.ja in staging/
|
||||||
|
#
|
||||||
|
# Zip paths are relative to the current directory, so this should be run from
|
||||||
|
# the client build/ directory
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage: $0 path/to/file
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
files="$@"
|
||||||
|
|
||||||
|
for file in $files; do
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo "Error: $file not found!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
mac_path="$STAGE_DIR/Zotero.app/Contents/Resources"
|
||||||
|
win_path="$STAGE_DIR/Zotero_win-x64"
|
||||||
|
linux_path="$STAGE_DIR/Zotero_linux-x86_64"
|
||||||
|
|
||||||
|
added=0
|
||||||
|
build_id=$(date +%Y%m%d%H%M%S)
|
||||||
|
for path in "$mac_path" "$win_path" "$linux_path"; do
|
||||||
|
if [ -d "$path" ]; then
|
||||||
|
echo "$path/app/omni.ja"
|
||||||
|
echo "Updating $(basename $(dirname $(dirname $path)))"
|
||||||
|
zip "$path/app/omni.ja" $files
|
||||||
|
# Bump BuildID so that startup caches are invalidated
|
||||||
|
perl -pi -e "s/^BuildID=.*/BuildID=$build_id/" "$path/app/application.ini"
|
||||||
|
added=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $added -eq 0 ]; then
|
||||||
|
echo "No directories found in staging!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
62
app/scripts/add_version_info
Executable file
62
app/scripts/add_version_info
Executable file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Update a builds manifest with info on a given build
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import json
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
MAJOR = None
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Update a builds manifest with info on a given build',
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
|
|
||||||
|
parser.add_argument('-f', '--file', required=True, help="path to updates.json")
|
||||||
|
parser.add_argument('-v', '--version', required=True, help='version number of build')
|
||||||
|
parser.add_argument('-b', '--build_id', required=True, help="build ID ('20160801142343')")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
file = args.file
|
||||||
|
version = args.version
|
||||||
|
short_version = re.match(r'\d+\.\d+', version).group(0)
|
||||||
|
|
||||||
|
# Back up JSON file
|
||||||
|
shutil.copy2(file, file + '.bak')
|
||||||
|
|
||||||
|
# Read in existing file
|
||||||
|
with open(file) as f:
|
||||||
|
updates = json.loads(f.read())
|
||||||
|
|
||||||
|
updates.append({
|
||||||
|
'version': version,
|
||||||
|
'buildID': args.build_id,
|
||||||
|
'detailsURL': f'https://www.zotero.org/support/{short_version}_changelog',
|
||||||
|
'major': MAJOR
|
||||||
|
})
|
||||||
|
|
||||||
|
# Keep last 5 entries
|
||||||
|
updates = updates[-5:]
|
||||||
|
|
||||||
|
# Write new file
|
||||||
|
updates = json.dumps(updates, indent=2)
|
||||||
|
with open(file, 'w') as f:
|
||||||
|
f.write(updates + "\n")
|
||||||
|
|
||||||
|
print(updates)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
sys.stderr.write("\n" + traceback.format_exc())
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
64
app/scripts/beta_build_and_deploy
Executable file
64
app/scripts/beta_build_and_deploy
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
CHANNEL="beta"
|
||||||
|
BRANCH="main"
|
||||||
|
BUILD_ONLY=0
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
export SAFARI_APPEX="$ROOT_DIR/../safari-web-extension-builds/ZoteroSafariExtension.appex"
|
||||||
|
export SAFARI_EXT_RESOURCES="$ROOT_DIR/../safari-web-extension-builds/beta/safari"
|
||||||
|
export SAFARI_APP_EXTENSION="$ROOT_DIR/../safari-app-extension-builds/beta/ZoteroSafariExtension.appex"
|
||||||
|
if [ ! -d "$SAFARI_APPEX" ]; then
|
||||||
|
echo "Safari extension stub not found at $SAFARI_APPEX -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$SAFARI_EXT_RESOURCES/manifest.json" ]; then
|
||||||
|
echo "Safari web extension not found in $SAFARI_EXT_RESOURCES -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -d "$SAFARI_APP_EXTENSION" ]; then
|
||||||
|
echo "Safari App Extension not found at $SAFARI_APP_EXTENSION -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
while getopts "b" opt; do
|
||||||
|
case $opt in
|
||||||
|
b)
|
||||||
|
BUILD_ONLY=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
./check_requirements
|
||||||
|
|
||||||
|
hash=`./get_repo_branch_hash $BRANCH`
|
||||||
|
./check_app_matches_commit $hash
|
||||||
|
source_dir=`./get_commit_files $hash`
|
||||||
|
build_dir=`mktemp -d`
|
||||||
|
|
||||||
|
function cleanup {
|
||||||
|
rm -rf "$source_dir"
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
./prepare_build -s "$source_dir" -o "$build_dir" -c $CHANNEL -m $hash
|
||||||
|
VERSION="`cat \"$build_dir/version\"`"
|
||||||
|
./build_for_deploy -d "$build_dir" -p $BUILD_PLATFORMS -c $CHANNEL
|
||||||
|
|
||||||
|
if [ $BUILD_ONLY -eq 1 ]; then
|
||||||
|
echo
|
||||||
|
echo "Build only -- skipping deploy."
|
||||||
|
echo "To deploy, run on the deploy server:"
|
||||||
|
echo " $DEPLOY_PATH/deploy $CHANNEL $VERSION $BUILD_PLATFORMS"
|
||||||
|
else
|
||||||
|
ssh $DEPLOY_HOST "$DEPLOY_PATH/deploy" $CHANNEL "$VERSION" $BUILD_PLATFORMS
|
||||||
|
fi
|
||||||
98
app/scripts/build_and_run
Executable file
98
app/scripts/build_and_run
Executable file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname $APP_ROOT_DIR)"
|
||||||
|
|
||||||
|
# Set ZOTERO_PROFILE environment variable to choose profile
|
||||||
|
profile_args=()
|
||||||
|
if [ -n "${ZOTERO_PROFILE:-}" ]; then
|
||||||
|
profile_args=(-p "$ZOTERO_PROFILE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
FORCE_FULL=0
|
||||||
|
NO_REBUILD=0
|
||||||
|
SKIP_BUNDLED_FILES=0
|
||||||
|
DEBUGGER=0
|
||||||
|
while getopts "rfnbd" opt; do
|
||||||
|
case $opt in
|
||||||
|
r)
|
||||||
|
# Deprecated -- rebuilding is now the default
|
||||||
|
echo "-r is deprecated -- rebuilding is now the default (use -n to skip)" >&2
|
||||||
|
;;
|
||||||
|
|
||||||
|
f)
|
||||||
|
FORCE_FULL=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
n)
|
||||||
|
NO_REBUILD=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
b)
|
||||||
|
SKIP_BUNDLED_FILES=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
d)
|
||||||
|
DEBUGGER=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
\?)
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove options from $@
|
||||||
|
shift $((OPTIND-1))
|
||||||
|
|
||||||
|
if [ $NO_REBUILD -eq 0 ]; then
|
||||||
|
PARAMS=""
|
||||||
|
if [ $DEBUGGER -eq 1 ]; then
|
||||||
|
PARAMS="-t"
|
||||||
|
fi
|
||||||
|
if [ $FORCE_FULL -eq 1 ]; then
|
||||||
|
PARAMS="$PARAMS -f"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if build watch is running
|
||||||
|
# If not, run now
|
||||||
|
if ! ps u | grep js-build/build.js | grep -v grep > /dev/null; then
|
||||||
|
echo "Running JS build process"
|
||||||
|
echo
|
||||||
|
cd $ROOT_DIR
|
||||||
|
# TEMP: --openssl-legacy-provider avoids a build error in pdf.js
|
||||||
|
NODE_OPTIONS=--openssl-legacy-provider node js-build/build.js
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$SCRIPT_DIR/dir_build" $PARAMS
|
||||||
|
fi
|
||||||
|
|
||||||
|
PARAMS=""
|
||||||
|
if [ $SKIP_BUNDLED_FILES -eq 1 ]; then
|
||||||
|
PARAMS="$PARAMS -ZoteroSkipBundledFiles"
|
||||||
|
fi
|
||||||
|
if [ $DEBUGGER -eq 1 ]; then
|
||||||
|
PARAMS="$PARAMS -jsdebugger"
|
||||||
|
else
|
||||||
|
PARAMS="$PARAMS -jsconsole"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
command="Zotero.app/Contents/MacOS/zotero"
|
||||||
|
elif [ "`uname`" = "Linux" ]; then
|
||||||
|
if [[ "`uname -m`" = "aarch64" ]]; then
|
||||||
|
command="Zotero_linux-arm64/zotero"
|
||||||
|
else
|
||||||
|
command="Zotero_linux-x86_64/zotero"
|
||||||
|
fi
|
||||||
|
elif [ "`uname -o 2> /dev/null`" = "Cygwin" ]; then
|
||||||
|
command="Zotero_win-x64/zotero.exe"
|
||||||
|
else
|
||||||
|
echo "Unknown platform" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
"$APP_ROOT_DIR/staging/$command" "${profile_args[@]}" -ZoteroDebugText $PARAMS "$@"
|
||||||
167
app/scripts/build_for_deploy
Executable file
167
app/scripts/build_for_deploy
Executable file
|
|
@ -0,0 +1,167 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Builds Zotero and uploads to S3 and deploy server, but does not make the build live.
|
||||||
|
# To make the build live, run the deploy script on the deploy server (or via SSH).
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage: $0 -d SOURCE_DIR -c CHANNEL -p PLATFORMS
|
||||||
|
-d SOURCE_DIR Source directory to build from
|
||||||
|
-c CHANNEL Release channel ('release', 'beta', 'dev')
|
||||||
|
-p PLATFORMS Platforms to build (m=Mac, w=Windows, l=Linux)
|
||||||
|
-i INCREMENTALS Number of incremental builds to create
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SOURCE_DIR=""
|
||||||
|
CHANNEL=""
|
||||||
|
PLATFORMS=""
|
||||||
|
while getopts "d:c:p:i:" opt; do
|
||||||
|
case $opt in
|
||||||
|
d)
|
||||||
|
SOURCE_DIR="$OPTARG"
|
||||||
|
if [ ! -d "$SOURCE_DIR" ]; then
|
||||||
|
echo "$SOURCE_DIR not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
c)
|
||||||
|
CHANNEL="$OPTARG"
|
||||||
|
;;
|
||||||
|
p)
|
||||||
|
PLATFORMS="$OPTARG"
|
||||||
|
;;
|
||||||
|
i)
|
||||||
|
NUM_INCREMENTALS="$OPTARG"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$SOURCE_DIR" ]] || [[ -z "$CHANNEL" ]] || [[ -z "$PLATFORMS" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$SCRIPT_DIR"/check_requirements
|
||||||
|
|
||||||
|
VERSION="`cat \"$SOURCE_DIR\"/version`"
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
echo "Error getting version from $SOURCE_DIR/version"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enforce signing unless a test build or macOS, which doesn't start otherwise
|
||||||
|
if [[ "$CHANNEL" != "test" || $PLATFORMS = "m" ]]; then
|
||||||
|
SIGN="-e"
|
||||||
|
else
|
||||||
|
SIGN=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build Zotero
|
||||||
|
"$ROOT_DIR/build.sh" -d "$SOURCE_DIR" -p $PLATFORMS -c $CHANNEL $SIGN
|
||||||
|
|
||||||
|
BUILD_ID=`cat "$DIST_DIR/build_id"`
|
||||||
|
if [ -z "$BUILD_ID" ]; then
|
||||||
|
echo "Error getting build id"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEMP_DIR=`mktemp -d`
|
||||||
|
# Clean up on exit
|
||||||
|
function cleanup {
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Build full update
|
||||||
|
"$ROOT_DIR/update-packaging/build_autoupdate.sh" -f -c $CHANNEL -p $PLATFORMS -l $VERSION
|
||||||
|
|
||||||
|
# Build incremental updates for each platform
|
||||||
|
for i in `seq 0 1 $((${#PLATFORMS}-1))`
|
||||||
|
do
|
||||||
|
case ${PLATFORMS:i:1} in
|
||||||
|
m)
|
||||||
|
platform=mac
|
||||||
|
platform_name=Mac
|
||||||
|
;;
|
||||||
|
w)
|
||||||
|
platform=win
|
||||||
|
platform_name=Windows
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
platform=linux
|
||||||
|
platform_name=Linux
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$0: Invalid platform option ${PLATFORMS:i:1}"
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Getting $platform_name incrementals"
|
||||||
|
INCREMENTALS="`\"$SCRIPT_DIR/manage_incrementals\" -c $CHANNEL -p ${PLATFORMS:i:1} -n $NUM_INCREMENTALS`"
|
||||||
|
|
||||||
|
# Fetch pinned incrementals from deploy server and merge
|
||||||
|
PINNED_FILE="$DEPLOY_PATH/manifests/$CHANNEL/pinned-incrementals-$platform"
|
||||||
|
PINNED=""
|
||||||
|
if ssh $DEPLOY_HOST "test -f $PINNED_FILE"; then
|
||||||
|
PINNED="`ssh $DEPLOY_HOST cat $PINNED_FILE`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Combine and deduplicate
|
||||||
|
INCREMENTALS="`echo -e "$INCREMENTALS\n$PINNED" | sort -u | grep -v '^$' || true`"
|
||||||
|
echo "$INCREMENTALS"
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [ -n "$INCREMENTALS" ]; then
|
||||||
|
for from in $INCREMENTALS; do
|
||||||
|
echo "Building incremental update for $platform_name from $from to $VERSION"
|
||||||
|
"$ROOT_DIR/update-packaging/build_autoupdate.sh" -i "$from" -c "$CHANNEL" -p ${PLATFORMS:i:1} -l $VERSION
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Upload builds to S3
|
||||||
|
"$SCRIPT_DIR/upload_builds" $CHANNEL $VERSION
|
||||||
|
|
||||||
|
# Upload file lists and build info for each platform
|
||||||
|
channel_deploy_path="$DEPLOY_PATH/manifests/$CHANNEL"
|
||||||
|
mkdir "$TEMP_DIR/version_info"
|
||||||
|
chmod g+ws "$TEMP_DIR/version_info"
|
||||||
|
cp "$DIST_DIR"/files-* "$TEMP_DIR/version_info"
|
||||||
|
chmod g+w "$TEMP_DIR"/version_info/files-*
|
||||||
|
# Generate build-{os}.json for each platform
|
||||||
|
SHORT_VERSION=$(echo "$VERSION" | grep -oE '^[0-9]+\.[0-9]+')
|
||||||
|
DETAILS_URL="https://www.zotero.org/support/${SHORT_VERSION}_changelog"
|
||||||
|
for i in `seq 0 1 $((${#PLATFORMS}-1))`
|
||||||
|
do
|
||||||
|
case ${PLATFORMS:i:1} in
|
||||||
|
m) os_name="mac" ;;
|
||||||
|
w) os_name="win" ;;
|
||||||
|
l) os_name="linux" ;;
|
||||||
|
esac
|
||||||
|
printf '{\n "buildID": "%s",\n "detailsURL": "%s"\n}\n' "$BUILD_ID" "$DETAILS_URL" \
|
||||||
|
> "$TEMP_DIR/version_info/build-${os_name}.json"
|
||||||
|
chmod g+w "$TEMP_DIR/version_info/build-${os_name}.json"
|
||||||
|
done
|
||||||
|
rsync -rv "$TEMP_DIR/version_info/" $DEPLOY_HOST:"$channel_deploy_path/$VERSION/"
|
||||||
|
|
||||||
|
rm -rf "$STAGE_DIR"/*
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Build $VERSION uploaded successfully."
|
||||||
|
echo "To deploy, run on the deploy server:"
|
||||||
|
echo " ./deploy $CHANNEL $VERSION $PLATFORMS"
|
||||||
37
app/scripts/check_app_matches_commit
Executable file
37
app/scripts/check_app_matches_commit
Executable file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Check that app/ in this checkout matches app/ in the commit being built.
|
||||||
|
#
|
||||||
|
# The build-and-deploy scripts run the build scripts and config from the local
|
||||||
|
# checkout but build source files from the tip of the remote branch, so a stale
|
||||||
|
# checkout can silently build with the wrong Gecko version or omni patches.
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
echo "Usage: $0 commit-hash" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
hash=$1
|
||||||
|
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
if ! git cat-file -e "$hash^{commit}" 2>/dev/null; then
|
||||||
|
git fetch -q origin
|
||||||
|
fi
|
||||||
|
if ! git cat-file -e "$hash^{commit}" 2>/dev/null; then
|
||||||
|
echo "Commit $hash not found locally after fetching -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git diff --quiet HEAD "$hash" -- app/; then
|
||||||
|
echo >&2
|
||||||
|
echo "app/ files in this checkout differ from app/ in $hash:" >&2
|
||||||
|
echo >&2
|
||||||
|
git --no-pager diff --stat HEAD "$hash" -- app/ >&2
|
||||||
|
echo >&2
|
||||||
|
echo "Update this checkout (e.g., 'git pull') and try again" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
158
app/scripts/check_requirements
Executable file
158
app/scripts/check_requirements
Executable file
|
|
@ -0,0 +1,158 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$APP_ROOT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
. "$SCRIPT_DIR/utils.sh"
|
||||||
|
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
platform=`get_current_platform`
|
||||||
|
|
||||||
|
FAIL_CMD='echo -e \033[31;1mFAIL\033[0m'
|
||||||
|
FAIL_CMD_INLINE='echo -n -e \033[31;1mFAIL\033[0m'
|
||||||
|
FAILED=0
|
||||||
|
|
||||||
|
hdr_start=`tput smul`
|
||||||
|
hdr_stop=`tput rmul`
|
||||||
|
|
||||||
|
echo "${hdr_start}Checking build requirements:${hdr_stop}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo -n "Checking for Node.js: "
|
||||||
|
which node || { $FAIL_CMD_INLINE; FAILED=1; }
|
||||||
|
node_version=$(node -v | cut -c 2-)
|
||||||
|
echo -n "Checking Node version: $node_version"
|
||||||
|
if [ $(echo $node_version | cut -d '.' -f1 ) -ge "18" ]; then
|
||||||
|
echo
|
||||||
|
else
|
||||||
|
echo -n " -- must be 18 or later "
|
||||||
|
{ $FAIL_CMD; FAILED=1; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n "Checking for Git LFS: "
|
||||||
|
which git-lfs || { $FAIL_CMD_INLINE; FAILED=1; }
|
||||||
|
|
||||||
|
echo "Checking for Git LFS checkouts: "
|
||||||
|
lfs_files=$(git lfs ls-files -n 2> /dev/null) || { $FAIL_CMD; FAILED=1; }
|
||||||
|
for lfs_file in $lfs_files; do
|
||||||
|
echo -n " - $lfs_file: "
|
||||||
|
file_type=$(file -b $lfs_file)
|
||||||
|
echo -n $file_type" "
|
||||||
|
if [ -z "$(echo -n $file_type | grep XZ)" ]; then
|
||||||
|
{ $FAIL_CMD_INLINE; FAILED=1; echo " -- run 'git lfs install; git lfs pull'"; }
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -n "Checking for perl: "
|
||||||
|
which perl || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for python3: "
|
||||||
|
which python3 || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for curl: "
|
||||||
|
which curl || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for zip: "
|
||||||
|
which zip || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for unzip: "
|
||||||
|
which unzip || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for xz: "
|
||||||
|
which xz || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for awk: "
|
||||||
|
which awk || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for rsync: "
|
||||||
|
which rsync || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
if [ $platform = "w" ]; then
|
||||||
|
echo -n "Checking for 7z: "
|
||||||
|
which 7z || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for rcedit: "
|
||||||
|
which rcedit || { $FAIL_CMD; FAILED=1; echo " -- Install with fetch_rcedit"; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $platform = "w" ]; then
|
||||||
|
echo
|
||||||
|
echo "${hdr_start}Checking Windows packaging requirements:${hdr_stop}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo -n "Checking for upx: "
|
||||||
|
which upx || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for uuidgen: "
|
||||||
|
which uuidgen || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for code-signing script: "
|
||||||
|
if [ -x "$APP_ROOT_DIR/win/codesign" ]; then
|
||||||
|
echo "$APP_ROOT_DIR/win/codesign"
|
||||||
|
else
|
||||||
|
$FAIL_CMD
|
||||||
|
FAILED=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n "Checking for Unicode NSIS: "
|
||||||
|
if [ -x "`cygpath -u \"${NSIS_DIR}makensis.exe\"`" ]; then
|
||||||
|
echo "`cygpath -u \"${NSIS_DIR}makensis.exe\"`"
|
||||||
|
else
|
||||||
|
$FAIL_CMD
|
||||||
|
FAILED=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
plugin_path=$(cd "$NSIS_DIR\\Plugins\\x86-unicode" && pwd)
|
||||||
|
plugins="AppAssocReg ApplicationID InvokeShellVerb nsProcess ShellLink UAC"
|
||||||
|
echo "Checking for NSIS plugins in $plugin_path"
|
||||||
|
for i in $plugins; do
|
||||||
|
echo -n " $i.dll: "
|
||||||
|
if [ -f "$plugin_path/$i.dll" ]; then
|
||||||
|
echo OK
|
||||||
|
else
|
||||||
|
$FAIL_CMD
|
||||||
|
FAILED=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $platform = "m" ]; then
|
||||||
|
echo
|
||||||
|
echo "${hdr_start}Checking Mac packaging requirements:${hdr_stop}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo -n "Checking for codesign: "
|
||||||
|
which /usr/bin/codesign || { $FAIL_CMD; FAILED=1; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "${hdr_start}Checking distribution requirements:${hdr_stop}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo -n "Checking for Mozilla ARchive (MAR) tool: "
|
||||||
|
which mar || { $FAIL_CMD; FAILED=1; echo " -- Install with fetch_mar_tools"; }
|
||||||
|
|
||||||
|
echo -n "Checking for mbsdiff: "
|
||||||
|
which mbsdiff || { $FAIL_CMD; FAILED=1; echo " -- Install with fetch_mar_tools"; }
|
||||||
|
|
||||||
|
echo -n "Checking for rsync: "
|
||||||
|
which rsync || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for sha512sum/shasum: "
|
||||||
|
which sha512sum 2>/dev/null || which shasum 2>/dev/null || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for AWS CLI: "
|
||||||
|
which aws || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for AWS S3 access: "
|
||||||
|
aws s3 ls $S3_BUCKET/$S3_DIST_PATH | sed 's/^[[:blank:]]*//' || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
echo -n "Checking for deploy host directory access: "
|
||||||
|
ssh $DEPLOY_HOST ls -d $DEPLOY_PATH || { $FAIL_CMD; FAILED=1; }
|
||||||
|
|
||||||
|
|
||||||
|
exit $FAILED
|
||||||
40
app/scripts/codesign_local
Executable file
40
app/scripts/codesign_local
Executable file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Perform ad-hoc code signing of Zotero.app for local usage
|
||||||
|
#
|
||||||
|
# Currently we sign only the Word dylib, since that's necessary for Zotero developers to work on
|
||||||
|
# Word integration on Apple Silicon. If we discover other problems, we can uncomment some of the
|
||||||
|
# other lines. If you're making a custom build, you can modify this file to sign the entire build
|
||||||
|
# instead of just the bare minimum needed for development.
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
echo "Usage: $0 path/to/staging/Zotero.app"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
APPDIR=$1
|
||||||
|
DEVELOPER_ID="-"
|
||||||
|
|
||||||
|
entitlements_file="$ROOT_DIR/mac/entitlements.xml"
|
||||||
|
#/usr/bin/codesign --force --options runtime --entitlements "$entitlements_file" --sign "$DEVELOPER_ID" \
|
||||||
|
# "$APPDIR/Contents/MacOS/XUL" \
|
||||||
|
# "$APPDIR/Contents/MacOS/updater.app/Contents/MacOS/org.mozilla.updater"
|
||||||
|
#find "$APPDIR/Contents" -name '*.dylib' -exec /usr/bin/codesign --force --options runtime --entitlements "$entitlements_file" --sign "$DEVELOPER_ID" {} \;
|
||||||
|
#find "$APPDIR/Contents" -name '*.app' -exec /usr/bin/codesign --force --options runtime --entitlements "$entitlements_file" --sign "$DEVELOPER_ID" {} \;
|
||||||
|
#/usr/bin/codesign --force --options runtime --entitlements "$entitlements_file" --sign "$DEVELOPER_ID" "$APPDIR/Contents/MacOS/zotero"
|
||||||
|
|
||||||
|
# Skip signing of Safari extension, since it's not present for local builds
|
||||||
|
|
||||||
|
# Sign final app package
|
||||||
|
#echo
|
||||||
|
#/usr/bin/codesign --force --options runtime --entitlements "$entitlements_file" --sign "$DEVELOPER_ID" "$APPDIR"
|
||||||
|
|
||||||
|
# Verify app
|
||||||
|
#/usr/bin/codesign --verify -vvvv "$APPDIR"
|
||||||
|
|
||||||
|
find "$APPDIR/Contents" -name 'libZoteroWordIntegration.dylib' -exec /usr/bin/codesign --force --options runtime --entitlements "$entitlements_file" --sign "$DEVELOPER_ID" {} \;
|
||||||
76
app/scripts/createprecomplete.py
Executable file
76
app/scripts/createprecomplete.py
Executable file
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Any copyright is dedicated to the Public Domain.
|
||||||
|
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
|
||||||
|
# Creates the precomplete file containing the remove and rmdir application
|
||||||
|
# update instructions which is used to remove files and directories that are no
|
||||||
|
# longer present in a complete update. The current working directory is used for
|
||||||
|
# the location to enumerate and to create the precomplete file.
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def get_build_entries(root_path):
|
||||||
|
"""Iterates through the root_path, creating a list for each file and
|
||||||
|
directory. Excludes any file paths ending with channel-prefs.js.
|
||||||
|
"""
|
||||||
|
rel_file_path_set = set()
|
||||||
|
rel_dir_path_set = set()
|
||||||
|
for root, dirs, files in os.walk(root_path):
|
||||||
|
for file_name in files:
|
||||||
|
parent_dir_rel_path = root[len(root_path) + 1 :]
|
||||||
|
rel_path_file = os.path.join(parent_dir_rel_path, file_name)
|
||||||
|
rel_path_file = rel_path_file.replace("\\", "/")
|
||||||
|
if not (
|
||||||
|
rel_path_file.endswith("channel-prefs.js")
|
||||||
|
or rel_path_file.endswith("update-settings.ini")
|
||||||
|
or "/ChannelPrefs.framework/" in rel_path_file
|
||||||
|
or rel_path_file.startswith("ChannelPrefs.framework/")
|
||||||
|
or "/UpdateSettings.framework/" in rel_path_file
|
||||||
|
or rel_path_file.startswith("UpdateSettings.framework/")
|
||||||
|
or "distribution/" in rel_path_file
|
||||||
|
):
|
||||||
|
rel_file_path_set.add(rel_path_file)
|
||||||
|
|
||||||
|
for dir_name in dirs:
|
||||||
|
parent_dir_rel_path = root[len(root_path) + 1 :]
|
||||||
|
rel_path_dir = os.path.join(parent_dir_rel_path, dir_name)
|
||||||
|
rel_path_dir = rel_path_dir.replace("\\", "/") + "/"
|
||||||
|
if rel_path_dir.find("distribution/") == -1:
|
||||||
|
rel_dir_path_set.add(rel_path_dir)
|
||||||
|
|
||||||
|
rel_file_path_list = list(rel_file_path_set)
|
||||||
|
rel_file_path_list.sort(reverse=True)
|
||||||
|
rel_dir_path_list = list(rel_dir_path_set)
|
||||||
|
rel_dir_path_list.sort(reverse=True)
|
||||||
|
|
||||||
|
return rel_file_path_list, rel_dir_path_list
|
||||||
|
|
||||||
|
|
||||||
|
def generate_precomplete(root_path):
|
||||||
|
"""Creates the precomplete file containing the remove and rmdir
|
||||||
|
application update instructions. The given directory is used
|
||||||
|
for the location to enumerate and to create the precomplete file.
|
||||||
|
"""
|
||||||
|
rel_path_precomplete = "precomplete"
|
||||||
|
# If inside a Mac bundle use the root of the bundle for the path.
|
||||||
|
if os.path.basename(root_path) == "Resources":
|
||||||
|
root_path = os.path.abspath(os.path.join(root_path, "../../"))
|
||||||
|
rel_path_precomplete = "Contents/Resources/precomplete"
|
||||||
|
|
||||||
|
precomplete_file_path = os.path.join(root_path, rel_path_precomplete)
|
||||||
|
# Open the file so it exists before building the list of files and open it
|
||||||
|
# in binary mode to prevent OS specific line endings.
|
||||||
|
precomplete_file = io.open(precomplete_file_path, mode="wt", newline="\n")
|
||||||
|
rel_file_path_list, rel_dir_path_list = get_build_entries(root_path)
|
||||||
|
for rel_file_path in rel_file_path_list:
|
||||||
|
precomplete_file.write('remove "' + rel_file_path + '"\n')
|
||||||
|
|
||||||
|
for rel_dir_path in rel_dir_path_list:
|
||||||
|
precomplete_file.write('rmdir "' + rel_dir_path + '"\n')
|
||||||
|
|
||||||
|
precomplete_file.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_precomplete(os.getcwd())
|
||||||
41
app/scripts/dev_build_and_deploy
Executable file
41
app/scripts/dev_build_and_deploy
Executable file
|
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
CHANNEL="dev"
|
||||||
|
BRANCH="main"
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
export SAFARI_APPEX="$ROOT_DIR/../safari-web-extension-builds/ZoteroSafariExtension.appex"
|
||||||
|
export SAFARI_EXT_RESOURCES="$ROOT_DIR/../safari-web-extension-builds/dev/safari"
|
||||||
|
if [ ! -d "$SAFARI_APPEX" ]; then
|
||||||
|
echo "Safari extension stub not found at $SAFARI_APPEX -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$SAFARI_EXT_RESOURCES/manifest.json" ]; then
|
||||||
|
echo "Safari web extension not found in $SAFARI_EXT_RESOURCES -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
./check_requirements
|
||||||
|
|
||||||
|
hash=`./get_repo_branch_hash $BRANCH`
|
||||||
|
./check_app_matches_commit $hash
|
||||||
|
source_dir=`./get_commit_files $hash`
|
||||||
|
build_dir=`mktemp -d`
|
||||||
|
|
||||||
|
function cleanup {
|
||||||
|
rm -rf "$source_dir"
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
./prepare_build -s "$source_dir" -o "$build_dir" -c $CHANNEL -m $hash
|
||||||
|
VERSION="`cat \"$build_dir/version\"`"
|
||||||
|
./build_for_deploy -d "$build_dir" -p $BUILD_PLATFORMS -c $CHANNEL -i 1
|
||||||
|
ssh $DEPLOY_HOST "$DEPLOY_PATH/deploy" $CHANNEL "$VERSION" $BUILD_PLATFORMS
|
||||||
175
app/scripts/dir_build
Executable file
175
app/scripts/dir_build
Executable file
|
|
@ -0,0 +1,175 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
. "$SCRIPT_DIR/utils.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage: $0 [options]
|
||||||
|
|
||||||
|
If -p is omitted, platform (and, for Windows/Linux, architecture) default to the host system.
|
||||||
|
Architecture is ignored for Mac builds, which are always shipped as universal binaries.
|
||||||
|
|
||||||
|
Options
|
||||||
|
-p PLATFORM Platform to build (m=Mac, w=Windows, l=Linux)
|
||||||
|
-a ARCH Target architecture (arm64, x64, win32) — **Windows/Linux only**
|
||||||
|
-t add devtools
|
||||||
|
-f force a full rebuild instead of updating the staged build in place
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
platform=""
|
||||||
|
arch=""
|
||||||
|
devtools=0
|
||||||
|
force_full=0
|
||||||
|
while getopts "tp:a:f" opt; do
|
||||||
|
case $opt in
|
||||||
|
t)
|
||||||
|
devtools=1
|
||||||
|
;;
|
||||||
|
p)
|
||||||
|
for (( i=0; i<${#OPTARG}; i++ )); do
|
||||||
|
case ${OPTARG:i:1} in
|
||||||
|
m) platform="m";;
|
||||||
|
w) platform="w";;
|
||||||
|
l) platform="l";;
|
||||||
|
*)
|
||||||
|
echo "$0: Invalid platform option ${OPTARG:i:1}" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
arch="$OPTARG"
|
||||||
|
;;
|
||||||
|
f)
|
||||||
|
force_full=1
|
||||||
|
;;
|
||||||
|
\?)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Derive platform from host if not provided
|
||||||
|
if [[ -z $platform ]]; then
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Darwin) platform="m" ;;
|
||||||
|
Linux) platform="l" ;;
|
||||||
|
CYGWIN*|MINGW*) platform="w" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle architecture rules
|
||||||
|
if [[ $platform = "m" ]]; then
|
||||||
|
# No arch for Mac — ignore anything provided
|
||||||
|
if [[ -n $arch ]]; then
|
||||||
|
echo "Ignoring -a $arch for Mac build (universal binary)" >&2
|
||||||
|
fi
|
||||||
|
arch=""
|
||||||
|
else
|
||||||
|
# Windows / Linux: derive arch if not supplied
|
||||||
|
if [[ -z $arch ]]; then
|
||||||
|
# An x64 build of Git for Windows runs emulated on Windows on ARM, where it
|
||||||
|
# reports x86_64 from `uname -m`, while `uname -s` reports the native
|
||||||
|
# architecture
|
||||||
|
if [[ $platform = "w" && "$(uname -s)" == *ARM64* ]]; then
|
||||||
|
arch="arm64"
|
||||||
|
else
|
||||||
|
case "$(uname -m)" in
|
||||||
|
arm64|aarch64) arch="arm64" ;;
|
||||||
|
x86_64) arch="x64" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
CHANNEL="source"
|
||||||
|
|
||||||
|
# Remove stale symlinks left behind in build/ when source files are deleted,
|
||||||
|
# which would otherwise break the build
|
||||||
|
if [ -d "$ROOT_DIR/build" ]; then
|
||||||
|
# With -L, -type l matches only broken symlinks
|
||||||
|
stale_links=$(find -L "$ROOT_DIR/build" -type l -print)
|
||||||
|
if [ -n "$stale_links" ]; then
|
||||||
|
echo "Removing stale symlinks from build/:" >&2
|
||||||
|
echo "$stale_links" >&2
|
||||||
|
while IFS= read -r link; do
|
||||||
|
rm "$link"
|
||||||
|
done <<< "$stale_links"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to update the staged build in place instead of doing a full rebuild
|
||||||
|
if [[ $force_full -eq 0 ]]; then
|
||||||
|
incr_cmd=("$SCRIPT_DIR/incremental_update" -p "$platform")
|
||||||
|
[[ -n $arch ]] && incr_cmd+=( -a "$arch" )
|
||||||
|
[[ $devtools -eq 1 ]] && incr_cmd+=( -t )
|
||||||
|
set +e
|
||||||
|
"${incr_cmd[@]}"
|
||||||
|
incr_status=$?
|
||||||
|
set -e
|
||||||
|
if [ $incr_status -ne 2 ]; then
|
||||||
|
exit $incr_status
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
hash=$(git -C "$ROOT_DIR" rev-parse --short HEAD)
|
||||||
|
|
||||||
|
build_dir=$(mktemp -d)
|
||||||
|
manifest_tmp=""
|
||||||
|
cleanup() {
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
if [ -n "$manifest_tmp" ]; then
|
||||||
|
rm -f "$manifest_tmp"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Snapshot the state of build/ and app/ before the build for later incremental
|
||||||
|
# updates
|
||||||
|
app_hash=""
|
||||||
|
if [ -d "$ROOT_DIR/build" ]; then
|
||||||
|
manifest_tmp=$(mktemp)
|
||||||
|
generate_build_manifest "$ROOT_DIR/build" > "$manifest_tmp"
|
||||||
|
app_hash=$(generate_app_hash "$APP_ROOT_DIR")
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$SCRIPT_DIR/prepare_build" -s "$ROOT_DIR/build" -o "$build_dir" -c "$CHANNEL" -m "$hash"
|
||||||
|
|
||||||
|
build_cmd=("$APP_ROOT_DIR/build.sh" -d "$build_dir" -p "$platform" -c "$CHANNEL" -s -q)
|
||||||
|
[[ -n $arch ]] && build_cmd+=( -a "$arch" )
|
||||||
|
[[ $devtools -eq 1 ]] && build_cmd+=( -t )
|
||||||
|
|
||||||
|
"${build_cmd[@]}"
|
||||||
|
|
||||||
|
# Save manifest for future incremental updates
|
||||||
|
if [ -n "$manifest_tmp" ]; then
|
||||||
|
if [[ -z "${ZOTERO_TEST:-}" ]] || [[ "${ZOTERO_TEST:-}" == "0" ]]; then
|
||||||
|
include_tests=0
|
||||||
|
else
|
||||||
|
include_tests=1
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo "#format=2"
|
||||||
|
echo "#include_tests=$include_tests"
|
||||||
|
echo "#devtools=$devtools"
|
||||||
|
echo "#app_hash=$app_hash"
|
||||||
|
cat "$manifest_tmp"
|
||||||
|
} > "$STAGE_DIR/.build-manifest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ad-hoc-sign the Word dylib so it works on Apple Silicon. This only needs to
|
||||||
|
# happen when the staged build is fully rebuilt -- incremental updates don't
|
||||||
|
# touch the dylib.
|
||||||
|
if [[ $platform = "m" ]] && [[ "$(uname -s)" = "Darwin" ]]; then
|
||||||
|
"$SCRIPT_DIR/codesign_local" "$STAGE_DIR/Zotero.app"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo Done
|
||||||
22
app/scripts/fetch_mar_tools
Executable file
22
app/scripts/fetch_mar_tools
Executable file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
cd "$APP_ROOT_DIR"
|
||||||
|
|
||||||
|
mkdir -p "xulrunner/bin"
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
# Mozilla has Linux executables where the Mac files should be, so supply our own Mac builds
|
||||||
|
curl -o "xulrunner/bin/mar" https://zotero-download.s3.us-east-1.amazonaws.com/tools/mac/102.11.0esr/mar
|
||||||
|
curl -o "xulrunner/bin/mbsdiff" https://zotero-download.s3.us-east-1.amazonaws.com/tools/mac/102.11.0esr/mbsdiff
|
||||||
|
elif [ "`uname -o 2> /dev/null`" = "Cygwin" ]; then
|
||||||
|
# Mozilla doesn't seem to provide Windows versions via its file server anymore, so supply our own
|
||||||
|
curl -o "xulrunner/bin/mar.exe" https://zotero-download.s3.us-east-1.amazonaws.com/tools/win/102.11.0esr/mar.exe
|
||||||
|
curl -o "xulrunner/bin/mbsdiff.exe" https://zotero-download.s3.us-east-1.amazonaws.com/tools/win/102.11.0esr/mbsdiff.exe
|
||||||
|
else
|
||||||
|
curl -o "xulrunner/bin/mar" https://ftp.mozilla.org/pub/firefox/nightly/2022/05/2022-05-30-09-39-43-mozilla-central/mar-tools/linux64/mar
|
||||||
|
curl -o "xulrunner/bin/mbsdiff" https://ftp.mozilla.org/pub/firefox/nightly/2022/05/2022-05-30-09-39-43-mozilla-central/mar-tools/linux64/mbsdiff
|
||||||
|
fi
|
||||||
|
chmod 755 xulrunner/bin/mar xulrunner/bin/mbsdiff
|
||||||
11
app/scripts/fetch_rcedit
Executable file
11
app/scripts/fetch_rcedit
Executable file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
mkdir -p "xulrunner/bin"
|
||||||
|
curl -L -o "xulrunner/bin/rcedit.exe" https://github.com/electron/rcedit/releases/download/v1.1.1/rcedit-x86.exe
|
||||||
|
chmod 755 xulrunner/bin/rcedit
|
||||||
855
app/scripts/fetch_xulrunner
Executable file
855
app/scripts/fetch_xulrunner
Executable file
|
|
@ -0,0 +1,855 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Copyright (c) 2011 Zotero
|
||||||
|
# Center for History and New Media
|
||||||
|
# George Mason University, Fairfax, Virginia, USA
|
||||||
|
# http://zotero.org
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
. "$SCRIPT_DIR/utils.sh"
|
||||||
|
cd "$APP_ROOT_DIR"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat >&2 <<'DONE'
|
||||||
|
Usage: fetch_xulrunner.sh -p <m|w|l> [-a ARCH]
|
||||||
|
|
||||||
|
Required
|
||||||
|
-p PLATFORM m (Mac), w (Windows), l (Linux)
|
||||||
|
|
||||||
|
Optional / Conditional
|
||||||
|
-a ARCH - Mac: disallowed (builds are universal)
|
||||||
|
- Windows: x64 | arm64 | win32
|
||||||
|
- Linux: x64 (or x86_64) | arm64
|
||||||
|
If omitted on Windows/Linux, all standard archs are fetched.
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_MAC=0
|
||||||
|
BUILD_WIN=0
|
||||||
|
BUILD_LINUX=0
|
||||||
|
arch=""
|
||||||
|
while getopts 'p:a:' opt; do
|
||||||
|
case $opt in
|
||||||
|
p)
|
||||||
|
for (( i=0; i<${#OPTARG}; i++ )); do
|
||||||
|
case ${OPTARG:i:1} in
|
||||||
|
m) BUILD_MAC=1;;
|
||||||
|
w) BUILD_WIN=1;;
|
||||||
|
l) BUILD_LINUX=1;;
|
||||||
|
*) echo "Invalid platform: ${OPTARG:i:1}"; echo; usage;;
|
||||||
|
esac
|
||||||
|
done;;
|
||||||
|
a) arch="$OPTARG";;
|
||||||
|
*) usage;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Require at least one platform
|
||||||
|
if [[ $BUILD_MAC == 0 ]] && [[ $BUILD_WIN == 0 ]] && [[ $BUILD_LINUX == 0 ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sanity‑check arch flag vs platform selections
|
||||||
|
if [[ $BUILD_MAC == 1 ]]; then
|
||||||
|
[[ -n $arch ]] && { echo "-a is not allowed for Mac" >&2; echo; usage; }
|
||||||
|
fi
|
||||||
|
if [[ $BUILD_WIN == 1 || $BUILD_LINUX == 1 ]]; then
|
||||||
|
# arch optional; if provided validate & map aliases now
|
||||||
|
if [[ -n $arch ]]; then
|
||||||
|
if [[ $BUILD_WIN == 1 && $BUILD_LINUX == 1 ]]; then
|
||||||
|
echo "-a cannot be used when building both Windows and Linux simultaneously" >&2; echo; usage
|
||||||
|
fi
|
||||||
|
if [[ $BUILD_WIN == 1 ]]; then
|
||||||
|
case $arch in
|
||||||
|
x64) arch="win-x64" ;;
|
||||||
|
arm64) arch="win-arm64" ;;
|
||||||
|
win32|win-x64|win-arm64) ;;
|
||||||
|
*) echo "Invalid Windows arch: $arch" >&2; echo; usage;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
if [[ $BUILD_LINUX == 1 ]]; then
|
||||||
|
[[ $arch == x64 ]] && arch="x86_64"
|
||||||
|
case $arch in x86_64|arm64) ;; *) echo "Invalid Linux arch: $arch" >&2; echo; usage;; esac
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
function get_utf16_chars {
|
||||||
|
str=$(echo -n "$1" | xxd -p | fold -w 2 | sed -r 's/(.+)/\\\\x{\1}\\\\x{00}/')
|
||||||
|
# Add NUL padding
|
||||||
|
if [ -n "${2:-}" ]; then
|
||||||
|
# Multiply characters x 2 for UTF-16
|
||||||
|
for i in `seq 1 $(($2 * 2))`; do
|
||||||
|
str+=$(echo '\\x{00}')
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
echo $str | xargs | sed 's/ //g'
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Make various modifications to the stock Firefox app
|
||||||
|
#
|
||||||
|
function modify_omni {
|
||||||
|
platform=$1
|
||||||
|
|
||||||
|
mkdir omni
|
||||||
|
mv omni.ja omni
|
||||||
|
cd omni
|
||||||
|
# omni.ja is an "optimized" ZIP file, so use a script from Mozilla to avoid a warning from unzip
|
||||||
|
# here and to make it work after rezipping below
|
||||||
|
python3 "$APP_ROOT_DIR/scripts/optimizejars.py" --deoptimize ./ ./ ./
|
||||||
|
rm -f omni.ja.log
|
||||||
|
unzip omni.ja
|
||||||
|
rm omni.ja
|
||||||
|
|
||||||
|
rm -r chrome/pdfjs
|
||||||
|
|
||||||
|
rm -r modules/narrate
|
||||||
|
#rm -r modules/translation
|
||||||
|
|
||||||
|
rm actors/AboutTranslations{Parent,Child}.sys.mjs
|
||||||
|
rm actors/CookieBanner{Parent,Child}.sys.mjs
|
||||||
|
rm actors/PictureInPictureChild.sys.mjs
|
||||||
|
rm actors/ThumbnailsChild.sys.mjs
|
||||||
|
rm actors/Translations{Engine,}{Parent,Child}.sys.mjs
|
||||||
|
rm actors/AudioPlayback{Parent,Child}.sys.mjs
|
||||||
|
|
||||||
|
replace_line 'BROWSER_CHROME_URL:.+' 'BROWSER_CHROME_URL: "chrome:\/\/zotero\/content\/zoteroPane.xhtml",' modules/AppConstants.sys.mjs
|
||||||
|
# Used by OSKeyStore as the master-key label, visible in macOS Keychain Access.
|
||||||
|
# Verify that OSKeyStore still derives the label from MOZ_APP_BASENAME, so a
|
||||||
|
# future Mozilla change to a hardcoded string doesn't silently rebrand the
|
||||||
|
# keychain entry back to "Firefox Encrypted Storage".
|
||||||
|
replace_line 'MOZ_APP_BASENAME: "Firefox"' 'MOZ_APP_BASENAME: "Zotero"' modules/AppConstants.sys.mjs
|
||||||
|
check_line 'STORE_LABEL: AppConstants\.MOZ_APP_BASENAME \+ " Encrypted Storage"' modules/OSKeyStore.sys.mjs
|
||||||
|
|
||||||
|
# https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/internals/preferences.html
|
||||||
|
#
|
||||||
|
# It's not clear that most of these do anything anymore when not compiled in, but just in case
|
||||||
|
replace_line 'MOZ_REQUIRE_SIGNING:' 'MOZ_REQUIRE_SIGNING: false \&\&' modules/AppConstants.sys.mjs
|
||||||
|
replace_line 'MOZ_DATA_REPORTING:' 'MOZ_DATA_REPORTING: false \&\&' modules/AppConstants.sys.mjs
|
||||||
|
replace_line 'MOZ_TELEMETRY_REPORTING:' 'MOZ_TELEMETRY_REPORTING: false \&\&' modules/AppConstants.sys.mjs
|
||||||
|
replace_line 'MOZ_CRASHREPORTER:' 'MOZ_CRASHREPORTER: false \&\&' modules/AppConstants.sys.mjs
|
||||||
|
replace_line 'MOZ_UPDATE_CHANNEL:.+' 'MOZ_UPDATE_CHANNEL: "none",' modules/AppConstants.sys.mjs
|
||||||
|
replace_line '"https:\/\/[^\/]+mozilla.com.+"' '""' modules/AppConstants.sys.mjs
|
||||||
|
|
||||||
|
# Don't use Mozilla Maintenance Service on Windows
|
||||||
|
replace_line 'MOZ_MAINTENANCE_SERVICE:' 'MOZ_MAINTENANCE_SERVICE: false \&\&' modules/AppConstants.sys.mjs
|
||||||
|
# Continue using app.update.auto in prefs.js on Windows
|
||||||
|
replace_line 'PER_INSTALLATION_PREFS_PLATFORMS = \["win"\]' 'PER_INSTALLATION_PREFS_PLATFORMS = []' modules/UpdateUtils.sys.mjs
|
||||||
|
|
||||||
|
# Prompt if major update is available instead of installing automatically on restart
|
||||||
|
replace_line 'if \(!updateAuto\) \{' 'if (update.type == "major") {
|
||||||
|
LOG("UpdateService:_selectAndInstallUpdate - prompting because it is a major update");
|
||||||
|
AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_SHOWPROMPT_PREF);
|
||||||
|
Services.obs.notifyObservers(update, "update-available", "show-prompt");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!updateAuto) {' modules/UpdateService.sys.mjs
|
||||||
|
|
||||||
|
# Avoid console warning about resource://gre/modules/FxAccountsCommon.js
|
||||||
|
replace_line 'const logins = this._data.logins;' 'const logins = this._data.logins; if (this._data.logins.length != -1) return;' modules/LoginStore.sys.mjs
|
||||||
|
|
||||||
|
# Prevent error during network requests
|
||||||
|
replace_line 'async lazyInit\(\) \{' 'async lazyInit() { if (this.features) return false;' modules/UrlClassifierExceptionListService.sys.mjs
|
||||||
|
|
||||||
|
# Silence CrashManager "Could not get children of [...]/Crash Reports/events" spam
|
||||||
|
replace_line '\/\/ Missing events folders are allowed' '\/\/ Missing events folders are allowed (silence warning)
|
||||||
|
if (ex) return entries;' modules/CrashManager.sys.mjs
|
||||||
|
|
||||||
|
# Several services pull in services-settings (which we strip) and throw
|
||||||
|
# at profile-after-change. Remove their #init() methods to prevent errors.
|
||||||
|
replace_line 'async #init\(\) \{' 'async #init() {} async _unused_init() {' modules/EssentialDomainsRemoteSettings.sys.mjs
|
||||||
|
replace_line 'async #init\(\) \{' 'async #init() {} async _unused_init() {' modules/SimpleURIUnknownSchemesRemoteObserver.sys.mjs
|
||||||
|
# RemotePermissionService uses a top-level import, so even loading the
|
||||||
|
# module throws
|
||||||
|
replace_line 'import \{ RemoteSettings \} from "resource:\/\/services-settings\/remote-settings.sys.mjs";' \
|
||||||
|
'const RemoteSettings = () => ({ on() {}, get: async () => [] });' \
|
||||||
|
modules/RemotePermissionService.sys.mjs
|
||||||
|
|
||||||
|
replace_line 'pref\("network.captive-portal-service.enabled".+' 'pref("network.captive-portal-service.enabled", false);' greprefs.js
|
||||||
|
replace_line 'pref\("network.connectivity-service.enabled".+' 'pref("network.connectivity-service.enabled", false);' greprefs.js
|
||||||
|
replace_line 'pref\("toolkit.telemetry.server".+' 'pref("toolkit.telemetry.server", "");' greprefs.js
|
||||||
|
replace_line 'pref\("toolkit.telemetry.unified".+' 'pref("toolkit.telemetry.unified", false);' greprefs.js
|
||||||
|
replace_line 'pref\("media.gmp-manager.url".+' 'pref("media.gmp-manager.url", "");' greprefs.js
|
||||||
|
|
||||||
|
#
|
||||||
|
# # Disable transaction timeout
|
||||||
|
# perl -pi -e 's/let timeoutPromise/\/*let timeoutPromise/' modules/Sqlite.jsm
|
||||||
|
# perl -pi -e 's/return Promise.race\(\[transactionPromise, timeoutPromise\]\);/*\/return transactionPromise;/' modules/Sqlite.jsm
|
||||||
|
# rm -f jsloader/resource/gre/modules/Sqlite.jsm
|
||||||
|
#
|
||||||
|
# Disable unwanted components
|
||||||
|
remove_line '(RemoteSettings|services-|telemetry|Telemetry|URLDecorationAnnotationsService)' components/components.manifest
|
||||||
|
|
||||||
|
file="modules/ActorManagerParent.sys.mjs"
|
||||||
|
# Remove deleted actors
|
||||||
|
# Entries in the JSWINDOWACTORS/JSPROCESSACTORS literals:
|
||||||
|
remove_between '^ AudioPlayback: \{' '^ },' $file
|
||||||
|
remove_between '^ CookieBanner: \{' '^ },' $file
|
||||||
|
remove_between '^ Thumbnails: \{' '^ },' $file
|
||||||
|
remove_between '^ Translations: \{' '^ },' $file
|
||||||
|
remove_between '^ TranslationsEngine: \{' '^ },' $file
|
||||||
|
# Entries added conditionally after the literals:
|
||||||
|
remove_between '^ JSWINDOWACTORS\.AboutTranslations = \{' '^ \};' $file
|
||||||
|
remove_between '^ JSWINDOWACTORS\.PictureInPictureLauncher = \{' '^ \};' $file
|
||||||
|
remove_between '^ JSWINDOWACTORS\.PictureInPictureToggle = \{' '^ \};' $file
|
||||||
|
remove_between '^ JSWINDOWACTORS\.PictureInPicture = \{' '^ \};' $file
|
||||||
|
# Do not trigger LoginManager event that logs an error on autocomplete submission
|
||||||
|
remove_line 'DOMInputPasswordAdded: \{\},' $file
|
||||||
|
|
||||||
|
# On Mac/Linux, ignore relative paths in PATH in Subprocess.pathSearch(), used when a bare command is passed to Utilities.Internal.subprocess()
|
||||||
|
if [[ $platform != win* ]]; then
|
||||||
|
replace_line 'let path = PathUtils.join\(dir, bin\);' 'if (!dir.startsWith("\/")) continue; let path = PathUtils.join(dir, bin);' modules/subprocess/subprocess_unix.sys.mjs
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove unwanted files
|
||||||
|
pushd modules
|
||||||
|
rm Bookmarks*
|
||||||
|
rm FxAccounts*
|
||||||
|
echo '' > FingerprintingWebCompatService.sys.mjs
|
||||||
|
echo '' > PartitioningExceptionListService.sys.mjs
|
||||||
|
rm Places*
|
||||||
|
echo '' > PlacesExpiration.sys.mjs
|
||||||
|
echo '' > PlacesFrecencyRecalculator.sys.mjs
|
||||||
|
rm -rf services-settings/*
|
||||||
|
touch services-settings/remote-settings.sys.mjs
|
||||||
|
# Causes a startup error -- try an empty file or a shim instead?
|
||||||
|
#rm Telemetry*
|
||||||
|
rm URLDecorationAnnotationsService.sys.mjs
|
||||||
|
popd
|
||||||
|
pushd chrome/toolkit/content/mozapps/extensions
|
||||||
|
rm -rf default-theme
|
||||||
|
popd
|
||||||
|
|
||||||
|
# fcntl() is variadic, but js-ctypes declares it with a fixed third argument, which violates
|
||||||
|
# the ABI on every platform. It's harmless on Linux, where variadic and fixed integer
|
||||||
|
# arguments are passed in the same registers, but Apple's arm64 ABI passes variadic
|
||||||
|
# arguments on the stack, so the flag goes into a register the callee never reads and
|
||||||
|
# fcntl() takes it from an uninitialized stack slot instead. F_SETFD can therefore set
|
||||||
|
# FD_CLOFORK (bit 1, added in macOS 26) rather than FD_CLOEXEC, closing the pipe in the
|
||||||
|
# forked child and breaking Subprocess spawns, and F_SETFL can silently fail to set
|
||||||
|
# O_NONBLOCK. Since the value comes from leftover stack contents, this varies by build and
|
||||||
|
# call path instead of failing consistently -- don't assume it's fixed just because a given
|
||||||
|
# build works. This change should stay until this is fixed upstream.
|
||||||
|
if [[ $platform != win* ]]; then
|
||||||
|
replace_line 'ctypes\.int \/\* \.\.\. \*\/,' '"...",' modules/subprocess/subprocess_shared_unix.js
|
||||||
|
replace_line 'libc\.fcntl\(fds\[0\], LIBC\.F_SETFD, LIBC\.FD_CLOEXEC\);' 'libc.fcntl(fds[0], LIBC.F_SETFD, ctypes.int(LIBC.FD_CLOEXEC));' modules/subprocess/subprocess_unix.worker.js
|
||||||
|
replace_line 'libc\.fcntl\(fds\[1\], LIBC\.F_SETFD, LIBC\.FD_CLOEXEC\);' 'libc.fcntl(fds[1], LIBC.F_SETFD, ctypes.int(LIBC.FD_CLOEXEC));' modules/subprocess/subprocess_unix.worker.js
|
||||||
|
replace_line 'libc\.fcntl\(fds\[1\], LIBC\.F_SETFL, LIBC\.O_NONBLOCK\);' 'libc.fcntl(fds[1], LIBC.F_SETFL, ctypes.int(LIBC.O_NONBLOCK));' modules/subprocess/subprocess_unix.worker.js
|
||||||
|
replace_line 'libc\.fcntl\(fds\[0\], LIBC\.F_SETFL, LIBC\.O_NONBLOCK\);' 'libc.fcntl(fds[0], LIBC.F_SETFL, ctypes.int(LIBC.O_NONBLOCK));' modules/subprocess/subprocess_unix.sys.mjs
|
||||||
|
replace_line 'libc\.fcntl\(fds\[0\], LIBC\.F_SETFD, LIBC\.FD_CLOEXEC\);' 'libc.fcntl(fds[0], LIBC.F_SETFD, ctypes.int(LIBC.FD_CLOEXEC));' modules/subprocess/subprocess_unix.sys.mjs
|
||||||
|
replace_line 'libc\.fcntl\(fds\[1\], LIBC\.F_SETFD, LIBC\.FD_CLOEXEC\);' 'libc.fcntl(fds[1], LIBC.F_SETFD, ctypes.int(LIBC.FD_CLOEXEC));' modules/subprocess/subprocess_unix.sys.mjs
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This file loads remote-settings.sys.mjs, but if it's empty Zotero crashes
|
||||||
|
replace_line 'async #init\(\) \{' 'async #init() { if (true) { return; }' modules/URLQueryStrippingListService.sys.mjs
|
||||||
|
|
||||||
|
# Clear most WebExtension manifest properties
|
||||||
|
replace_line 'manifest = normalized.value;' 'manifest = normalized.value;
|
||||||
|
if (this.type == "extension") {
|
||||||
|
if (!manifest.applications?.zotero?.id) {
|
||||||
|
this.manifestError("applications.zotero.id not provided");
|
||||||
|
}
|
||||||
|
if (!manifest.applications?.zotero?.update_url) {
|
||||||
|
this.manifestError("applications.zotero.update_url not provided");
|
||||||
|
}
|
||||||
|
if (!manifest.applications?.zotero?.strict_max_version) {
|
||||||
|
this.manifestError("applications.zotero.strict_max_version not provided");
|
||||||
|
}
|
||||||
|
manifest.browser_specific_settings = undefined;
|
||||||
|
manifest.content_scripts = [];
|
||||||
|
manifest.permissions = [];
|
||||||
|
manifest.host_permissions = [];
|
||||||
|
manifest.web_accessible_resources = undefined;
|
||||||
|
manifest.experiment_apis = {};
|
||||||
|
}' modules/Extension.sys.mjs
|
||||||
|
|
||||||
|
# Use applications.zotero instead of applications.gecko
|
||||||
|
replace_line 'let bss = manifest.applications\?.gecko' 'let bss = manifest.applications?.zotero' modules/addons/XPIInstall.sys.mjs
|
||||||
|
replace_line 'manifest.applications\?.gecko' 'manifest.applications?.zotero' modules/Extension.sys.mjs
|
||||||
|
|
||||||
|
# When installing addon, use app version instead of toolkit version for targetApplication
|
||||||
|
replace_line "id: TOOLKIT_ID," "id: '$APP_ID'," modules/addons/XPIInstall.sys.mjs
|
||||||
|
|
||||||
|
# Set strictCompatibility to false in beta/dev/source builds to skip strict_max_version check
|
||||||
|
replace_line 'addon.strictCompatibility = true;' \
|
||||||
|
'let version = Services.appinfo.version;
|
||||||
|
addon.strictCompatibility = !version.includes("-beta") && !version.includes("-dev") && !version.includes("SOURCE");' modules/addons/XPIInstall.sys.mjs
|
||||||
|
|
||||||
|
# In beta/dev/source builds, ignore the persisted strictCompatibility flag for already-installed
|
||||||
|
# plugins, so plugins installed on a stable build (where the flag was set to true) aren't marked
|
||||||
|
# incompatible after upgrading. The manifest isn't re-parsed on app upgrade, so the flag set at
|
||||||
|
# install time sticks around.
|
||||||
|
replace_line '!this\.addon\.strictCompatibility' \
|
||||||
|
'(!this.addon.strictCompatibility || Services.appinfo.version.includes("-beta") || Services.appinfo.version.includes("-dev") || Services.appinfo.version.includes("SOURCE"))' modules/addons/XPIInstall.sys.mjs
|
||||||
|
replace_line '!this\.strictCompatibility &&' \
|
||||||
|
'(!this.strictCompatibility || Services.appinfo.version.includes("-beta") || Services.appinfo.version.includes("-dev") || Services.appinfo.version.includes("SOURCE")) &&' modules/addons/XPIDatabase.sys.mjs
|
||||||
|
|
||||||
|
# Accept zotero@chnm.gmu.edu for target application to allow Zotero 6 plugins to remain
|
||||||
|
# installed in Zotero 7
|
||||||
|
replace_line "if \(targetApp.id == Services.appinfo.ID\) \{" "if (targetApp.id == 'zotero\@chnm.gmu.edu') targetApp.id = '$APP_ID'; if (targetApp.id == Services.appinfo.ID) {" modules/addons/XPIDatabase.sys.mjs
|
||||||
|
|
||||||
|
# TEMP: Skip addons without ids until we figure out what's going on with the default theme.
|
||||||
|
# This fixes plugin updating and other things.
|
||||||
|
replace_line 'return addons;' 'return addons.filter(addon => addon.id);' modules/addons/XPIDatabase.sys.mjs
|
||||||
|
|
||||||
|
# For updates, look for applications.zotero instead of applications.gecko in manifest.json and
|
||||||
|
# use the app id and version for strict_min_version/strict_max_version comparisons
|
||||||
|
replace_line 'gecko: \{\},' 'zotero: {},' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
replace_line 'if \(!\("gecko" in applications\)\) \{' 'if (!("zotero" in applications)) {' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
replace_line '"gecko not in application entry' '"zotero not in application entry' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
replace_line 'let app = getProperty\(applications, "gecko", "object"\);' 'let app = getProperty(applications, "zotero", "object");' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
replace_line "id: TOOLKIT_ID," "id: '$APP_ID'," modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
replace_line 'lazy.AddonManagerPrivate.webExtensionsMinPlatformVersion' '"7.0"' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
replace_line 'result.targetApplications.push' 'false && result.targetApplications.push' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
# In beta/dev/source builds, don't set strictCompatibility on parsed update entries so that
|
||||||
|
# AddonUpdateChecker doesn't reject an available update whose maxVersion is lower than the
|
||||||
|
# current (non-stable) app version.
|
||||||
|
replace_line 'result\.strictCompatibility = appEntry\.maxVersion != "\*";' \
|
||||||
|
'let appVer = Services.appinfo.version; result.strictCompatibility = appEntry.maxVersion != "*" && !appVer.includes("-beta") && !appVer.includes("-dev") && !appVer.includes("SOURCE");' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
# Set uninstall flag to true if the update config has it set
|
||||||
|
replace_line 'targetApplications: \[appEntry\],' \
|
||||||
|
'targetApplications: \[appEntry\],
|
||||||
|
uninstall: getProperty(update, "uninstall", "boolean"),' modules/addons/AddonUpdateChecker.sys.mjs
|
||||||
|
|
||||||
|
# Prevent automatic installation of default theme
|
||||||
|
# (chrome/toolkit/content/mozapps/extensions/default-theme, removed above)
|
||||||
|
replace_line 'this.maybeInstallBuiltinAddon\(' 'if (false) this.maybeInstallBuiltinAddon(' modules/addons/XPIProvider.sys.mjs
|
||||||
|
|
||||||
|
# Don't log a warning when checking 'distribution/extensions' for addons
|
||||||
|
replace_line 'logger.warn\(`Checking' 'logger.debug(`Checking' modules/addons/XPIProvider.sys.mjs
|
||||||
|
|
||||||
|
# Allow addon installation by bypassing confirmation dialogs. If we want a confirmation dialog,
|
||||||
|
# we need to either add gXPInstallObserver from browser-addons.js [1][2] or provide our own with
|
||||||
|
# Ci.amIWebInstallPrompt [3].
|
||||||
|
#
|
||||||
|
# [1] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/browser/base/content/browser.js#1902-1923
|
||||||
|
# [2] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/browser/base/content/browser-addons.js#201
|
||||||
|
# [3] https://searchfox.org/mozilla-esr102/rev/5a6d529652045050c5cdedc0558238949b113741/toolkit/mozapps/extensions/AddonManager.sys.mjs#3114-3124
|
||||||
|
replace_line 'if \(info.addon.installPermissions\) \{' 'if (false) {' modules/AddonManager.sys.mjs
|
||||||
|
replace_line '\} else if \(info.addon.sitePermissions\) \{' '} else if (false) {' modules/AddonManager.sys.mjs
|
||||||
|
replace_line '\} else if \(requireConfirm\) \{' '} else if (false) {' modules/AddonManager.sys.mjs
|
||||||
|
|
||||||
|
# Make addon listener methods wait for promises, to allow calling asynchronous plugin `shutdown`
|
||||||
|
# and `uninstall` methods in our `onInstalling` handler
|
||||||
|
replace_line 'callAddonListeners\(aMethod' 'async callAddonListeners(aMethod' modules/AddonManager.sys.mjs
|
||||||
|
# Don't need this one to be async, but we can't easily avoid modifying its `listener[aMethod].apply()` call
|
||||||
|
replace_line 'callManagerListeners\(aMethod' 'async callManagerListeners(aMethod' modules/AddonManager.sys.mjs
|
||||||
|
replace_line 'AddonManagerInternal.callAddonListeners.apply\(AddonManagerInternal, aArgs\);' \
|
||||||
|
'return AddonManagerInternal.callAddonListeners.apply(AddonManagerInternal, aArgs);' modules/AddonManager.sys.mjs
|
||||||
|
replace_line 'listener\[aMethod\].apply\(listener, aArgs\);' \
|
||||||
|
'let maybePromise = listener[aMethod].apply(listener, aArgs);
|
||||||
|
if (maybePromise && maybePromise.then) await maybePromise;' modules/AddonManager.sys.mjs
|
||||||
|
replace_line 'AddonManagerPrivate.callAddonListeners' 'await AddonManagerPrivate.callAddonListeners' modules/addons/XPIInstall.sys.mjs
|
||||||
|
replace_line 'let uninstall = \(\) => \{' 'let uninstall = async () => {' modules/addons/XPIInstall.sys.mjs
|
||||||
|
replace_line 'cancelUninstallAddon\(aAddon\)' 'async cancelUninstallAddon(aAddon)' modules/addons/XPIInstall.sys.mjs
|
||||||
|
# Check for `uninstall` flag in update config and uninstall the addon if set
|
||||||
|
replace_line 'if \(update && !this.addon.location.locked\) \{' \
|
||||||
|
'if (update && !this.addon.location.locked) {
|
||||||
|
if (update.uninstall) {
|
||||||
|
let aId = this.addon.id;
|
||||||
|
logger.debug(`AddonUpdateChecker: uninstall addon \${aId} with uninstall flag`);
|
||||||
|
let addon = await AddonManager.getAddonByID(aId);
|
||||||
|
if (addon && (addon.permissions & AddonManager.PERM_CAN_UNINSTALL)) {
|
||||||
|
try {
|
||||||
|
addon.uninstall();
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(`AddonUpdateChecker: error uninstalling addon \${aId} with uninstall flag`, err);
|
||||||
|
}
|
||||||
|
sendUpdateAvailableMessages(this, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger.error(`AddonUpdateChecker: addon \${aId} with uninstall flag not found or cannot be uninstalled`);
|
||||||
|
sendUpdateAvailableMessages(this, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' modules/addons/XPIInstall.sys.mjs
|
||||||
|
|
||||||
|
# Prevent login manager from trying to load FxAccountsCommon.sys.mjs
|
||||||
|
replace_line 'return login.hostname == lazy.FXA_PWDMGR_HOST;' 'return false;' modules/storage-json.sys.mjs
|
||||||
|
|
||||||
|
# No idea why this is necessary, but without it initialization fails with "TypeError: "constructor" is read-only"
|
||||||
|
replace_line 'LoginStore.prototype.constructor = LoginStore;' '\/\/LoginStore.prototype.constructor = LoginStore;' modules/LoginStore.sys.mjs
|
||||||
|
#
|
||||||
|
# # Allow proxy password saving
|
||||||
|
# perl -pi -e 's/get _inPrivateBrowsing\(\) \{/get _inPrivateBrowsing() {if (true) { return false; }/' components/nsLoginManagerPrompter.js
|
||||||
|
#
|
||||||
|
# # Change text in update dialog
|
||||||
|
# perl -pi -e 's/A security and stability update for/A new version of/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
|
||||||
|
# perl -pi -e 's/updateType_major=New Version/updateType_major=New Major Version/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
|
||||||
|
# perl -pi -e 's/updateType_minor=Security Update/updateType_minor=New Version/' chrome/en-US/locale/en-US/mozapps/update/updates.properties
|
||||||
|
# perl -pi -e 's/update for &brandShortName; as soon as possible/update as soon as possible/' chrome/en-US/locale/en-US/mozapps/update/updates.dtd
|
||||||
|
#
|
||||||
|
# Set available locales
|
||||||
|
cp "$APP_ROOT_DIR/assets/multilocale.txt" res/multilocale.txt
|
||||||
|
|
||||||
|
# Use Zotero URL opening in Mozilla dialogs (e.g., app update dialog)
|
||||||
|
replace_line 'function openURL\(aURL\) \{' 'function openURL(aURL) {let {Zotero} = ChromeUtils.importESModule("chrome:\/\/zotero\/content\/zotero.mjs"); Zotero.launchURL(aURL); if (true) { return; }' chrome/toolkit/content/global/contentAreaUtils.js
|
||||||
|
|
||||||
|
#
|
||||||
|
# Modify Add-ons window
|
||||||
|
#
|
||||||
|
|
||||||
|
# Prevent display: block from overriding display: none on <hr>s
|
||||||
|
replace_line 'display: block !important;' 'display: block;' chrome/toolkit/content/global/elements/panel-list.css
|
||||||
|
|
||||||
|
file="chrome/toolkit/content/mozapps/extensions/aboutaddons.css"
|
||||||
|
echo >> $file
|
||||||
|
# Hide the search bar and the whole sidebar, since we only ever show plugins and the main pane
|
||||||
|
# is already headed "Manage Your Plugins"
|
||||||
|
echo '.main-search, #sidebar { display: none; }' >> $file
|
||||||
|
# Center the content in the window now that it isn't offset by the sidebar
|
||||||
|
echo '#full { grid-template-columns: 1fr; }' >> $file
|
||||||
|
echo '#content { max-width: calc(var(--page-main-content-width) + var(--main-margin-start)); margin-inline: auto; }' >> $file
|
||||||
|
echo '.main-heading { margin-top: 2em; }' >> $file
|
||||||
|
# Hide Details/Permissions tabs in addon details so we only show details
|
||||||
|
echo 'addon-details > button-group { display: none !important; }' >> $file
|
||||||
|
# Hide "Run on sites with restrictions" row and helper message
|
||||||
|
echo '.addon-detail-row-quarantined-domains { display: none; }' >> $file
|
||||||
|
echo '.addon-detail-help-row:has([data-l10n-id="addon-detail-quarantined-domains-help"]) { display: none; }' >> $file
|
||||||
|
# Hide "Report" button from plugin menu
|
||||||
|
echo 'addon-card addon-options hr:first-of-type { display: none }' >> $file
|
||||||
|
echo '[data-l10n-id="report-addon-button"] { display: none }' >> $file
|
||||||
|
# Hide "Debug Addons" and "Manage Extension Shortcuts"
|
||||||
|
echo 'panel-item[action="debug-addons"], panel-item[action="reset-update-states"] + hr, panel-item[action="manage-shortcuts"] { display: none }' >> $file
|
||||||
|
# Show cursor feedback on plugin homepage links
|
||||||
|
echo '.addon-detail-row-homepage .text-link { cursor: pointer; color: LinkText; }' >> $file
|
||||||
|
echo '.addon-detail-row-homepage .text-link:hover { text-decoration: underline; }' >> $file
|
||||||
|
|
||||||
|
file="chrome/toolkit/content/mozapps/extensions/aboutaddons-utils.mjs"
|
||||||
|
# Hide unsigned-addon warning
|
||||||
|
replace_line 'export function isUnsignedWarningMessageDisabled\(\) \{' \
|
||||||
|
'export function isUnsignedWarningMessageDisabled() {if (true) return true;' $file
|
||||||
|
# Use our own localized string for blocked plugin notification
|
||||||
|
replace_line 'details-notification-hard-blocked-\$\{typeSuffix\}' 'plugins-blocked-plugin' $file
|
||||||
|
# Hide Recommendations tab in sidebar and recommendations in main pane
|
||||||
|
replace_line 'function isDiscoverEnabled\(\) \{' 'function isDiscoverEnabled() {return false;' $file
|
||||||
|
|
||||||
|
file="chrome/toolkit/content/mozapps/extensions/components/addon-details.mjs"
|
||||||
|
# Hide Private Browsing setting in addon details
|
||||||
|
replace_line 'pbRow\.' '\/\/pbRow.' $file
|
||||||
|
replace_line 'let isAllowed = await isAllowedInPrivateBrowsing' '\/\/let isAllowed = await isAllowedInPrivateBrowsing' $file
|
||||||
|
# Open plugin links in external browser
|
||||||
|
replace_line 'let homepageURL = homepageRow.querySelector\(\"a\"\);' 'let homepageURL = homepageRow.querySelector(\"\.text-link\");' $file
|
||||||
|
replace_line 'homepageURL.href = addon.homepageURL;' 'homepageURL.setAttribute("href", addon.homepageURL);' $file
|
||||||
|
replace_line '<a target="_blank" dir="ltr"><\/a>' \
|
||||||
|
'<label target="_blank" class="text-link" dir="ltr"><\/label>' $file
|
||||||
|
|
||||||
|
file="chrome/toolkit/content/mozapps/extensions/components/addon-card.mjs"
|
||||||
|
# Use our own strings for the removal prompt
|
||||||
|
replace_line 'let \{ BrowserAddonUI \} = windowRoot.window;' '' $file
|
||||||
|
replace_line 'await BrowserAddonUI.promptRemoveExtension' 'promptRemoveExtension' $file
|
||||||
|
|
||||||
|
# Customize empty-list message
|
||||||
|
replace_line 'createEmptyListMessage\(\) {' 'createEmptyListMessage() {
|
||||||
|
var p = document.createElement("p");
|
||||||
|
p.id = "empty-list-message";
|
||||||
|
return p;' chrome/toolkit/content/mozapps/extensions/components/addon-list.mjs
|
||||||
|
|
||||||
|
# Add zotero.ftl to the addons page for our own localized strings
|
||||||
|
replace_line 'href="toolkit\/about\/aboutAddons.ftl"' 'href="toolkit\/about\/aboutAddons.ftl" \/>\n <link rel="localization" href="zotero.ftl"' \
|
||||||
|
chrome/toolkit/content/mozapps/extensions/aboutaddons.html
|
||||||
|
|
||||||
|
# TODO: Use our own strings, but for now fix the bundled English ones
|
||||||
|
replace_line 'Manage Your Extensions' 'Manage Your Plugins' localization/en-US/toolkit/about/aboutAddons.ftl
|
||||||
|
replace_line 'Add-on' 'Plugin' localization/en-US/toolkit/about/aboutAddons.ftl
|
||||||
|
replace_line 'add-ons' 'plugins' localization/en-US/toolkit/about/aboutAddons.ftl
|
||||||
|
replace_line 'Select add-on to install' 'Select plugin to install' localization/en-US/toolkit/about/aboutAddons.ftl
|
||||||
|
|
||||||
|
replace_line 'pref\("extensions.htmlaboutaddons.recommendations.enabled".+' 'pref("extensions.htmlaboutaddons.recommendations.enabled", false);' greprefs.js
|
||||||
|
|
||||||
|
# Hide Report option
|
||||||
|
replace_line 'pref\("extensions.abuseReport.enabled".+' 'pref("extensions.abuseReport.enabled", false);' greprefs.js
|
||||||
|
|
||||||
|
# The first displayed Services.prompt dialog's size jumps around because sizeToContent() is called twice
|
||||||
|
# Fix by preventing the first sizeToContent() call if the icon hasn't been loaded yet
|
||||||
|
replace_line 'window.sizeToContent\(\);' 'if (ui.infoIcon.complete) window.sizeToContent();' chrome/toolkit/content/global/commonDialog.js
|
||||||
|
replace_line 'ui.infoIcon.addEventListener' 'if (!ui.infoIcon.complete) ui.infoIcon.addEventListener' chrome/toolkit/content/global/commonDialog.js
|
||||||
|
|
||||||
|
# Import style into built-in dialogs
|
||||||
|
replace_line 'id=\"commonDialogWindow\"' \
|
||||||
|
'id=\"commonDialogWindow\" class=\"zotero-dialog\" drawintitlebar-platforms=\"mac\"' \
|
||||||
|
chrome/toolkit/content/global/commonDialog.xhtml
|
||||||
|
# commonDialog.css link is split across multiple lines, so we have to do a weird substitution,
|
||||||
|
# so check the one-line global.css to make sure the format hasn't changed
|
||||||
|
check_line '<html:link rel="stylesheet" href="chrome:\/\/global\/skin\/global.css" \/>' chrome/toolkit/content/global/commonDialog.xhtml
|
||||||
|
replace_line 'chrome:\/\/global\/skin\/commonDialog.css"' \
|
||||||
|
'chrome:\/\/global\/skin\/commonDialog.css"\/>
|
||||||
|
<html:link rel="stylesheet" href="chrome:\/\/zotero-platform\/content\/zotero.css"' \
|
||||||
|
chrome/toolkit/content/global/commonDialog.xhtml
|
||||||
|
# commonDialog.xhtml can be opened via Services.prompt in the Profile Manager, so check for a profile first
|
||||||
|
replace_line 'function commonDialogOnLoad\(\) \{' \
|
||||||
|
'function commonDialogOnLoad() {
|
||||||
|
try {
|
||||||
|
Services.dirsvc.get(\"ProfD\", Ci.nsIFile);
|
||||||
|
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/include.js\", this);
|
||||||
|
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/titlebar.js\", this);
|
||||||
|
Services.scriptloader.loadSubScript(\"chrome:\/\/zotero\/content\/customElements.js\", this);
|
||||||
|
} catch (e) {}' \
|
||||||
|
chrome/toolkit/content/global/commonDialog.js
|
||||||
|
|
||||||
|
# Use native checkbox instead of Firefox-themed version in prompt dialogs
|
||||||
|
replace_line '<xul:checkbox' '<xul:checkbox native=\"true\"' chrome/toolkit/content/global/commonDialog.xhtml
|
||||||
|
|
||||||
|
# The <browser> CE appends its autoscroll <popup> to document.documentElement, which doesn't work in zoteroPane.xhtml
|
||||||
|
# (in Firefox browser.xhtml, document.documentElement is <html>, which can contain <popup>s; in zoteroPane.xhtml, it's
|
||||||
|
# <window>, which can't)
|
||||||
|
# Fix by appending it to a <popupset> instead
|
||||||
|
replace_line 'document.documentElement.appendChild\(this._autoScrollPopup\);' 'let popupset = document.querySelector("popupset");
|
||||||
|
if (!popupset) {
|
||||||
|
popupset = document.createXULElement("popupset");
|
||||||
|
document.documentElement.appendChild(popupset);
|
||||||
|
}
|
||||||
|
popupset.appendChild(this._autoScrollPopup);' chrome/toolkit/content/global/elements/browser-custom-element.mjs
|
||||||
|
|
||||||
|
# Add the dropmarker for toolbarbuttons with wantdropmarker, which Firefox no longer creates
|
||||||
|
replace_line 'this.appendChild\(this.constructor.fragment.cloneNode\(true\)\);' \
|
||||||
|
'this.appendChild(this.constructor.fragment.cloneNode(true));
|
||||||
|
|
||||||
|
if (this.hasAttribute("wantdropmarker")) {
|
||||||
|
let dropmarker = document.createXULElement("dropmarker");
|
||||||
|
dropmarker.setAttribute("type", "menu");
|
||||||
|
dropmarker.className = "toolbarbutton-menu-dropmarker";
|
||||||
|
this.appendChild(dropmarker);
|
||||||
|
}' chrome/toolkit/content/global/elements/toolbarbutton.js
|
||||||
|
# Let clicks on the dropmarker pass through to the toolbarbutton, which only opens its menu
|
||||||
|
# when it's the original event target, as xul.css did when Firefox created the dropmarker
|
||||||
|
echo '.toolbarbutton-menu-dropmarker { pointer-events: none; }' >> chrome/toolkit/content/global/xul.css
|
||||||
|
|
||||||
|
# Remove non-native text input styles
|
||||||
|
remove_between 'html\|input\:where\(' '^}' chrome/toolkit/skin/classic/global/global-shared.css
|
||||||
|
|
||||||
|
# Prevent window dragging on scrollbars
|
||||||
|
echo 'scrollbar { -moz-window-dragging: no-drag; }' >> chrome/toolkit/res/scrollbars.css
|
||||||
|
|
||||||
|
# Provide a mechanism for non-UA stylesheets to override the overflow property
|
||||||
|
# of a text control's anonymous text node child
|
||||||
|
echo '::placeholder, ::-moz-text-control-editing-root, ::-moz-text-control-preview {
|
||||||
|
overflow: var(--moz-text-control-overflow);
|
||||||
|
}' >> chrome/toolkit/res/forms.css
|
||||||
|
|
||||||
|
# Size an autocomplete popup to the input that opened it, or to an ancestor that designates
|
||||||
|
# itself as the width container. Firefox sizes the popup to its content. (For creator inputs.)
|
||||||
|
replace_line '\/\/ invalidate\(\) depends on the width attribute' \
|
||||||
|
'let widthElement = aElement.closest(".autocomplete-popup-width-container") || aElement;
|
||||||
|
this.style.setProperty("--panel-width", Math.max(widthElement.getBoundingClientRect().width, 100) + "px");
|
||||||
|
\/\/ invalidate() depends on the width attribute' \
|
||||||
|
chrome/toolkit/content/global/elements/autocomplete-popup.js
|
||||||
|
|
||||||
|
zip -qr9XD omni.ja *
|
||||||
|
mv omni.ja ..
|
||||||
|
cd ..
|
||||||
|
python3 "$APP_ROOT_DIR/scripts/optimizejars.py" --optimize ./ ./ ./
|
||||||
|
rm -rf omni
|
||||||
|
|
||||||
|
# Unzip browser/omni.ja and leave unzipped
|
||||||
|
cd browser
|
||||||
|
mkdir omni
|
||||||
|
mv omni.ja omni
|
||||||
|
cd omni
|
||||||
|
ls -la
|
||||||
|
set +e
|
||||||
|
unzip omni.ja
|
||||||
|
set -e
|
||||||
|
rm omni.ja
|
||||||
|
|
||||||
|
# Remove Firefox update URLs
|
||||||
|
remove_line 'pref\("app.update.url.(manual|details)' defaults/preferences/firefox-branding.js
|
||||||
|
|
||||||
|
# Remove Firefox overrides (e.g., to use Firefox-specific strings for connection errors)
|
||||||
|
remove_line '(override)' chrome/chrome.manifest
|
||||||
|
|
||||||
|
# Remove WebExtension APIs
|
||||||
|
remove_line ext-browser.json components/components.manifest
|
||||||
|
|
||||||
|
# Don't open a second window if app is already open when launching .exe (Windows) or running via
|
||||||
|
# command line (macOS)
|
||||||
|
replace_line 'function dch_handle\(cmdLine\) \{' 'function dch_handle(cmdLine) {
|
||||||
|
if (cmdLine.state == Ci.nsICommandLine.STATE_REMOTE_AUTO) { return; }
|
||||||
|
' modules/BrowserContentHandler.sys.mjs
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p xulrunner
|
||||||
|
cd xulrunner
|
||||||
|
|
||||||
|
if [ $BUILD_MAC == 1 ]; then
|
||||||
|
GECKO_VERSION="$GECKO_VERSION_MAC"
|
||||||
|
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
|
||||||
|
rm -rf Firefox.app
|
||||||
|
|
||||||
|
if [ -e "Firefox $GECKO_VERSION.app.zip" ]; then
|
||||||
|
echo "Using Firefox $GECKO_VERSION.app.zip"
|
||||||
|
unzip "Firefox $GECKO_VERSION.app.zip"
|
||||||
|
else
|
||||||
|
curl -fo Firefox.dmg "$DOWNLOAD_URL/mac/en-US/Firefox%20$GECKO_VERSION.dmg"
|
||||||
|
set +e
|
||||||
|
hdiutil detach -quiet /Volumes/Firefox 2>/dev/null
|
||||||
|
set -e
|
||||||
|
hdiutil attach -quiet Firefox.dmg
|
||||||
|
cp -a /Volumes/Firefox/Firefox.app .
|
||||||
|
# Store local copy of unmodified app
|
||||||
|
zip -r "Firefox $GECKO_VERSION.app.zip" Firefox.app
|
||||||
|
hdiutil detach -quiet /Volumes/Firefox
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download custom components (e.g., XUL), as an xz-compressed tarball of the MacOS folder with
|
||||||
|
# custom files in it
|
||||||
|
echo
|
||||||
|
rm -rf MacOS
|
||||||
|
if [ -n "$custom_components_hash_mac" ]; then
|
||||||
|
tarfile="Firefox $GECKO_VERSION MacOS.tar.xz"
|
||||||
|
if [[ "$(uname)" = "Darwin" ]]; then
|
||||||
|
shasum="shasum -a 256"
|
||||||
|
else
|
||||||
|
shasum=sha256sum
|
||||||
|
fi
|
||||||
|
|
||||||
|
download_components() {
|
||||||
|
echo "Downloading custom Firefox components"
|
||||||
|
echo
|
||||||
|
curl -fo "$tarfile" "${custom_components_url}mac/$custom_components_hash_mac.tar.xz"
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_components_hash() {
|
||||||
|
echo "$custom_components_hash_mac $tarfile" | $shasum -c -
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ! -e "$tarfile" ]; then
|
||||||
|
download_components
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify hash
|
||||||
|
echo
|
||||||
|
if ! verify_components_hash; then
|
||||||
|
echo "SHA hash mismatch. Redownloading custom Firefox components…"
|
||||||
|
rm -f "$tarfile"
|
||||||
|
download_components
|
||||||
|
echo
|
||||||
|
if ! verify_components_hash; then
|
||||||
|
echo "Hash still doesn't match. Aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
tar xvf "$tarfile"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd Firefox.app/Contents/Resources
|
||||||
|
modify_omni mac
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Replace "FirefoxCP" with "ZoteroCP" for subprocesses ("Isolated Web Content", "Socket Process", "Web Content", etc.)
|
||||||
|
info_plist=Firefox.app/Contents/MacOS/plugin-container.app/Contents/Resources/English.lproj/InfoPlist.strings
|
||||||
|
from=$(get_utf16_chars "FirefoxCP")
|
||||||
|
to=$(get_utf16_chars "ZoteroCP")
|
||||||
|
perl -pi -e "s/$from/$to/" $info_plist
|
||||||
|
# Check for UTF-16 "ZoteroCP"
|
||||||
|
if ! grep -a -q "Z.o.t.e.r.o.C.P." $info_plist; then
|
||||||
|
echo '"ZoteroCP" not found in InfoPlist.strings after replacement'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f Firefox.dmg
|
||||||
|
|
||||||
|
echo $("$SCRIPT_DIR/xulrunner_hash" -p m) > hash-mac
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $BUILD_WIN == 1 ]; then
|
||||||
|
GECKO_VERSION="$GECKO_VERSION_WIN"
|
||||||
|
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
|
||||||
|
|
||||||
|
if [[ -n $arch ]]; then
|
||||||
|
arch_list=("$(get_canonical_arch w $arch)")
|
||||||
|
else
|
||||||
|
arch_list=(win-x64 win-arm64 win32)
|
||||||
|
fi
|
||||||
|
for arch in "${arch_list[@]}"; do
|
||||||
|
xdir=firefox-$arch
|
||||||
|
|
||||||
|
rm -rf $xdir
|
||||||
|
mkdir $xdir
|
||||||
|
|
||||||
|
archived_file="Firefox Setup $GECKO_VERSION-$arch.exe"
|
||||||
|
if [ -e "$archived_file" ]; then
|
||||||
|
echo "Using $archived_file"
|
||||||
|
cp "$archived_file" "Firefox%20Setup%20$GECKO_VERSION.exe"
|
||||||
|
else
|
||||||
|
if [ $arch = "win-x64" ]; then
|
||||||
|
moz_arch=win64
|
||||||
|
elif [ $arch = "win-arm64" ]; then
|
||||||
|
moz_arch=win64-aarch64
|
||||||
|
else
|
||||||
|
moz_arch=$arch
|
||||||
|
fi
|
||||||
|
curl -fO "$DOWNLOAD_URL/$moz_arch/en-US/Firefox%20Setup%20$GECKO_VERSION.exe"
|
||||||
|
# Store local copy of unmodified app
|
||||||
|
cp "Firefox%20Setup%20$GECKO_VERSION.exe" "$archived_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
7z x Firefox%20Setup%20$GECKO_VERSION.exe -o$xdir 'core/*'
|
||||||
|
mv $xdir/core $xdir-core
|
||||||
|
rm -rf $xdir
|
||||||
|
mv $xdir-core $xdir
|
||||||
|
|
||||||
|
# Download custom components, as an architecture-specific ZIP containing xul.dll, etc.
|
||||||
|
echo
|
||||||
|
hash_arch_name="${arch/-/_}"
|
||||||
|
arch_var_name="custom_components_hash_${hash_arch_name}"
|
||||||
|
hash=${!arch_var_name:-}
|
||||||
|
if [ -n "$hash" ]; then
|
||||||
|
zipfile="Firefox $GECKO_VERSION-$arch Components.zip"
|
||||||
|
# ZIP filename doesn't include "esr" or "win-"
|
||||||
|
url="${custom_components_url}win/${GECKO_VERSION//esr}-${arch#win-}-$hash.zip"
|
||||||
|
|
||||||
|
if [[ "$(uname)" = "Darwin" ]]; then
|
||||||
|
shasum="shasum -a 256"
|
||||||
|
else
|
||||||
|
shasum=sha256sum
|
||||||
|
fi
|
||||||
|
|
||||||
|
download_zip() {
|
||||||
|
echo "Downloading custom Firefox components"
|
||||||
|
echo
|
||||||
|
echo $url
|
||||||
|
curl -fo "$zipfile" "$url"
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_hash() {
|
||||||
|
echo "$hash $zipfile" | $shasum -c -
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download if file doesn't exist
|
||||||
|
if [ ! -e "$zipfile" ]; then
|
||||||
|
download_zip
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
if ! verify_hash; then
|
||||||
|
echo "SHA hash mismatch. Redownloading ZIP…"
|
||||||
|
rm -f "$zipfile"
|
||||||
|
download_zip
|
||||||
|
echo
|
||||||
|
if ! verify_hash; then
|
||||||
|
echo "Hash still doesn't match. Aborting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
|
unzip -o "$zipfile" -d "$xdir"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd $xdir
|
||||||
|
|
||||||
|
#
|
||||||
|
# NOTE: Below is disabled, since the full UTF-16 string no longer appears directly in the DLL
|
||||||
|
# -- it's now truncated after "e594e8d1" for x64/win32 and doesn't appear at all for ARM64
|
||||||
|
#
|
||||||
|
|
||||||
|
# Replace "Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38" with "Zotero" for C:\ProgramData directory
|
||||||
|
#
|
||||||
|
# Mozilla uses a UUID in the path because they previously used just "Mozilla" and needed to
|
||||||
|
# recreate the folder with correct permissions for security reasons, but we never had a folder in
|
||||||
|
# ProgramData, so we can just create it as "Zotero". Instead of using a custom xul.dll, just
|
||||||
|
# replace the hard-coded string with "Zotero" and add a bunch of NULs.
|
||||||
|
#
|
||||||
|
#from=$(get_utf16_chars "Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38")
|
||||||
|
#to=$(get_utf16_chars "Zotero" 38)
|
||||||
|
#perl -pe "s/$from/$to/" < xul.dll > xul.dll.new
|
||||||
|
#mv xul.dll.new xul.dll
|
||||||
|
|
||||||
|
# Check for UTF-16 "Zotero" in DLL
|
||||||
|
#
|
||||||
|
# (The macOS strings command doesn't have an encoding option, so skip on macOS. You need to
|
||||||
|
# build on Windows to make an installer, so a Windows build from macOS likely isn't being
|
||||||
|
# deployed.)
|
||||||
|
#
|
||||||
|
#if [[ "`uname`" != "Darwin" ]] && [[ -z "$(strings -e l xul.dll | grep -m 1 Zotero)" ]]; then
|
||||||
|
# echo '"Zotero" not found in xul.dll after replacement'
|
||||||
|
# exit 1
|
||||||
|
#fi
|
||||||
|
|
||||||
|
# We re-sign DLL in build.sh, but presumably this file, which is for the Widevine CDM,
|
||||||
|
# isn't vaid anymore
|
||||||
|
rm xul.dll.sig
|
||||||
|
|
||||||
|
modify_omni $arch
|
||||||
|
# Disable skeleton UI window
|
||||||
|
# https://forums.zotero.org/discussion/comment/437636/#Comment_437636
|
||||||
|
replace_line 'pref\("browser\.startup\.preXulSkeletonUI", true\);' 'pref("browser.startup.preXulSkeletonUI", false);' defaults/preferences/firefox.js
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Uncomment to create local copies for reuse
|
||||||
|
#cp "Firefox%20Setup%20$GECKO_VERSION.exe" "Firefox Setup $GECKO_VERSION-$arch.exe"
|
||||||
|
rm "Firefox%20Setup%20$GECKO_VERSION.exe"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "$( "$SCRIPT_DIR/xulrunner_hash" -p w -a "$arch" )" > "hash-$arch"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $BUILD_LINUX == 1 ]; then
|
||||||
|
GECKO_VERSION="$GECKO_VERSION_LINUX"
|
||||||
|
DOWNLOAD_URL="https://ftp.mozilla.org/pub/firefox/releases/$GECKO_VERSION"
|
||||||
|
|
||||||
|
if [[ -n $arch ]]; then
|
||||||
|
arch_list=("$arch")
|
||||||
|
else
|
||||||
|
arch_list=(x86_64 arm64)
|
||||||
|
fi
|
||||||
|
for arch in "${arch_list[@]}"; do
|
||||||
|
xdir="firefox-linux-$arch"
|
||||||
|
rm -rf $xdir
|
||||||
|
|
||||||
|
archived_file="firefox-$GECKO_VERSION-$arch.tar.xz"
|
||||||
|
if [ -e "$archived_file" ]; then
|
||||||
|
echo "Using $archived_file"
|
||||||
|
cp "$archived_file" "firefox-$GECKO_VERSION.tar.xz"
|
||||||
|
else
|
||||||
|
if [ $arch = "arm64" ]; then
|
||||||
|
moz_arch=aarch64
|
||||||
|
else
|
||||||
|
moz_arch=$arch
|
||||||
|
fi
|
||||||
|
curl -fO "$DOWNLOAD_URL/linux-$moz_arch/en-US/firefox-$GECKO_VERSION.tar.xz"
|
||||||
|
# Store local copy of unmodified app
|
||||||
|
cp "firefox-$GECKO_VERSION.tar.xz" "$archived_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tar xvf firefox-$GECKO_VERSION.tar.xz
|
||||||
|
mv firefox $xdir
|
||||||
|
|
||||||
|
pushd $xdir
|
||||||
|
modify_omni $arch
|
||||||
|
popd
|
||||||
|
|
||||||
|
rm "firefox-$GECKO_VERSION.tar.xz"
|
||||||
|
|
||||||
|
echo "$( $SCRIPT_DIR/xulrunner_hash -p l -a "$arch" )" > "hash-linux-${arch}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo Done
|
||||||
21
app/scripts/get_commit_files
Executable file
21
app/scripts/get_commit_files
Executable file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
echo "Commit hash not provided"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
hash="$1"
|
||||||
|
|
||||||
|
tmpdir=`mktemp -d`
|
||||||
|
|
||||||
|
cd $tmpdir
|
||||||
|
curl -sS -f -L -o build.zip "https://$S3_BUCKET.s3.amazonaws.com/$S3_CI_ZIP_PATH/$hash.zip" >&2 \
|
||||||
|
|| (echo "ZIP file not found for commit '$hash'" && exit 1)
|
||||||
|
unzip build.zip >&2
|
||||||
|
rm build.zip
|
||||||
|
echo $tmpdir
|
||||||
14
app/scripts/get_repo_branch_hash
Executable file
14
app/scripts/get_repo_branch_hash
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [ -z "${1:-}" ]; then
|
||||||
|
echo "Usage: $0 branch"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
branch=$1
|
||||||
|
|
||||||
|
git ls-remote --exit-code $SOURCE_REPO_URL $branch | cut -f 1
|
||||||
322
app/scripts/incremental_update
Executable file
322
app/scripts/incremental_update
Executable file
|
|
@ -0,0 +1,322 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
#
|
||||||
|
# Incrementally update a staged build in staging/ by zipping changed files from
|
||||||
|
# the client build/ directory directly into app/omni.ja, based on a manifest
|
||||||
|
# saved by dir_build after the last full build.
|
||||||
|
#
|
||||||
|
# Only files that are copied into omni.ja unmodified by build.sh can be updated
|
||||||
|
# this way. If any other file changed (or a file was removed), a full rebuild
|
||||||
|
# is required.
|
||||||
|
#
|
||||||
|
# Exit codes:
|
||||||
|
# 0 -- staged build was updated (or nothing changed)
|
||||||
|
# 2 -- a full rebuild is required
|
||||||
|
#
|
||||||
|
# This is normally run automatically by dir_build, not directly.
|
||||||
|
#
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$APP_ROOT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
. "$SCRIPT_DIR/utils.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage: $0 -p PLATFORM [-a ARCH] [-t]
|
||||||
|
|
||||||
|
Options
|
||||||
|
-p PLATFORM platform of the staged build to update (m=Mac, w=Windows, l=Linux)
|
||||||
|
-a ARCH target architecture (Windows/Linux only)
|
||||||
|
-t devtools requested
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
platform=""
|
||||||
|
arch=""
|
||||||
|
devtools=0
|
||||||
|
while getopts "p:a:t" opt; do
|
||||||
|
case $opt in
|
||||||
|
p)
|
||||||
|
platform="$OPTARG"
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
arch="$OPTARG"
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
devtools=1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$platform" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_SRC_DIR="$ROOT_DIR/build"
|
||||||
|
MANIFEST_FILE="$STAGE_DIR/.build-manifest"
|
||||||
|
|
||||||
|
function fall_back {
|
||||||
|
echo "$1 -- performing full build" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ! -d "$BUILD_SRC_DIR" ]; then
|
||||||
|
fall_back "No build/ directory"
|
||||||
|
fi
|
||||||
|
if [ ! -f "$MANIFEST_FILE" ]; then
|
||||||
|
fall_back "No manifest from previous build"
|
||||||
|
fi
|
||||||
|
if [[ "$(sed -n 's/^#format=//p' "$MANIFEST_FILE")" != "2" ]]; then
|
||||||
|
fall_back "Unsupported manifest format"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure a staged build exists for the requested platform
|
||||||
|
case $platform in
|
||||||
|
m)
|
||||||
|
app_dir="$STAGE_DIR/Zotero.app/Contents/Resources"
|
||||||
|
;;
|
||||||
|
w)
|
||||||
|
app_dir="$STAGE_DIR/Zotero_$(get_canonical_arch w "$arch")"
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
app_dir="$STAGE_DIR/Zotero_linux-$(get_canonical_arch l "$arch")"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fall_back "Unknown platform '$platform'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [ ! -f "$app_dir/app/omni.ja" ]; then
|
||||||
|
fall_back "No staged build for requested platform"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If the previous build didn't include tests or devtools and they're requested
|
||||||
|
# now, files are missing from the staged build
|
||||||
|
manifest_tests=$(sed -n 's/^#include_tests=//p' "$MANIFEST_FILE")
|
||||||
|
manifest_tests=${manifest_tests:-0}
|
||||||
|
manifest_devtools=$(sed -n 's/^#devtools=//p' "$MANIFEST_FILE")
|
||||||
|
manifest_devtools=${manifest_devtools:-0}
|
||||||
|
if [[ -z "${ZOTERO_TEST:-}" ]] || [[ "${ZOTERO_TEST:-}" == "0" ]]; then
|
||||||
|
want_tests=0
|
||||||
|
else
|
||||||
|
want_tests=1
|
||||||
|
fi
|
||||||
|
if [[ $want_tests -eq 1 ]] && [[ $manifest_tests != "1" ]]; then
|
||||||
|
fall_back "Tests requested but not included in staged build"
|
||||||
|
fi
|
||||||
|
if [[ $devtools -eq 1 ]] && [[ $manifest_devtools != "1" ]]; then
|
||||||
|
fall_back "Devtools requested but not included in staged build"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If anything changed in app/ (build scripts, assets, bundled modules, Firefox
|
||||||
|
# runtime), a full rebuild is required
|
||||||
|
manifest_app_hash=$(sed -n 's/^#app_hash=//p' "$MANIFEST_FILE")
|
||||||
|
app_hash=$(generate_app_hash "$APP_ROOT_DIR")
|
||||||
|
if [[ -z "$manifest_app_hash" ]] || [[ "$app_hash" != "$manifest_app_hash" ]]; then
|
||||||
|
fall_back "Files in app/ changed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
file_list=$(mktemp)
|
||||||
|
new_stats=$(mktemp)
|
||||||
|
carried=$(mktemp)
|
||||||
|
candidates=$(mktemp)
|
||||||
|
removed=$(mktemp)
|
||||||
|
cand_entries=$(mktemp)
|
||||||
|
trap 'rm -f "$file_list" "$new_stats" "$carried" "$candidates" "$removed" "$cand_entries"' EXIT
|
||||||
|
|
||||||
|
cd "$BUILD_SRC_DIR"
|
||||||
|
|
||||||
|
# Quickly find files that may have changed based on size/mtime, so that only
|
||||||
|
# those have to be hashed. Unmodified manifest entries are carried over,
|
||||||
|
# new/modified files become candidates, and files no longer present are
|
||||||
|
# considered removed.
|
||||||
|
build_manifest_file_list > "$file_list"
|
||||||
|
stat_file_list < "$file_list" > "$new_stats"
|
||||||
|
awk -F'\t' -v carried="$carried" -v candidates="$candidates" -v removed="$removed" '
|
||||||
|
NR==FNR {
|
||||||
|
if (/^#/) next
|
||||||
|
hash[$3] = $1
|
||||||
|
stat[$3] = $2
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if (!($2 in stat)) {
|
||||||
|
print > candidates
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($1 == stat[$2]) {
|
||||||
|
print hash[$2] "\t" $0 > carried
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print > candidates
|
||||||
|
}
|
||||||
|
delete stat[$2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
for (path in stat) print path > removed
|
||||||
|
}
|
||||||
|
' "$MANIFEST_FILE" "$new_stats"
|
||||||
|
|
||||||
|
# Hash the candidates and compare to the previous hashes to find real changes
|
||||||
|
# -- A = added, C = changed, R = removed
|
||||||
|
if [ -s "$candidates" ]; then
|
||||||
|
paste \
|
||||||
|
<(cut -f2 "$candidates" | sed 's,^,./,' | tr '\n' '\0' | hash_file_list | cut -f1) \
|
||||||
|
"$candidates" \
|
||||||
|
> "$cand_entries"
|
||||||
|
fi
|
||||||
|
changes=$(
|
||||||
|
if [ -s "$cand_entries" ]; then
|
||||||
|
awk -F'\t' '
|
||||||
|
NR==FNR {
|
||||||
|
if (/^#/) next
|
||||||
|
old[$3] = $1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if (!($3 in old)) print "A\t" $3
|
||||||
|
else if (old[$3] != $1) print "C\t" $3
|
||||||
|
}
|
||||||
|
' "$MANIFEST_FILE" "$cand_entries"
|
||||||
|
fi
|
||||||
|
if [ -s "$removed" ]; then
|
||||||
|
awk '{print "R\t" $0}' "$removed"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure all changed files can be zipped directly into omni.ja, and skip
|
||||||
|
# ones that aren't included in the staged build
|
||||||
|
zip_files=()
|
||||||
|
ftl_files=()
|
||||||
|
test_copy_files=()
|
||||||
|
while IFS=$'\t' read -r status path; do
|
||||||
|
if [ -z "$status" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$status" == "R" ]; then
|
||||||
|
case "$path" in
|
||||||
|
test/*)
|
||||||
|
# Ignore removed test files if tests weren't included
|
||||||
|
if [[ $manifest_tests != "1" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fall_back "$path was removed"
|
||||||
|
fi
|
||||||
|
case "$path" in
|
||||||
|
# Copied into localization/ subdirectories by build.sh
|
||||||
|
chrome/locale/*/zotero/mozilla/*)
|
||||||
|
fall_back "Can't update $path in place"
|
||||||
|
;;
|
||||||
|
# Pruned by prepare_build
|
||||||
|
chrome/content/zotero/locale/csl/*)
|
||||||
|
fall_back "Can't update $path in place"
|
||||||
|
;;
|
||||||
|
# Copied to localization/<locale>/ in addition to the chrome path
|
||||||
|
chrome/locale/*/zotero/*.ftl)
|
||||||
|
zip_files+=("$path")
|
||||||
|
ftl_files+=("$path")
|
||||||
|
;;
|
||||||
|
chrome/*|components/*|resource/*)
|
||||||
|
zip_files+=("$path")
|
||||||
|
;;
|
||||||
|
# Appended to the main chrome.manifest by build.sh
|
||||||
|
test/chrome.manifest)
|
||||||
|
fall_back "Can't update $path in place"
|
||||||
|
;;
|
||||||
|
test/*)
|
||||||
|
# If tests weren't included in the staged build, ignore changes
|
||||||
|
# to test files
|
||||||
|
if [[ $manifest_tests == "1" ]]; then
|
||||||
|
zip_files+=("$path")
|
||||||
|
case "$path" in
|
||||||
|
# Also copied to tests/ at the top level of the app
|
||||||
|
test/tests/*)
|
||||||
|
test_copy_files+=("$path")
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
fall_back "Can't update $path in place"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done <<< "$changes"
|
||||||
|
|
||||||
|
# Find all staged omni.ja files to update (multiple can exist -- e.g., all
|
||||||
|
# Windows architectures)
|
||||||
|
omni_files=()
|
||||||
|
while IFS= read -r file; do
|
||||||
|
omni_files+=("$file")
|
||||||
|
done < <(find "$STAGE_DIR" -path '*/app/omni.ja')
|
||||||
|
|
||||||
|
if [ ${#zip_files[@]} -gt 0 ]; then
|
||||||
|
echo "Changed files:"
|
||||||
|
for path in "${zip_files[@]}"; do
|
||||||
|
echo " $path"
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$BUILD_SRC_DIR"
|
||||||
|
for omni_file in "${omni_files[@]}"; do
|
||||||
|
echo "Updating ${omni_file#"$STAGE_DIR"/}"
|
||||||
|
zip -qX "$omni_file" "${zip_files[@]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy .ftl files to their localization/ paths
|
||||||
|
if [ ${#ftl_files[@]} -gt 0 ]; then
|
||||||
|
l10n_dir=$(mktemp -d)
|
||||||
|
for path in "${ftl_files[@]}"; do
|
||||||
|
locale=${path#chrome/locale/}
|
||||||
|
locale=${locale%%/*}
|
||||||
|
mkdir -p "$l10n_dir/localization/$locale"
|
||||||
|
cp -L "$path" "$l10n_dir/localization/$locale/$(basename "$path")"
|
||||||
|
done
|
||||||
|
pushd "$l10n_dir" > /dev/null
|
||||||
|
for omni_file in "${omni_files[@]}"; do
|
||||||
|
zip -qrX "$omni_file" localization
|
||||||
|
done
|
||||||
|
popd > /dev/null
|
||||||
|
rm -rf "$l10n_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy test files to tests/ directories
|
||||||
|
if [ ${#test_copy_files[@]} -gt 0 ]; then
|
||||||
|
for path in "${test_copy_files[@]}"; do
|
||||||
|
for omni_file in "${omni_files[@]}"; do
|
||||||
|
dest="${omni_file%/app/omni.ja}/tests/${path#test/tests/}"
|
||||||
|
mkdir -p "$(dirname "$dest")"
|
||||||
|
cp -L "$path" "$dest"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Bump BuildID so that startup caches are invalidated even without
|
||||||
|
# -purgecaches
|
||||||
|
build_id=$(date +%Y%m%d%H%M%S)
|
||||||
|
for omni_file in "${omni_files[@]}"; do
|
||||||
|
perl -pi -e "s/^BuildID=.*/BuildID=$build_id/" "$(dirname "$omni_file")/application.ini"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Updated staged build with ${#zip_files[@]} changed file(s)"
|
||||||
|
elif [ -n "$changes" ]; then
|
||||||
|
echo "No staged files changed"
|
||||||
|
else
|
||||||
|
echo "No changes since last build"
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "#format=2"
|
||||||
|
echo "#include_tests=$manifest_tests"
|
||||||
|
echo "#devtools=$manifest_devtools"
|
||||||
|
echo "#app_hash=$app_hash"
|
||||||
|
LC_ALL=C sort -t$'\t' -k3 "$carried" "$cand_entries"
|
||||||
|
} > "$MANIFEST_FILE.tmp"
|
||||||
|
mv "$MANIFEST_FILE.tmp" "$MANIFEST_FILE"
|
||||||
88
app/scripts/manage_incrementals
Executable file
88
app/scripts/manage_incrementals
Executable file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Manage list of deployed version numbers for a channel in order to generate incremental builds
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage:
|
||||||
|
-c CHANNEL Release channel (e.g., 'beta'); defaults to 'release'
|
||||||
|
-p PLATFORM Platform (m=Mac, w=Windows, l=Linux)
|
||||||
|
-a VERSION Add version to incrementals list; cannot be used with -n
|
||||||
|
-n NUM_VERSIONS Number of previous versions to return; cannot be used with -a
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
CHANNEL="release"
|
||||||
|
PLATFORM=""
|
||||||
|
VERSION=""
|
||||||
|
NUM_VERSIONS=""
|
||||||
|
while getopts "c:p:a:n:" opt; do
|
||||||
|
case $opt in
|
||||||
|
c)
|
||||||
|
CHANNEL="$OPTARG"
|
||||||
|
;;
|
||||||
|
p)
|
||||||
|
case "$OPTARG" in
|
||||||
|
m) PLATFORM=mac;;
|
||||||
|
w) PLATFORM=win;;
|
||||||
|
l) PLATFORM=linux;;
|
||||||
|
*)
|
||||||
|
echo "$0: Invalid platform option $OPTARG"
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
VERSION="$OPTARG"
|
||||||
|
;;
|
||||||
|
n)
|
||||||
|
NUM_VERSIONS="$OPTARG"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PLATFORM" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$VERSION" ]] && [[ -z "$NUM_VERSIONS" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$VERSION" ]] && [[ "$NUM_VERSIONS" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
INCR_FILENAME="incrementals-$PLATFORM"
|
||||||
|
REMOTE_PATH="$DEPLOY_PATH/manifests/$CHANNEL/$INCR_FILENAME"
|
||||||
|
INCR_PATH="$DIST_DIR/$INCR_FILENAME"
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p "$DIST_DIR"
|
||||||
|
scp $DEPLOY_HOST:"$REMOTE_PATH" "$INCR_PATH" >&2
|
||||||
|
|
||||||
|
# Add version to file and reupload
|
||||||
|
if [ "$VERSION" ]; then
|
||||||
|
echo "Adding $VERSION to incrementals-$PLATFORM"
|
||||||
|
echo $VERSION >> "$INCR_PATH"
|
||||||
|
scp "$INCR_PATH" $DEPLOY_HOST:"$REMOTE_PATH"
|
||||||
|
# Show last n versions
|
||||||
|
elif [ "$NUM_VERSIONS" -gt 0 ]; then
|
||||||
|
# TEMP: Don't include 6.0 versions
|
||||||
|
#tail -n $NUM_VERSIONS "$INCR_PATH"
|
||||||
|
set +e
|
||||||
|
tail -n $NUM_VERSIONS "$INCR_PATH" | grep -v '^6\.0'
|
||||||
|
set -e
|
||||||
|
fi
|
||||||
|
rm "$INCR_PATH"
|
||||||
22
app/scripts/notarization_info
Executable file
22
app/scripts/notarization_info
Executable file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
. "$SCRIPT_DIR/utils.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $0 id"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
id=${1:-}
|
||||||
|
if [[ -z "$id" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
prepare_notary_auth
|
||||||
|
|
||||||
|
xcrun notarytool log "$id" "${notary_auth[@]}" notary_log.json
|
||||||
|
cat notary_log.json
|
||||||
19
app/scripts/notarization_stapler
Executable file
19
app/scripts/notarization_stapler
Executable file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $0 file"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
file=${1:-}
|
||||||
|
if [[ -z "$file" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Stapling $file"
|
||||||
|
xcrun stapler staple $file
|
||||||
22
app/scripts/notarize_mac_app
Executable file
22
app/scripts/notarize_mac_app
Executable file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
. "$SCRIPT_DIR/utils.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $0 file"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
file=${1:-}
|
||||||
|
if [[ -z "$file" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
prepare_notary_auth
|
||||||
|
|
||||||
|
echo "Uploading ${file##*/} to Apple for notarization" >&2
|
||||||
|
xcrun notarytool submit $file "${notary_auth[@]}" --wait
|
||||||
376
app/scripts/optimizejars.py
Normal file
376
app/scripts/optimizejars.py
Normal file
|
|
@ -0,0 +1,376 @@
|
||||||
|
# ***** BEGIN LICENSE BLOCK *****
|
||||||
|
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
# http://www.mozilla.org/MPL/
|
||||||
|
#
|
||||||
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
# for the specific language governing rights and limitations under the
|
||||||
|
# License.
|
||||||
|
#
|
||||||
|
# The Original Code is mozilla.org code
|
||||||
|
#
|
||||||
|
# The Initial Developer of the Original Code is
|
||||||
|
# Mozilla Foundation.
|
||||||
|
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
# the Initial Developer. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Contributor(s):
|
||||||
|
# Taras Glek <tglek@mozilla.com>
|
||||||
|
#
|
||||||
|
# Alternatively, the contents of this file may be used under the terms of
|
||||||
|
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
# of those above. If you wish to allow use of your version of this file only
|
||||||
|
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
# use your version of this file under the terms of the MPL, indicate your
|
||||||
|
# decision by deleting the provisions above and replace them with the notice
|
||||||
|
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
# the provisions above, a recipient may use your version of this file under
|
||||||
|
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
#
|
||||||
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
|
import sys, os, subprocess, struct, re
|
||||||
|
|
||||||
|
local_file_header = [
|
||||||
|
("signature", "uint32"),
|
||||||
|
("min_version", "uint16"),
|
||||||
|
("general_flag", "uint16"),
|
||||||
|
("compression", "uint16"),
|
||||||
|
("lastmod_time", "uint16"),
|
||||||
|
("lastmod_date", "uint16"),
|
||||||
|
("crc32", "uint32"),
|
||||||
|
("compressed_size", "uint32"),
|
||||||
|
("uncompressed_size", "uint32"),
|
||||||
|
("filename_size", "uint16"),
|
||||||
|
("extra_field_size", "uint16"),
|
||||||
|
("filename", "filename_size"),
|
||||||
|
("extra_field", "extra_field_size"),
|
||||||
|
("data", "compressed_size")
|
||||||
|
]
|
||||||
|
|
||||||
|
cdir_entry = [
|
||||||
|
("signature", "uint32"),
|
||||||
|
("creator_version", "uint16"),
|
||||||
|
("min_version", "uint16"),
|
||||||
|
("general_flag", "uint16"),
|
||||||
|
("compression", "uint16"),
|
||||||
|
("lastmod_time", "uint16"),
|
||||||
|
("lastmod_date", "uint16"),
|
||||||
|
("crc32", "uint32"),
|
||||||
|
("compressed_size", "uint32"),
|
||||||
|
("uncompressed_size", "uint32"),
|
||||||
|
("filename_size", "uint16"),
|
||||||
|
("extrafield_size", "uint16"),
|
||||||
|
("filecomment_size", "uint16"),
|
||||||
|
("disknum", "uint16"),
|
||||||
|
("internal_attr", "uint16"),
|
||||||
|
("external_attr", "uint32"),
|
||||||
|
("offset", "uint32"),
|
||||||
|
("filename", "filename_size"),
|
||||||
|
("extrafield", "extrafield_size"),
|
||||||
|
("filecomment", "filecomment_size"),
|
||||||
|
]
|
||||||
|
|
||||||
|
cdir_end = [
|
||||||
|
("signature", "uint32"),
|
||||||
|
("disk_num", "uint16"),
|
||||||
|
("cdir_disk", "uint16"),
|
||||||
|
("disk_entries", "uint16"),
|
||||||
|
("cdir_entries", "uint16"),
|
||||||
|
("cdir_size", "uint32"),
|
||||||
|
("cdir_offset", "uint32"),
|
||||||
|
("comment_size", "uint16"),
|
||||||
|
]
|
||||||
|
|
||||||
|
type_mapping = { "uint32":"I", "uint16":"H"}
|
||||||
|
|
||||||
|
def format_struct (format):
|
||||||
|
string_fields = {}
|
||||||
|
fmt = "<"
|
||||||
|
for (name,value) in iter(format):
|
||||||
|
try:
|
||||||
|
fmt += type_mapping[value][0]
|
||||||
|
except KeyError:
|
||||||
|
string_fields[name] = value
|
||||||
|
return (fmt, string_fields)
|
||||||
|
|
||||||
|
def size_of(format):
|
||||||
|
return struct.calcsize(format_struct(format)[0])
|
||||||
|
|
||||||
|
class MyStruct:
|
||||||
|
def __init__(self, format, string_fields):
|
||||||
|
self.__dict__["struct_members"] = {}
|
||||||
|
self.__dict__["format"] = format
|
||||||
|
self.__dict__["string_fields"] = string_fields
|
||||||
|
|
||||||
|
def addMember(self, name, value):
|
||||||
|
self.__dict__["struct_members"][name] = value
|
||||||
|
|
||||||
|
def __getattr__(self, item):
|
||||||
|
try:
|
||||||
|
return self.__dict__["struct_members"][item]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
print("no %s" %item)
|
||||||
|
print(self.__dict__["struct_members"])
|
||||||
|
raise AttributeError
|
||||||
|
|
||||||
|
def __setattr__(self, item, value):
|
||||||
|
if item in self.__dict__["struct_members"]:
|
||||||
|
self.__dict__["struct_members"][item] = value
|
||||||
|
else:
|
||||||
|
raise AttributeError
|
||||||
|
|
||||||
|
def pack(self):
|
||||||
|
extra_data = b""
|
||||||
|
values = []
|
||||||
|
string_fields = self.__dict__["string_fields"]
|
||||||
|
struct_members = self.__dict__["struct_members"]
|
||||||
|
format = self.__dict__["format"]
|
||||||
|
for (name,_) in format:
|
||||||
|
if name in string_fields:
|
||||||
|
if not isinstance(struct_members[name], bytes):
|
||||||
|
struct_members[name] = struct_members[name].encode('utf-8')
|
||||||
|
extra_data = extra_data + struct_members[name]
|
||||||
|
else:
|
||||||
|
values.append(struct_members[name]);
|
||||||
|
return struct.pack(format_struct(format)[0], *values) + extra_data
|
||||||
|
|
||||||
|
ENDSIG = 0x06054b50
|
||||||
|
|
||||||
|
def assert_true(cond, msg):
|
||||||
|
if not cond:
|
||||||
|
raise Exception(msg)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
class BinaryBlob:
|
||||||
|
def __init__(self, f):
|
||||||
|
self.data = open(f, "rb").read()
|
||||||
|
self.offset = 0
|
||||||
|
self.length = len(self.data)
|
||||||
|
|
||||||
|
def readAt(self, pos, length):
|
||||||
|
self.offset = pos + length
|
||||||
|
return self.data[pos:self.offset]
|
||||||
|
|
||||||
|
def read_struct (self, format, offset = None):
|
||||||
|
if offset == None:
|
||||||
|
offset = self.offset
|
||||||
|
(fstr, string_fields) = format_struct(format)
|
||||||
|
size = struct.calcsize(fstr)
|
||||||
|
data = self.readAt(offset, size)
|
||||||
|
ret = struct.unpack(fstr, data)
|
||||||
|
retstruct = MyStruct(format, string_fields)
|
||||||
|
i = 0
|
||||||
|
for (name,_) in iter(format):
|
||||||
|
member_desc = None
|
||||||
|
if not name in string_fields:
|
||||||
|
member_data = ret[i]
|
||||||
|
i = i + 1
|
||||||
|
else:
|
||||||
|
# zip has data fields which are described by other struct fields, this does
|
||||||
|
# additional reads to fill em in
|
||||||
|
member_desc = string_fields[name]
|
||||||
|
member_data = self.readAt(self.offset, retstruct.__getattr__(member_desc))
|
||||||
|
retstruct.addMember(name, member_data)
|
||||||
|
# sanity check serialization code
|
||||||
|
data = self.readAt(offset, self.offset - offset)
|
||||||
|
out_data = retstruct.pack()
|
||||||
|
assert_true(out_data == data, "Serialization fail %d !=%d"% (len(out_data), len(data)))
|
||||||
|
return retstruct
|
||||||
|
|
||||||
|
def optimizejar(jar, outjar, inlog = None):
|
||||||
|
if inlog is not None:
|
||||||
|
inlog = open(inlog).read().rstrip()
|
||||||
|
# in the case of an empty log still move the index forward
|
||||||
|
if len(inlog) == 0:
|
||||||
|
inlog = []
|
||||||
|
else:
|
||||||
|
inlog = inlog.split("\n")
|
||||||
|
outlog = []
|
||||||
|
jarblob = BinaryBlob(jar)
|
||||||
|
dirend = jarblob.read_struct(cdir_end, jarblob.length - size_of(cdir_end))
|
||||||
|
assert_true(dirend.signature == ENDSIG, "no signature in the end");
|
||||||
|
cdir_offset = dirend.cdir_offset
|
||||||
|
readahead = 0
|
||||||
|
if inlog is None and cdir_offset == 4:
|
||||||
|
readahead = struct.unpack("<I", jarblob.readAt(0, 4))[0]
|
||||||
|
print("%s: startup data ends at byte %d" % (outjar, readahead));
|
||||||
|
|
||||||
|
total_stripped = 0;
|
||||||
|
jarblob.offset = cdir_offset
|
||||||
|
central_directory = []
|
||||||
|
for i in range(0, dirend.cdir_entries):
|
||||||
|
entry = jarblob.read_struct(cdir_entry)
|
||||||
|
if entry.filename[-1:] == "/":
|
||||||
|
total_stripped += len(entry.pack())
|
||||||
|
else:
|
||||||
|
total_stripped += entry.extrafield_size
|
||||||
|
central_directory.append(entry)
|
||||||
|
|
||||||
|
reordered_count = 0
|
||||||
|
if inlog is not None:
|
||||||
|
dup_guard = set()
|
||||||
|
for ordered_name in inlog:
|
||||||
|
if ordered_name in dup_guard:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
dup_guard.add(ordered_name)
|
||||||
|
found = False
|
||||||
|
for i in range(reordered_count, len(central_directory)):
|
||||||
|
if central_directory[i].filename == ordered_name:
|
||||||
|
# swap the cdir entries
|
||||||
|
tmp = central_directory[i]
|
||||||
|
central_directory[i] = central_directory[reordered_count]
|
||||||
|
central_directory[reordered_count] = tmp
|
||||||
|
reordered_count = reordered_count + 1
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
print( "Can't find '%s' in %s" % (ordered_name, jar))
|
||||||
|
|
||||||
|
outfd = open(outjar, "wb")
|
||||||
|
out_offset = 0
|
||||||
|
if inlog is not None:
|
||||||
|
# have to put central directory at offset 4 cos 0 confuses some tools.
|
||||||
|
# This also lets us specify how many entries should be preread
|
||||||
|
dirend.cdir_offset = 4
|
||||||
|
# make room for central dir + end of dir + 4 extra bytes at front
|
||||||
|
out_offset = dirend.cdir_offset + dirend.cdir_size + size_of(cdir_end) - total_stripped
|
||||||
|
outfd.seek(out_offset)
|
||||||
|
|
||||||
|
cdir_data = b""
|
||||||
|
written_count = 0
|
||||||
|
crc_mapping = {}
|
||||||
|
dups_found = 0
|
||||||
|
dupe_bytes = 0
|
||||||
|
# store number of bytes suggested for readahead
|
||||||
|
for entry in central_directory:
|
||||||
|
# read in the header twice..first for comparison, second time for convenience when writing out
|
||||||
|
jarfile = jarblob.read_struct(local_file_header, entry.offset)
|
||||||
|
assert_true(jarfile.filename == entry.filename, "Directory/Localheader mismatch")
|
||||||
|
# drop directory entries
|
||||||
|
if entry.filename[-1:] == "/":
|
||||||
|
total_stripped += len(jarfile.pack())
|
||||||
|
dirend.cdir_entries -= 1
|
||||||
|
continue
|
||||||
|
# drop extra field data
|
||||||
|
else:
|
||||||
|
total_stripped += jarfile.extra_field_size;
|
||||||
|
entry.extrafield = jarfile.extra_field = ""
|
||||||
|
entry.extrafield_size = jarfile.extra_field_size = 0
|
||||||
|
# January 1st, 2010
|
||||||
|
entry.lastmod_date = jarfile.lastmod_date = ((2010 - 1980) << 9) | (1 << 5) | 1
|
||||||
|
entry.lastmod_time = jarfile.lastmod_time = 0
|
||||||
|
data = jarfile.pack()
|
||||||
|
outfd.write(data)
|
||||||
|
old_entry_offset = entry.offset
|
||||||
|
entry.offset = out_offset
|
||||||
|
out_offset = out_offset + len(data)
|
||||||
|
entry_data = entry.pack()
|
||||||
|
cdir_data += entry_data
|
||||||
|
expected_len = entry.filename_size + entry.extrafield_size + entry.filecomment_size
|
||||||
|
assert_true(len(entry_data) != expected_len,
|
||||||
|
"%s entry size - expected:%d got:%d" % (entry.filename, len(entry_data), expected_len))
|
||||||
|
written_count += 1
|
||||||
|
|
||||||
|
if entry.crc32 in crc_mapping:
|
||||||
|
dups_found += 1
|
||||||
|
dupe_bytes += entry.compressed_size + len(data) + len(entry_data)
|
||||||
|
print("%s\n\tis a duplicate of\n%s\n---"%(entry.filename, crc_mapping[entry.crc32]))
|
||||||
|
else:
|
||||||
|
crc_mapping[entry.crc32] = entry.filename;
|
||||||
|
|
||||||
|
if inlog is not None:
|
||||||
|
if written_count == reordered_count:
|
||||||
|
readahead = out_offset
|
||||||
|
print("%s: startup data ends at byte %d"%( outjar, readahead));
|
||||||
|
elif written_count < reordered_count:
|
||||||
|
pass
|
||||||
|
#print("%s @ %d" % (entry.filename, out_offset))
|
||||||
|
elif readahead >= old_entry_offset + len(data):
|
||||||
|
outlog.append(entry.filename)
|
||||||
|
reordered_count += 1
|
||||||
|
|
||||||
|
if inlog is None:
|
||||||
|
dirend.cdir_offset = out_offset
|
||||||
|
|
||||||
|
if dups_found > 0:
|
||||||
|
print("WARNING: Found %d duplicate files taking %d bytes"%(dups_found, dupe_bytes))
|
||||||
|
|
||||||
|
dirend.cdir_size = len(cdir_data)
|
||||||
|
dirend.disk_entries = dirend.cdir_entries
|
||||||
|
dirend_data = dirend.pack()
|
||||||
|
assert_true(size_of(cdir_end) == len(dirend_data), "Failed to serialize directory end correctly. Serialized size;%d, expected:%d"%(len(dirend_data), size_of(cdir_end)));
|
||||||
|
|
||||||
|
outfd.seek(dirend.cdir_offset)
|
||||||
|
outfd.write(cdir_data)
|
||||||
|
outfd.write(dirend_data)
|
||||||
|
|
||||||
|
# for ordered jars the central directory is written in the begining of the file, so a second central-directory
|
||||||
|
# entry has to be written in the end of the file
|
||||||
|
if inlog is not None:
|
||||||
|
outfd.seek(0)
|
||||||
|
outfd.write(struct.pack("<I", readahead));
|
||||||
|
outfd.seek(out_offset)
|
||||||
|
outfd.write(dirend_data)
|
||||||
|
|
||||||
|
print("Stripped %d bytes" % total_stripped)
|
||||||
|
print("%s %d/%d in %s" % (("Ordered" if inlog is not None else "Deoptimized"),
|
||||||
|
reordered_count, len(central_directory), outjar))
|
||||||
|
outfd.close()
|
||||||
|
return outlog
|
||||||
|
|
||||||
|
if len(sys.argv) != 5:
|
||||||
|
print("Usage: --optimize|--deoptimize %s JAR_LOG_DIR IN_JAR_DIR OUT_JAR_DIR" % sys.argv[0])
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
jar_regex = re.compile("\\.jar?$")
|
||||||
|
|
||||||
|
def optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
|
||||||
|
ls = os.listdir(IN_JAR_DIR)
|
||||||
|
for jarfile in ls:
|
||||||
|
if not re.search(jar_regex, jarfile):
|
||||||
|
continue
|
||||||
|
injarfile = os.path.join(IN_JAR_DIR, jarfile)
|
||||||
|
outjarfile = os.path.join(OUT_JAR_DIR, jarfile)
|
||||||
|
logfile = os.path.join(JAR_LOG_DIR, jarfile + ".log")
|
||||||
|
if not os.path.isfile(logfile):
|
||||||
|
logfile = None
|
||||||
|
optimizejar(injarfile, outjarfile, logfile)
|
||||||
|
|
||||||
|
def deoptimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR):
|
||||||
|
if not os.path.exists(JAR_LOG_DIR):
|
||||||
|
os.makedirs(JAR_LOG_DIR)
|
||||||
|
|
||||||
|
ls = os.listdir(IN_JAR_DIR)
|
||||||
|
for jarfile in ls:
|
||||||
|
if not re.search(jar_regex, jarfile):
|
||||||
|
continue
|
||||||
|
injarfile = os.path.join(IN_JAR_DIR, jarfile)
|
||||||
|
outjarfile = os.path.join(OUT_JAR_DIR, jarfile)
|
||||||
|
logfile = os.path.join(JAR_LOG_DIR, jarfile + ".log")
|
||||||
|
log = str(optimizejar(injarfile, outjarfile, None))
|
||||||
|
open(logfile, "wb").write("\n".join(log).encode('utf-8'))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
MODE = sys.argv[1]
|
||||||
|
JAR_LOG_DIR = sys.argv[2]
|
||||||
|
IN_JAR_DIR = sys.argv[3]
|
||||||
|
OUT_JAR_DIR = sys.argv[4]
|
||||||
|
if MODE == "--optimize":
|
||||||
|
optimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR)
|
||||||
|
elif MODE == "--deoptimize":
|
||||||
|
deoptimize(JAR_LOG_DIR, IN_JAR_DIR, OUT_JAR_DIR)
|
||||||
|
else:
|
||||||
|
print("Unknown mode %s" % MODE)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
218
app/scripts/prepare_build
Executable file
218
app/scripts/prepare_build
Executable file
|
|
@ -0,0 +1,218 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import tempfile
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
import fileinput
|
||||||
|
from collections import OrderedDict
|
||||||
|
import json
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
# Hack to combine two argparse formatters
|
||||||
|
class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
|
||||||
|
pass
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Prepare build/ files for the app build process',
|
||||||
|
formatter_class=CustomFormatter)
|
||||||
|
|
||||||
|
parser.add_argument('--source-dir', '-s', required=True, metavar='BUILD_DIR', help='Directory to build from')
|
||||||
|
parser.add_argument('--output-dir', '-o', required=True, metavar='OUTPUT_DIR', help='Directory to write files to')
|
||||||
|
parser.add_argument('-c', '--channel', default='source', help='channel to add to dev build version number (e.g., "beta" for "5.0-beta.3+a5f28ca8"), or "release" or "source" to skip')
|
||||||
|
parser.add_argument('--commit-hash', '-m', metavar='HASH', help='Commit hash (required for non-release builds)')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
app_root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
|
||||||
|
lastrev_dir = os.path.join(app_root_dir, 'lastrev')
|
||||||
|
if not os.path.exists(lastrev_dir):
|
||||||
|
os.mkdir(lastrev_dir)
|
||||||
|
tmp_dir = os.path.join(app_root_dir, 'tmp')
|
||||||
|
|
||||||
|
if args.commit_hash:
|
||||||
|
commit_hash = args.commit_hash[0:9]
|
||||||
|
elif args.channel != "release":
|
||||||
|
raise Exception("--commit-hash must be specified for non-release builds")
|
||||||
|
|
||||||
|
src_dir = args.source_dir
|
||||||
|
if not os.path.isdir(src_dir):
|
||||||
|
raise Exception(src_dir + " is not a directory")
|
||||||
|
|
||||||
|
output_dir = args.output_dir
|
||||||
|
if not os.path.isdir(output_dir):
|
||||||
|
raise Exception(output_dir + " is not a directory")
|
||||||
|
if os.listdir(output_dir):
|
||||||
|
raise Exception(output_dir + " is not empty")
|
||||||
|
|
||||||
|
log("Using source directory of " + src_dir)
|
||||||
|
os.chdir(src_dir)
|
||||||
|
|
||||||
|
if not os.path.exists('version'):
|
||||||
|
raise FileNotFoundError("version file not found in {0}".format(src_dir))
|
||||||
|
|
||||||
|
# Extract version number from version file
|
||||||
|
with open('version') as f:
|
||||||
|
rdf = f.read()
|
||||||
|
m = re.search('([0-9].+)\\.SOURCE', rdf)
|
||||||
|
if not m:
|
||||||
|
raise Exception("Version number not found in version file")
|
||||||
|
version = m.group(1)
|
||||||
|
|
||||||
|
# Remove tmp build directory if it already exists
|
||||||
|
if os.path.exists(tmp_dir):
|
||||||
|
shutil.rmtree(tmp_dir)
|
||||||
|
os.mkdir(tmp_dir)
|
||||||
|
|
||||||
|
tmp_src_dir = os.path.join(tmp_dir, 'zotero')
|
||||||
|
|
||||||
|
# Export a clean copy of the source tree -- with Python on Windows, where rsync,
|
||||||
|
# if present at all, doesn't handle Windows-style paths
|
||||||
|
if os.name == 'nt' or not shutil.which('rsync'):
|
||||||
|
shutil.copytree(
|
||||||
|
'.',
|
||||||
|
tmp_src_dir,
|
||||||
|
ignore=shutil.ignore_patterns('.*', '#*', 'package.json', 'package-lock.json')
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
subprocess.check_call([
|
||||||
|
'rsync',
|
||||||
|
'-aL',
|
||||||
|
# Exclude hidden files
|
||||||
|
'--exclude', '.*',
|
||||||
|
'--exclude', '#*',
|
||||||
|
'--exclude', 'package.json',
|
||||||
|
'--exclude', 'package-lock.json',
|
||||||
|
'.' + os.sep,
|
||||||
|
tmp_src_dir + os.sep
|
||||||
|
])
|
||||||
|
|
||||||
|
# Make sure the copy worked
|
||||||
|
d = os.path.join(tmp_src_dir, 'chrome')
|
||||||
|
if not os.path.isdir(d):
|
||||||
|
raise FileNotFoundError(d + " not found")
|
||||||
|
|
||||||
|
# Delete CSL locale support files
|
||||||
|
csl_dir = os.path.normpath(tmp_src_dir + '/chrome/content/zotero/locale/csl/')
|
||||||
|
for root, dirs, files in os.walk(csl_dir, topdown=False):
|
||||||
|
for name in files:
|
||||||
|
if not name.endswith('.xml') and name != 'locales.json':
|
||||||
|
os.remove(os.path.join(root, name))
|
||||||
|
for name in dirs:
|
||||||
|
d = os.path.join(root, name)
|
||||||
|
if not os.listdir(d):
|
||||||
|
os.rmdir(d)
|
||||||
|
|
||||||
|
# Delete styles build script
|
||||||
|
os.remove(os.path.join(tmp_src_dir, 'styles', 'update'))
|
||||||
|
|
||||||
|
translators_dir = os.path.join(tmp_src_dir, 'translators')
|
||||||
|
|
||||||
|
# Move deleted.txt out of translators directory
|
||||||
|
f = os.path.join(translators_dir, 'deleted.txt')
|
||||||
|
if os.path.exists(f):
|
||||||
|
shutil.move(f, tmp_src_dir)
|
||||||
|
|
||||||
|
# Build translator index
|
||||||
|
index = OrderedDict()
|
||||||
|
for fn in sorted((fn for fn in os.listdir(translators_dir)), key=str.lower):
|
||||||
|
if not fn.endswith('.js'):
|
||||||
|
continue
|
||||||
|
with open(os.path.join(translators_dir, fn), 'r', encoding='utf-8') as f:
|
||||||
|
contents = f.read()
|
||||||
|
# Parse out the JSON metadata block
|
||||||
|
m = re.match(r'^\s*{[\S\s]*?}\s*?[\r\n]', contents)
|
||||||
|
if not m:
|
||||||
|
raise Exception("Metadata block not found in " + f.name)
|
||||||
|
metadata = json.loads(m.group(0))
|
||||||
|
index[metadata["translatorID"]] = {
|
||||||
|
"fileName": fn,
|
||||||
|
"label": metadata["label"],
|
||||||
|
"lastUpdated": metadata["lastUpdated"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Write translator index as JSON file
|
||||||
|
with open(os.path.join(tmp_src_dir, 'translators.json'), 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(index, f, indent=True, ensure_ascii=False)
|
||||||
|
|
||||||
|
version_file = os.path.join(tmp_src_dir, 'version')
|
||||||
|
|
||||||
|
log('')
|
||||||
|
log_line()
|
||||||
|
log('Original version:\n')
|
||||||
|
dump_file(version_file)
|
||||||
|
|
||||||
|
# Modify version as necessary
|
||||||
|
|
||||||
|
# The dev build revision number is stored in lastrev/{version}-{channel}.
|
||||||
|
#
|
||||||
|
# If we're including it, get the current version number and increment it.
|
||||||
|
if args.channel not in ["release", "source"]:
|
||||||
|
lastrev_file = os.path.join(
|
||||||
|
lastrev_dir, '{0}-{1}'.format(version, args.channel)
|
||||||
|
)
|
||||||
|
if not os.path.exists(lastrev_file):
|
||||||
|
with open(lastrev_file, 'w') as f:
|
||||||
|
f.write("0")
|
||||||
|
rev = 1
|
||||||
|
else:
|
||||||
|
with open(lastrev_file, 'r') as f:
|
||||||
|
rev = f.read()
|
||||||
|
rev = int(rev if rev else 0) + 1
|
||||||
|
|
||||||
|
if args.channel == "release":
|
||||||
|
rev_sub_str = ""
|
||||||
|
elif args.channel == "source":
|
||||||
|
rev_sub_str = ".SOURCE.{0}".format(commit_hash)
|
||||||
|
else:
|
||||||
|
rev_sub_str = "-{0}.{1}+{2}".format(args.channel, str(rev), commit_hash)
|
||||||
|
# Update version
|
||||||
|
for line in fileinput.FileInput(version_file, inplace=1):
|
||||||
|
line = line.replace('.SOURCE', rev_sub_str)
|
||||||
|
print(line, file=sys.stdout, end='')
|
||||||
|
|
||||||
|
log('Modified version:\n')
|
||||||
|
dump_file(version_file)
|
||||||
|
log('')
|
||||||
|
log_line()
|
||||||
|
|
||||||
|
# Move source files to output directory
|
||||||
|
os.rmdir(output_dir)
|
||||||
|
shutil.move(tmp_src_dir, output_dir)
|
||||||
|
|
||||||
|
# Update lastrev file with new revision number
|
||||||
|
if args.channel not in ["release", "source"]:
|
||||||
|
with open(lastrev_file, 'w') as f:
|
||||||
|
f.write(str(rev))
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
sys.stderr.write("\n" + traceback.format_exc())
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
finally:
|
||||||
|
if 'tmp_src_dir' in locals() and os.path.exists(tmp_src_dir):
|
||||||
|
shutil.rmtree(tmp_src_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def dump_file(f):
|
||||||
|
with open(f, 'r') as f:
|
||||||
|
log(f.read())
|
||||||
|
|
||||||
|
|
||||||
|
def log(msg):
|
||||||
|
print(msg, file=sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def log_line():
|
||||||
|
log('======================================================\n\n')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
46
app/scripts/test_build_and_deploy
Executable file
46
app/scripts/test_build_and_deploy
Executable file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
ROOT_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
CHANNEL="test"
|
||||||
|
BRANCH="main"
|
||||||
|
if [ "`uname`" = "Darwin" ]; then
|
||||||
|
export SAFARI_APPEX="$ROOT_DIR/../safari-web-extension-builds/ZoteroSafariExtension.appex"
|
||||||
|
export SAFARI_EXT_RESOURCES="$ROOT_DIR/../safari-web-extension-builds/test/safari"
|
||||||
|
export SAFARI_APP_EXTENSION="$ROOT_DIR/../safari-app-extension-builds/test/ZoteroSafariExtension.appex"
|
||||||
|
if [ ! -d "$SAFARI_APPEX" ]; then
|
||||||
|
echo "Safari extension stub not found at $SAFARI_APPEX -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$SAFARI_EXT_RESOURCES/manifest.json" ]; then
|
||||||
|
echo "Safari web extension not found in $SAFARI_EXT_RESOURCES -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -d "$SAFARI_APP_EXTENSION" ]; then
|
||||||
|
echo "Safari App Extension not found at $SAFARI_APP_EXTENSION -- aborting" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
./check_requirements
|
||||||
|
|
||||||
|
hash=`./get_repo_branch_hash $BRANCH`
|
||||||
|
./check_app_matches_commit $hash
|
||||||
|
source_dir=`./get_commit_files $hash`
|
||||||
|
build_dir=`mktemp -d`
|
||||||
|
|
||||||
|
function cleanup {
|
||||||
|
rm -rf "$source_dir"
|
||||||
|
rm -rf "$build_dir"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
./prepare_build -s "$source_dir" -o "$build_dir" -c $CHANNEL -m $hash
|
||||||
|
VERSION="`cat \"$build_dir/version\"`"
|
||||||
|
./build_for_deploy -d "$build_dir" -p $BUILD_PLATFORMS -c $CHANNEL -i 1
|
||||||
|
ssh $DEPLOY_HOST "$DEPLOY_PATH/deploy" $CHANNEL "$VERSION" $BUILD_PLATFORMS
|
||||||
28
app/scripts/upload_builds
Executable file
28
app/scripts/upload_builds
Executable file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Upload build archives from 'dist' to S3 with the specified channel and version
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
echo Usage: $0 CHANNEL VERSION >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
CHANNEL="${1:-}"
|
||||||
|
VERSION="${2:-}"
|
||||||
|
|
||||||
|
if [[ -z "$CHANNEL" ]] || [[ -z "$VERSION" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
source_dir="$DIST_DIR"
|
||||||
|
if [ "`uname -o 2> /dev/null`" = "Cygwin" ]; then
|
||||||
|
source_dir=$(cygpath -w "$source_dir")
|
||||||
|
fi
|
||||||
|
url="s3://$S3_BUCKET/$S3_DIST_PATH/$CHANNEL/$VERSION/"
|
||||||
|
aws s3 sync --exclude "files-*" --exclude build_id "$source_dir" $url
|
||||||
187
app/scripts/utils.sh
Normal file
187
app/scripts/utils.sh
Normal file
|
|
@ -0,0 +1,187 @@
|
||||||
|
get_current_platform() {
|
||||||
|
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||||
|
echo l
|
||||||
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
echo m
|
||||||
|
elif [[ "$OSTYPE" == "cygwin" ]]; then
|
||||||
|
echo w
|
||||||
|
elif [[ "$OSTYPE" == "msys" ]]; then
|
||||||
|
echo w
|
||||||
|
# Unknown, so probably Unix-y
|
||||||
|
else
|
||||||
|
echo l
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_canonical_arch() {
|
||||||
|
local _platform=$1
|
||||||
|
local _arch=$2
|
||||||
|
|
||||||
|
case $_platform in
|
||||||
|
w)
|
||||||
|
case $_arch in
|
||||||
|
x64) _arch="win-x64" ;;
|
||||||
|
arm64) _arch="win-arm64" ;;
|
||||||
|
win32|win-x64|win-arm64) ;;
|
||||||
|
*) echo "Invalid Windows archicture: $_arch" >&2;;
|
||||||
|
esac
|
||||||
|
echo $_arch
|
||||||
|
;;
|
||||||
|
|
||||||
|
l)
|
||||||
|
[[ $_arch == x64 ]] && _arch="x86_64"
|
||||||
|
echo $_arch
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Invalid platform '$platform'" 2>&1
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print a sorted NUL-separated list of the files in the current directory to
|
||||||
|
# include in the build manifest. Follows symlinks, like the rsync calls in
|
||||||
|
# prepare_build and build.sh.
|
||||||
|
function build_manifest_file_list {
|
||||||
|
# Exclusions match the rsync call in prepare_build
|
||||||
|
find -L . -mindepth 1 \( -name '.*' -o -name '#*' \) -prune \
|
||||||
|
-o -type f ! -name 'package.json' ! -name 'package-lock.json' -print0 \
|
||||||
|
| LC_ALL=C sort -z
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read a NUL-separated file list on stdin and print "size|mtime<TAB>path" for
|
||||||
|
# each file
|
||||||
|
function stat_file_list {
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
xargs -0 stat -L -f '%z|%Fm|%N'
|
||||||
|
else
|
||||||
|
xargs -0 stat -L -c '%s|%y|%n'
|
||||||
|
fi | sed -E 's,^([0-9]+[|][^|]+)[|](\./)?,\1'$'\t'','
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read a NUL-separated file list on stdin and print "hash<TAB>path" for each
|
||||||
|
# file
|
||||||
|
function hash_file_list {
|
||||||
|
local md5_cmd
|
||||||
|
if command -v md5sum > /dev/null 2>&1; then
|
||||||
|
md5_cmd="md5sum"
|
||||||
|
else
|
||||||
|
md5_cmd="md5 -r"
|
||||||
|
fi
|
||||||
|
xargs -0 $md5_cmd | sed -E 's,^([0-9a-f]{32}) ?(\./)?,\1'$'\t'','
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate a manifest of a build directory for incremental updates, with one
|
||||||
|
# "hash<TAB>size|mtime<TAB>path" line per file, sorted by path
|
||||||
|
function generate_build_manifest {
|
||||||
|
local dir=$1
|
||||||
|
(
|
||||||
|
cd "$dir"
|
||||||
|
local file_list
|
||||||
|
file_list=$(mktemp)
|
||||||
|
build_manifest_file_list > "$file_list"
|
||||||
|
paste \
|
||||||
|
<(hash_file_list < "$file_list" | cut -f1) \
|
||||||
|
<(stat_file_list < "$file_list")
|
||||||
|
rm -f "$file_list"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate a hash of the files in app/ that affect build output, for detecting
|
||||||
|
# when a staged build can't be updated incrementally. Since some of the files
|
||||||
|
# are large binaries, use file sizes and modification times rather than
|
||||||
|
# contents. The xulrunner runtimes are covered by the hash-* files written by
|
||||||
|
# fetch_xulrunner.
|
||||||
|
function generate_app_hash {
|
||||||
|
local app_dir=$1
|
||||||
|
local md5_cmd
|
||||||
|
if command -v md5sum > /dev/null 2>&1; then
|
||||||
|
md5_cmd="md5sum"
|
||||||
|
else
|
||||||
|
md5_cmd="md5 -r"
|
||||||
|
fi
|
||||||
|
(
|
||||||
|
cd "$app_dir"
|
||||||
|
local paths=(assets build.sh config.sh scripts mac win linux modules update-packaging)
|
||||||
|
if [ -f config-custom.sh ]; then
|
||||||
|
paths+=(config-custom.sh)
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
find -L "${paths[@]}" -name '.*' -prune -o -type f -print0 | xargs -0 stat -L -f '%N|%z|%m'
|
||||||
|
else
|
||||||
|
find -L "${paths[@]}" -name '.*' -prune -o -type f -print0 | xargs -0 stat -L -c '%n|%s|%Y'
|
||||||
|
fi
|
||||||
|
cat xulrunner/hash-* 2> /dev/null || true
|
||||||
|
} | LC_ALL=C sort | $md5_cmd | awk '{print $1}'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_line {
|
||||||
|
pattern=$1
|
||||||
|
file=$2
|
||||||
|
if ! grep -E -q "$pattern" "$file"; then
|
||||||
|
echo "$pattern" not found in "$file" -- aborting 2>&1
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function replace_line {
|
||||||
|
pattern=$1
|
||||||
|
replacement=$2
|
||||||
|
file=$3
|
||||||
|
|
||||||
|
if grep -E -q "$pattern" "$file"; then
|
||||||
|
perl -pi -e "s/$pattern/$replacement/" "$file"
|
||||||
|
else
|
||||||
|
echo "$pattern" not found in "$file" -- aborting 2>&1
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_line {
|
||||||
|
pattern=$1
|
||||||
|
file=$2
|
||||||
|
|
||||||
|
if grep -E -q "$pattern" "$file"; then
|
||||||
|
grep -E -v "$pattern" "$file" > "$file.tmp"
|
||||||
|
mv "$file.tmp" "$file"
|
||||||
|
else
|
||||||
|
echo "$pattern" not found in "$file" -- aborting 2>&1
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_between {
|
||||||
|
start_pattern=$1
|
||||||
|
end_pattern=$2
|
||||||
|
file=$3
|
||||||
|
|
||||||
|
if grep -E -q "$start_pattern" "$file" && grep -E -q "$end_pattern" "$file"; then
|
||||||
|
perl -ni -e '
|
||||||
|
if (/'"$start_pattern"'/) { $skip = 1; next; }
|
||||||
|
elsif ($skip && /'"$end_pattern"'/) { $skip = 0; next; }
|
||||||
|
print unless $skip;' "$file"
|
||||||
|
else
|
||||||
|
echo "$start_pattern" and "$end_pattern" not found in "$file" -- aborting 2>&1
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set $notary_auth to notarytool authentication arguments: the keychain profile in
|
||||||
|
# NOTARIZATION_PROFILE if set, or else the Apple ID and app-specific password
|
||||||
|
function prepare_notary_auth {
|
||||||
|
if [[ -n "${NOTARIZATION_PROFILE:-}" ]]; then
|
||||||
|
notary_auth=(--keychain-profile "$NOTARIZATION_PROFILE")
|
||||||
|
if [[ -n "$KEYCHAIN" ]]; then
|
||||||
|
keychain_path="$HOME/Library/Keychains/$KEYCHAIN.keychain-db"
|
||||||
|
# The keychain may have auto-locked since signing
|
||||||
|
if [[ -n "$KEYCHAIN_PASSWORD" ]]; then
|
||||||
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$keychain_path"
|
||||||
|
fi
|
||||||
|
notary_auth+=(--keychain "$keychain_path")
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
notary_auth=(--apple-id "$NOTARIZATION_USER" --team-id "$NOTARIZATION_TEAM_ID" --password "$NOTARIZATION_PASSWORD")
|
||||||
|
fi
|
||||||
|
}
|
||||||
95
app/scripts/xulrunner_hash
Executable file
95
app/scripts/xulrunner_hash
Executable file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Calculates a hash for the processed Firefox package for a given platform and architecture
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# xulrunner_hash.sh -p <m|w|l> [-a ARCH]
|
||||||
|
#
|
||||||
|
# * **Mac (m)** ‑a is disallowed (universal build).
|
||||||
|
# * **Windows (w)** ‑a is **required**. Accepted values:
|
||||||
|
# win32 | x64 | arm64
|
||||||
|
# * **Linux (l)** ‑a is **required**. Accepted values:
|
||||||
|
# x86_64 | arm64 (alias x64 → x86_64)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
cd "$APP_ROOT_DIR"
|
||||||
|
|
||||||
|
platform=""; arch=""
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat >&2 <<'DONE'
|
||||||
|
Usage: xulrunner_hash.sh -p <m|w|l> [-a ARCH]
|
||||||
|
|
||||||
|
-p PLATFORM m (mac), w (windows), l (linux) [required]
|
||||||
|
-a ARCH *required* for Windows & Linux builds
|
||||||
|
Windows: x64 | arm64 | win32
|
||||||
|
Linux: x64 (or x86_64) | arm64
|
||||||
|
Mac: disallowed – always universal
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
while getopts ':p:a:' opt; do
|
||||||
|
case $opt in
|
||||||
|
p) platform="$OPTARG";;
|
||||||
|
a) arch="$OPTARG";;
|
||||||
|
:) echo "Option -$OPTARG requires an argument" >&2; usage;;
|
||||||
|
? ) echo "Invalid option: -$OPTARG" >&2; echo; usage;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -z $platform ]] && { echo "-p is required" >&2; echo; usage; }
|
||||||
|
|
||||||
|
case $platform in
|
||||||
|
m)
|
||||||
|
[[ -n $arch ]] && { echo "-a is not allowed for Mac (universal build)" >&2; echo; usage; }
|
||||||
|
arch="universal"
|
||||||
|
GECKO_VERSION="$GECKO_VERSION_MAC"
|
||||||
|
;;
|
||||||
|
w)
|
||||||
|
[[ -z $arch ]] && { echo "-a is required for Windows builds" >&2; echo; usage; }
|
||||||
|
# Map CLI-friendly aliases → canonical form
|
||||||
|
case $arch in
|
||||||
|
x64) arch="win-x64" ;;
|
||||||
|
arm64) arch="win-arm64" ;;
|
||||||
|
win32|win-x64|win-arm64) ;; # already canonical
|
||||||
|
*) echo "Invalid Windows arch: $arch" >&2; echo; usage;;
|
||||||
|
esac
|
||||||
|
GECKO_VERSION="$GECKO_VERSION_WIN"
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
[[ -z $arch ]] && { echo "-a is required for Linux builds" >&2; echo; usage; }
|
||||||
|
[[ $arch == x64 ]] && arch="x86_64"
|
||||||
|
case $arch in
|
||||||
|
x86_64|arm64) ;;
|
||||||
|
*) echo "Invalid Linux arch: $arch" >&2; echo; usage;;
|
||||||
|
esac
|
||||||
|
GECKO_VERSION="$GECKO_VERSION_LINUX"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid platform: $platform" >&2; echo; usage;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Concatenate scripts that affect the build
|
||||||
|
xulrunner_content=$(< "$SCRIPT_DIR/fetch_xulrunner")
|
||||||
|
xulrunner_content+=$(< "$SCRIPT_DIR/utils.sh")
|
||||||
|
xulrunner_content+=$(< "$APP_ROOT_DIR/assets/multilocale.txt")
|
||||||
|
|
||||||
|
# Get custom components hash
|
||||||
|
if [[ $platform = "m" ]]; then
|
||||||
|
components_hash="$custom_components_hash_mac"
|
||||||
|
else
|
||||||
|
hash_arch_name="${arch/-/_}"
|
||||||
|
arch_var_name="custom_components_hash_${hash_arch_name}"
|
||||||
|
components_hash=${!arch_var_name:-}
|
||||||
|
fi
|
||||||
|
|
||||||
|
input_string="${platform}-${arch}-${components_hash}|${GECKO_VERSION}|${xulrunner_content}"
|
||||||
|
|
||||||
|
|
||||||
|
printf "%s" "$input_string" | openssl dgst -sha256 | awk '{print $NF}'
|
||||||
411
app/update-packaging/build_autoupdate.sh
Executable file
411
app/update-packaging/build_autoupdate.sh
Executable file
|
|
@ -0,0 +1,411 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
UPDATE_STAGE_DIR="$SCRIPT_DIR/staging"
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat >&2 <<DONE
|
||||||
|
Usage: $0 -c CHANNEL [-f] [-i FROM_VERSION] [-p PLATFORMS] [-l] VERSION
|
||||||
|
Options
|
||||||
|
-c CHANNEL Release channel ('release', 'beta')
|
||||||
|
-f Perform full build
|
||||||
|
-i FROM_VERSION Perform incremental build
|
||||||
|
-p PLATFORMS Platforms to build (m=Mac, w=Windows, l=Linux)
|
||||||
|
-l Use local TO directory instead of downloading TO files from S3
|
||||||
|
DONE
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# From https://gist.github.com/cdown/1163649#gistcomment-1639097
|
||||||
|
urlencode() {
|
||||||
|
local LANG=C
|
||||||
|
local length="${#1}"
|
||||||
|
for (( i = 0; i < length; i++ )); do
|
||||||
|
local c="${1:i:1}"
|
||||||
|
case $c in
|
||||||
|
[a-zA-Z0-9.~_-]) printf "$c" ;;
|
||||||
|
*) printf '%%%02X' "'$c" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_FULL=0
|
||||||
|
BUILD_INCREMENTAL=0
|
||||||
|
FROM=""
|
||||||
|
CHANNEL=""
|
||||||
|
BUILD_MAC=0
|
||||||
|
BUILD_WIN=0
|
||||||
|
BUILD_LINUX=0
|
||||||
|
USE_LOCAL_TO=0
|
||||||
|
while getopts "i:c:p:fl" opt; do
|
||||||
|
case $opt in
|
||||||
|
i)
|
||||||
|
FROM="$OPTARG"
|
||||||
|
BUILD_INCREMENTAL=1
|
||||||
|
;;
|
||||||
|
c)
|
||||||
|
CHANNEL="$OPTARG"
|
||||||
|
;;
|
||||||
|
p)
|
||||||
|
for i in `seq 0 1 $((${#OPTARG}-1))`
|
||||||
|
do
|
||||||
|
case ${OPTARG:i:1} in
|
||||||
|
m) BUILD_MAC=1;;
|
||||||
|
w) BUILD_WIN=1;;
|
||||||
|
l) BUILD_LINUX=1;;
|
||||||
|
*)
|
||||||
|
echo "$0: Invalid platform option ${OPTARG:i:1}"
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
f)
|
||||||
|
BUILD_FULL=1
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
USE_LOCAL_TO=1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift $((OPTIND-1)); OPTIND=1
|
||||||
|
done
|
||||||
|
|
||||||
|
shift $(($OPTIND - 1))
|
||||||
|
TO=${1:-}
|
||||||
|
|
||||||
|
if [ -z "$TO" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$FROM" ] && [ $BUILD_FULL -eq 0 ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$CHANNEL" ]]; then
|
||||||
|
echo "Channel not provided" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Require at least one platform
|
||||||
|
if [[ $BUILD_MAC == 0 ]] && [[ $BUILD_WIN == 0 ]] && [[ $BUILD_LINUX == 0 ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
TO_MAJOR_VERSION="${TO%%.*}"
|
||||||
|
|
||||||
|
rm -rf "$UPDATE_STAGE_DIR"
|
||||||
|
mkdir "$UPDATE_STAGE_DIR"
|
||||||
|
|
||||||
|
INCREMENTALS_FOUND=0
|
||||||
|
for version in "$FROM" "$TO"; do
|
||||||
|
if [[ $version == "$TO" ]] && [[ $INCREMENTALS_FOUND == 0 ]] && [[ $BUILD_FULL == 0 ]]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Getting Zotero version $version"
|
||||||
|
|
||||||
|
versiondir="$UPDATE_STAGE_DIR/$version"
|
||||||
|
|
||||||
|
#
|
||||||
|
# If -l passed, use main build script's staging directory for TO files rather than downloading
|
||||||
|
# the given version.
|
||||||
|
#
|
||||||
|
# The caller must ensure that the files in ../staging match the platforms and version given.
|
||||||
|
if [[ $version == $TO && $USE_LOCAL_TO == "1" ]]; then
|
||||||
|
if [ ! -d "$STAGE_DIR" ]; then
|
||||||
|
echo "Can't find local TO dir $STAGE_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Using files from $STAGE_DIR"
|
||||||
|
ln -s "$STAGE_DIR" "$versiondir"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Otherwise, download version from S3
|
||||||
|
#
|
||||||
|
mkdir -p "$versiondir"
|
||||||
|
cd "$versiondir"
|
||||||
|
|
||||||
|
# Determine Linux archive extension by major Zotero version
|
||||||
|
MAJOR_VERSION="${version%%.*}"
|
||||||
|
if [ "$MAJOR_VERSION" -lt 8 ]; then
|
||||||
|
LINUX_EXT="tar.bz2"
|
||||||
|
else
|
||||||
|
LINUX_EXT="tar.xz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAC_ARCHIVE="Zotero-${version}.dmg"
|
||||||
|
WIN32_ARCHIVE="Zotero-${version}_win32.zip"
|
||||||
|
WIN_X64_ARCHIVE="Zotero-${version}_win-x64.zip"
|
||||||
|
WIN_ARM64_ARCHIVE="Zotero-${version}_win-arm64.zip"
|
||||||
|
LINUX_X86_ARCHIVE="Zotero-${version}_linux-i686.${LINUX_EXT}"
|
||||||
|
LINUX_X86_64_ARCHIVE="Zotero-${version}_linux-x86_64.${LINUX_EXT}"
|
||||||
|
LINUX_ARM64_ARCHIVE="Zotero-${version}_linux-arm64.${LINUX_EXT}"
|
||||||
|
|
||||||
|
CACHE_DIR="$ROOT_DIR/cache"
|
||||||
|
if [ ! -e "$CACHE_DIR" ]; then
|
||||||
|
mkdir "$CACHE_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build archive list (no Linux arm64 before Zotero 8, no Linux i686 from Zotero 11)
|
||||||
|
ARCHIVES=(
|
||||||
|
"$MAC_ARCHIVE"
|
||||||
|
"$WIN32_ARCHIVE"
|
||||||
|
"$WIN_X64_ARCHIVE"
|
||||||
|
"$WIN_ARM64_ARCHIVE"
|
||||||
|
"$LINUX_X86_64_ARCHIVE"
|
||||||
|
)
|
||||||
|
if [ "$TO_MAJOR_VERSION" -lt 11 ]; then
|
||||||
|
ARCHIVES+=("$LINUX_X86_ARCHIVE")
|
||||||
|
fi
|
||||||
|
if [ "$MAJOR_VERSION" -ge 8 ]; then
|
||||||
|
ARCHIVES+=("$LINUX_ARM64_ARCHIVE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
for archive in "${ARCHIVES[@]}"; do
|
||||||
|
if [[ $archive = "$MAC_ARCHIVE" ]] && [[ $BUILD_MAC != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $archive = "$WIN32_ARCHIVE" ]] && [[ $BUILD_WIN != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $archive = "$WIN_X64_ARCHIVE" ]] && [[ $BUILD_WIN != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $archive = "$WIN_ARM64_ARCHIVE" ]] && [[ $BUILD_WIN != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $archive = "$LINUX_X86_ARCHIVE" ]] && [[ $BUILD_LINUX != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $archive = "$LINUX_X86_64_ARCHIVE" ]] && [[ $BUILD_LINUX != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $archive = "$LINUX_ARM64_ARCHIVE" ]] && [[ $BUILD_LINUX != 1 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
ETAG_FILE="$CACHE_DIR/$archive.etag"
|
||||||
|
|
||||||
|
# Check cache for archive
|
||||||
|
if [[ -f "$CACHE_DIR/$archive" ]] && [[ -f "$CACHE_DIR/$archive.etag" ]]; then
|
||||||
|
ETAG="`cat $ETAG_FILE | tr '\n' ' '`"
|
||||||
|
else
|
||||||
|
ETAG=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f $archive
|
||||||
|
# URL-encode '+' in beta version numbers
|
||||||
|
ENCODED_VERSION=`urlencode $version`
|
||||||
|
ENCODED_ARCHIVE=`urlencode $archive`
|
||||||
|
URL="https://$S3_BUCKET.s3.amazonaws.com/$S3_DIST_PATH/$CHANNEL/$ENCODED_VERSION/$ENCODED_ARCHIVE"
|
||||||
|
echo "Fetching $URL"
|
||||||
|
set +e
|
||||||
|
# Cached version is available
|
||||||
|
if [ -n "$ETAG" ]; then
|
||||||
|
HTTP_CODE=$(curl -sS -L -D headers.txt -o $archive -w '%{http_code}' -H "If-None-Match: $ETAG" "$URL")
|
||||||
|
NEW_ETAG=$(awk 'tolower($1) == "etag:" {print $2}' headers.txt | tr -d '\r' | tail -n 1)
|
||||||
|
rm -f headers.txt
|
||||||
|
|
||||||
|
# If ETag didn't match, cache newly downloaded version
|
||||||
|
if [ "$HTTP_CODE" = 200 ]; then
|
||||||
|
echo "ETag for $archive didn't match! -- using new version"
|
||||||
|
rm -f "$CACHE_DIR/$archive.etag"
|
||||||
|
cp $archive "$CACHE_DIR/"
|
||||||
|
echo "$NEW_ETAG" > "$CACHE_DIR/$archive.etag"
|
||||||
|
# If ETag matched (or there was another error), use cached version
|
||||||
|
else
|
||||||
|
echo "Using cached $archive"
|
||||||
|
cp "$CACHE_DIR/$archive" .
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
curl -sS -f -L -D headers.txt -o $archive "$URL"
|
||||||
|
NEW_ETAG=$(awk 'tolower($1) == "etag:" {print $2}' headers.txt | tr -d '\r' | tail -n 1)
|
||||||
|
rm -f headers.txt
|
||||||
|
|
||||||
|
# Save archive to cache
|
||||||
|
rm -f "$CACHE_DIR/$archive.etag"
|
||||||
|
cp $archive "$CACHE_DIR/"
|
||||||
|
echo "$NEW_ETAG" > "$CACHE_DIR/$archive.etag"
|
||||||
|
fi
|
||||||
|
set -e
|
||||||
|
done
|
||||||
|
|
||||||
|
# Delete cached archives older than 14 days
|
||||||
|
find "$CACHE_DIR" -maxdepth 1 -type f -ctime +14 -delete
|
||||||
|
# Delete cached diffs and compressed files not created or used in 60 days
|
||||||
|
# (cache hits touch the entries)
|
||||||
|
if [ -d "$CACHE_DIR/update-packaging" ]; then
|
||||||
|
find "$CACHE_DIR/update-packaging" -type f -ctime +60 -delete
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unpack Zotero.app
|
||||||
|
if [ $BUILD_MAC == 1 ]; then
|
||||||
|
if [ -f "$MAC_ARCHIVE" ]; then
|
||||||
|
set +e
|
||||||
|
hdiutil detach -quiet /Volumes/Zotero 2>/dev/null
|
||||||
|
set -e
|
||||||
|
hdiutil attach -quiet "$MAC_ARCHIVE"
|
||||||
|
cp -R /Volumes/Zotero/Zotero.app "$versiondir"
|
||||||
|
rm "$MAC_ARCHIVE"
|
||||||
|
hdiutil detach -quiet /Volumes/Zotero
|
||||||
|
INCREMENTALS_FOUND=1
|
||||||
|
else
|
||||||
|
echo "$MAC_ARCHIVE not found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unpack Windows zips
|
||||||
|
if [ $BUILD_WIN == 1 ]; then
|
||||||
|
if [[ -f "$WIN32_ARCHIVE" ]] && [[ -f "$WIN_X64_ARCHIVE" ]] && [[ -f "$WIN_ARM64_ARCHIVE" ]]; then
|
||||||
|
# Unpack architectures in parallel
|
||||||
|
UNPACK_PIDS=""
|
||||||
|
for build in "$WIN32_ARCHIVE" "$WIN_X64_ARCHIVE" "$WIN_ARM64_ARCHIVE"; do
|
||||||
|
(unzip -q "$build" && rm "$build") &
|
||||||
|
UNPACK_PIDS="$UNPACK_PIDS $!"
|
||||||
|
done
|
||||||
|
for pid in $UNPACK_PIDS; do
|
||||||
|
wait $pid
|
||||||
|
done
|
||||||
|
INCREMENTALS_FOUND=1
|
||||||
|
else
|
||||||
|
echo "$WIN32_ARCHIVE/$WIN_X64_ARCHIVE/$WIN_ARM64_ARCHIVE not found"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Unpack Linux tarballs
|
||||||
|
if [ $BUILD_LINUX == 1 ]; then
|
||||||
|
# Zotero 7 has no Linux arm64 build; Zotero 11 has no Linux i686 build
|
||||||
|
LINUX_BUILDS_TO_UNPACK=("$LINUX_X86_64_ARCHIVE")
|
||||||
|
if [ "$TO_MAJOR_VERSION" -lt 11 ]; then
|
||||||
|
LINUX_BUILDS_TO_UNPACK+=("$LINUX_X86_ARCHIVE")
|
||||||
|
fi
|
||||||
|
if [ "$MAJOR_VERSION" -ge 8 ]; then
|
||||||
|
LINUX_BUILDS_TO_UNPACK+=("$LINUX_ARM64_ARCHIVE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
MISSING=0
|
||||||
|
for build in "${LINUX_BUILDS_TO_UNPACK[@]}"; do
|
||||||
|
if [ ! -f "$build" ]; then
|
||||||
|
MISSING=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$MISSING" -eq 0 ]; then
|
||||||
|
# Unpack architectures in parallel
|
||||||
|
UNPACK_PIDS=""
|
||||||
|
for build in "${LINUX_BUILDS_TO_UNPACK[@]}"; do
|
||||||
|
(tar -xf "$build" && rm "$build") &
|
||||||
|
UNPACK_PIDS="$UNPACK_PIDS $!"
|
||||||
|
done
|
||||||
|
for pid in $UNPACK_PIDS; do
|
||||||
|
wait $pid
|
||||||
|
done
|
||||||
|
INCREMENTALS_FOUND=1
|
||||||
|
else
|
||||||
|
echo "Linux tarballs not found: ${LINUX_BUILDS_TO_UNPACK[*]}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
|
||||||
|
# Set variables for mar command in make_(incremental|full)_update.sh
|
||||||
|
export MOZ_PRODUCT_VERSION="$TO"
|
||||||
|
export MAR_CHANNEL_ID="$CHANNEL"
|
||||||
|
|
||||||
|
# Reuse diffs and compressed files across incremental builds, since FROM
|
||||||
|
# versions often share files with each other and with the TO version. Entries
|
||||||
|
# that haven't been used recently are cleaned up above.
|
||||||
|
export UPDATE_CACHE_DIR="$ROOT_DIR/cache/update-packaging"
|
||||||
|
|
||||||
|
CHANGES_MADE=0
|
||||||
|
for build in "mac" "win32" "win-x64" "win-arm64" "linux-i686" "linux-x86_64" "linux-arm64"; do
|
||||||
|
# Zotero 7 has no Linux arm64 builds
|
||||||
|
if [[ $build == "linux-arm64" ]] && [[ $FROM == 7.* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Zotero 11 has no Linux i686 builds, so there's nothing to update to
|
||||||
|
if [[ $build == "linux-i686" ]] && [[ $TO_MAJOR_VERSION -ge 11 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $build == "mac" ]]; then
|
||||||
|
if [[ $BUILD_MAC == 0 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
dir="Zotero.app"
|
||||||
|
else
|
||||||
|
if ([[ $build == "win32" ]] || [[ $build == "win-x64" ]] || [[ $build == "win-arm64" ]]) && [[ $BUILD_WIN == 0 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ([[ $build == "linux-i686" ]] || [[ $build == "linux-x86_64" ]] || [[ $build == "linux-arm64" ]]) && [[ $BUILD_LINUX == 0 ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
dir="Zotero_$build"
|
||||||
|
fi
|
||||||
|
if [[ $BUILD_INCREMENTAL == 1 ]] && [[ -d "$UPDATE_STAGE_DIR/$FROM/$dir" ]]; then
|
||||||
|
echo
|
||||||
|
echo "Building incremental $build update from $FROM to $TO"
|
||||||
|
"$SCRIPT_DIR/make_incremental_update.sh" "$DIST_DIR/Zotero-${TO}-${FROM}_$build.mar" "$UPDATE_STAGE_DIR/$FROM/$dir" "$UPDATE_STAGE_DIR/$TO/$dir"
|
||||||
|
CHANGES_MADE=1
|
||||||
|
|
||||||
|
# If it's an incremental patch from a 6.0 build, use bzip instead of xz
|
||||||
|
if [[ $FROM = 6.0* ]]; then
|
||||||
|
echo "Building bzip2 version of incremental $build update from $FROM to $TO"
|
||||||
|
"$SCRIPT_DIR/xz_to_bzip" "$DIST_DIR/Zotero-${TO}-${FROM}_$build.mar" "$DIST_DIR/Zotero-${TO}-${FROM}_${build}_bz.mar"
|
||||||
|
rm "$DIST_DIR/Zotero-${TO}-${FROM}_$build.mar"
|
||||||
|
mv "$DIST_DIR/Zotero-${TO}-${FROM}_${build}_bz.mar" "$DIST_DIR/Zotero-${TO}-${FROM}_$build.mar"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ $BUILD_FULL == 1 ]]; then
|
||||||
|
echo
|
||||||
|
echo "Building full $build update for $TO"
|
||||||
|
"$SCRIPT_DIR/make_full_update.sh" "$DIST_DIR/Zotero-${TO}-full_$build.mar" "$UPDATE_STAGE_DIR/$TO/$dir"
|
||||||
|
CHANGES_MADE=1
|
||||||
|
|
||||||
|
# Make a bzip version of all complete patches for serving to <7.0 builds. Don't bother with
|
||||||
|
# architectures that didn't exist in Z6.
|
||||||
|
#
|
||||||
|
# We can stop this once we do a waterfall build that all older versions get updated to.
|
||||||
|
if [[ $build != "win-x64" ]] && [[ $build != "win-arm64" ]]; then
|
||||||
|
echo "Building bzip2 version of full $build update for $TO"
|
||||||
|
"$SCRIPT_DIR/xz_to_bzip" "$DIST_DIR/Zotero-${TO}-full_$build.mar" "$DIST_DIR/Zotero-${TO}-full_bz_${build}.mar"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf "$UPDATE_STAGE_DIR"
|
||||||
|
|
||||||
|
# Update file manifests
|
||||||
|
if [ $CHANGES_MADE -eq 1 ]; then
|
||||||
|
# Cygwin has sha512sum, macOS has shasum, Linux has both
|
||||||
|
if [[ -n "`which sha512sum 2> /dev/null`" ]]; then
|
||||||
|
SHACMD="sha512sum"
|
||||||
|
else
|
||||||
|
SHACMD="shasum -a 512"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$DIST_DIR"
|
||||||
|
for platform in "mac" "win" "linux"; do
|
||||||
|
file=files-$platform
|
||||||
|
rm -f $file
|
||||||
|
for fn in `find . -name "*$platform*.mar" -exec basename {} \;`; do
|
||||||
|
size=`wc -c "$fn" | awk '{print $1}'`
|
||||||
|
hash=`$SHACMD "$fn" | awk '{print $1}'`
|
||||||
|
echo $fn $hash $size >> $file
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
450
app/update-packaging/common.sh
Normal file
450
app/update-packaging/common.sh
Normal file
|
|
@ -0,0 +1,450 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#
|
||||||
|
# Code shared by update packaging scripts.
|
||||||
|
# Author: Darin Fisher
|
||||||
|
#
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Preserve a value set by the parent so it survives in the child processes
|
||||||
|
# spawned by run_parallel_tasks()
|
||||||
|
QUIET=${QUIET:-0}
|
||||||
|
|
||||||
|
# By default just assume that these tools exist on our path
|
||||||
|
MAR=${MAR:-mar}
|
||||||
|
MBSDIFF=${MBSDIFF:-mbsdiff}
|
||||||
|
XZ=${XZ:-xz}
|
||||||
|
$XZ --version > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
# If $XZ is not set and not found on the path then this is probably
|
||||||
|
# running on a windows buildbot. Some of the Windows build systems have
|
||||||
|
# xz.exe in topsrcdir/xz/. Look in the places this would be in both a
|
||||||
|
# mozilla-central and comm-central build.
|
||||||
|
XZ="$(dirname "$(dirname "$(dirname "$0")")")/xz/xz.exe"
|
||||||
|
$XZ --version > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
XZ="$(dirname "$(dirname "$(dirname "$(dirname "$0")")")")/xz/xz.exe"
|
||||||
|
$XZ --version > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "xz was not found on this system!"
|
||||||
|
echo "exiting"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Ensure that we're always using the right compression settings.
|
||||||
|
# -T1 (single-threaded) is required: multi-threaded xz produces non-deterministic
|
||||||
|
# output, which would break both the reproducibility of MARs and the content-hash
|
||||||
|
# cache in process_update_task(). See get_cache_tag() for how changes here are
|
||||||
|
# accounted for in the cache.
|
||||||
|
export XZ_OPT="-T1 -7e"
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Helper routines
|
||||||
|
|
||||||
|
notice() {
|
||||||
|
echo "$*" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
verbose_notice() {
|
||||||
|
if [ $QUIET -eq 0 ]; then
|
||||||
|
notice "$*"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_file_size() {
|
||||||
|
info=($(ls -ln "$1"))
|
||||||
|
echo ${info[4]}
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_perm() {
|
||||||
|
reference="$1"
|
||||||
|
target="$2"
|
||||||
|
|
||||||
|
if [ -x "$reference" ]; then
|
||||||
|
chmod 0755 "$target"
|
||||||
|
else
|
||||||
|
chmod 0644 "$target"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
make_add_instruction() {
|
||||||
|
f="$1"
|
||||||
|
filev3="$2"
|
||||||
|
|
||||||
|
# Used to log to the console
|
||||||
|
if [ $4 ]; then
|
||||||
|
forced=" (forced)"
|
||||||
|
else
|
||||||
|
forced=
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Changed by Zotero for -e
|
||||||
|
is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/') || true
|
||||||
|
if [ $is_extension = "1" ]; then
|
||||||
|
# Use the subdirectory of the extensions folder as the file to test
|
||||||
|
# before performing this add instruction.
|
||||||
|
testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
|
||||||
|
verbose_notice " add-if \"$testdir\" \"$f\""
|
||||||
|
echo "add-if \"$testdir\" \"$f\"" >> "$filev3"
|
||||||
|
else
|
||||||
|
verbose_notice " add \"$f\"$forced"
|
||||||
|
echo "add \"$f\"" >> "$filev3"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_for_add_if_not_update() {
|
||||||
|
add_if_not_file_chk="$1"
|
||||||
|
|
||||||
|
if [[ "$(basename "$add_if_not_file_chk")" = "channel-prefs.js" || \
|
||||||
|
"$add_if_not_file_chk" =~ (^|/)ChannelPrefs\.framework/ || \
|
||||||
|
"$(basename "$add_if_not_file_chk")" = "update-settings.ini" || \
|
||||||
|
"$add_if_not_file_chk" =~ (^|/)UpdateSettings\.framework/ ]]; then
|
||||||
|
## "true"
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
## "false"
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
make_add_if_not_instruction() {
|
||||||
|
f="$1"
|
||||||
|
filev3="$2"
|
||||||
|
|
||||||
|
verbose_notice " add-if-not \"$f\" \"$f\""
|
||||||
|
echo "add-if-not \"$f\" \"$f\"" >> "$filev3"
|
||||||
|
}
|
||||||
|
|
||||||
|
make_patch_instruction() {
|
||||||
|
f="$1"
|
||||||
|
filev3="$2"
|
||||||
|
|
||||||
|
# Changed by Zotero for -e
|
||||||
|
is_extension=$(echo "$f" | grep -c 'distribution/extensions/.*/') || true
|
||||||
|
if [ $is_extension = "1" ]; then
|
||||||
|
# Use the subdirectory of the extensions folder as the file to test
|
||||||
|
# before performing this add instruction.
|
||||||
|
testdir=$(echo "$f" | sed 's/\(.*distribution\/extensions\/[^\/]*\)\/.*/\1/')
|
||||||
|
verbose_notice " patch-if \"$testdir\" \"$f.patch\" \"$f\""
|
||||||
|
echo "patch-if \"$testdir\" \"$f.patch\" \"$f\"" >> "$filev3"
|
||||||
|
else
|
||||||
|
verbose_notice " patch \"$f.patch\" \"$f\""
|
||||||
|
echo "patch \"$f.patch\" \"$f\"" >> "$filev3"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
append_remove_instructions() {
|
||||||
|
dir="$1"
|
||||||
|
filev3="$2"
|
||||||
|
|
||||||
|
if [ -f "$dir/removed-files" ]; then
|
||||||
|
listfile="$dir/removed-files"
|
||||||
|
elif [ -f "$dir/Contents/Resources/removed-files" ]; then
|
||||||
|
listfile="$dir/Contents/Resources/removed-files"
|
||||||
|
fi
|
||||||
|
if [ -n "$listfile" ]; then
|
||||||
|
# Changed by Zotero: Use subshell and disable filename globbing to prevent bash from expanding
|
||||||
|
# entries in removed-files with paths from the root (e.g., 'xulrunner/*')
|
||||||
|
(
|
||||||
|
set -f
|
||||||
|
# Map spaces to pipes so that we correctly handle filenames with spaces.
|
||||||
|
files=($(cat "$listfile" | tr " " "|" | sort -r))
|
||||||
|
num_files=${#files[*]}
|
||||||
|
for ((i=0; $i<$num_files; i=$i+1)); do
|
||||||
|
# Map pipes back to whitespace and remove carriage returns
|
||||||
|
f=$(echo ${files[$i]} | tr "|" " " | tr -d '\r')
|
||||||
|
# Trim whitespace
|
||||||
|
f=$(echo $f)
|
||||||
|
# Exclude blank lines.
|
||||||
|
if [ -n "$f" ]; then
|
||||||
|
# Exclude comments
|
||||||
|
if [ ! $(echo "$f" | grep -c '^#') = 1 ]; then
|
||||||
|
if [ $(echo "$f" | grep -c '/$') = 1 ]; then
|
||||||
|
verbose_notice " rmdir \"$f\""
|
||||||
|
echo "rmdir \"$f\"" >> "$filev3"
|
||||||
|
elif [ $(echo "$f" | grep -c '/\*$') = 1 ]; then
|
||||||
|
# Remove the *
|
||||||
|
f=$(echo "$f" | sed -e 's:\*$::')
|
||||||
|
verbose_notice " rmrfdir \"$f\""
|
||||||
|
echo "rmrfdir \"$f\"" >> "$filev3"
|
||||||
|
else
|
||||||
|
verbose_notice " remove \"$f\""
|
||||||
|
echo "remove \"$f\"" >> "$filev3"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return the number of parallel jobs to use for diffing/compression, from
|
||||||
|
# UPDATE_PACKAGING_JOBS or the number of cores
|
||||||
|
get_parallel_jobs() {
|
||||||
|
if [ -n "${UPDATE_PACKAGING_JOBS:-}" ]; then
|
||||||
|
echo "$UPDATE_PACKAGING_JOBS"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
nproc 2>/dev/null && return 0
|
||||||
|
sysctl -n hw.ncpu 2>/dev/null && return 0
|
||||||
|
echo 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run per-file tasks from a task file in parallel by re-invoking the calling
|
||||||
|
# script with --run-task for each line. Tasks are ordered largest-file-first so
|
||||||
|
# that long-running jobs (e.g., diffing xul) start as early as possible.
|
||||||
|
#
|
||||||
|
# $1 - task file, with one "<type><TAB><relative path>" task per line
|
||||||
|
# $2 - directory to measure file sizes against for job ordering
|
||||||
|
# $3 - script to re-invoke (callers pass "$0" and handle --run-task before
|
||||||
|
# option parsing by calling process_update_task)
|
||||||
|
#
|
||||||
|
# Callers must export the variables needed by process_update_task().
|
||||||
|
run_parallel_tasks() {
|
||||||
|
local taskfile="$1"
|
||||||
|
local basedir="$2"
|
||||||
|
local script="$3"
|
||||||
|
local jobs
|
||||||
|
|
||||||
|
if [ ! -s "$taskfile" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# xargs requires a resolvable command path
|
||||||
|
script="$(cd "$(dirname "$script")" && pwd)/$(basename "$script")"
|
||||||
|
|
||||||
|
# Compute the cache tag once here and export it so the per-file child
|
||||||
|
# processes inherit it rather than recomputing it for every file
|
||||||
|
if [ -n "${UPDATE_CACHE_DIR:-}" ] && [ -z "${UPDATE_CACHE_TAG:-}" ]; then
|
||||||
|
UPDATE_CACHE_TAG="$(get_cache_tag)"
|
||||||
|
export UPDATE_CACHE_TAG
|
||||||
|
fi
|
||||||
|
|
||||||
|
jobs=$(get_parallel_jobs)
|
||||||
|
notice "Processing $(wc -l < "$taskfile" | tr -d ' ') files with $jobs parallel jobs"
|
||||||
|
|
||||||
|
(cd "$basedir" && du -ak .) > "$taskfile.sizes"
|
||||||
|
awk -F'\t' 'NR==FNR { sizes[substr($2, 3)] = $1; next } { print sizes[$2] "\t" $0 }' \
|
||||||
|
"$taskfile.sizes" "$taskfile" \
|
||||||
|
| sort -rn \
|
||||||
|
| cut -f 2- \
|
||||||
|
| tr '\n' '\000' \
|
||||||
|
| xargs -0 -n 1 -P "$jobs" "$script" --run-task
|
||||||
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Diff and compression cache
|
||||||
|
#
|
||||||
|
# Building updates repeats the same expensive work: the same file contents get
|
||||||
|
# xz-compressed once per architecture, per FROM version, and per release, and
|
||||||
|
# the same before/after file pair gets binary-diffed again and again. When
|
||||||
|
# UPDATE_CACHE_DIR is set, we cache the results by content hash and reuse them
|
||||||
|
# across builds. Two kinds of entry are stored:
|
||||||
|
#
|
||||||
|
# full-<tag>-<hash>.xz A single file compressed with xz, keyed
|
||||||
|
# on the file's contents. Reused whenever
|
||||||
|
# the same content shows up again, in any
|
||||||
|
# architecture, version, or release.
|
||||||
|
#
|
||||||
|
# patch-<tag>-<oldhash>-<newhash>.xz The compressed binary diff between a
|
||||||
|
# file's old and new contents, keyed on
|
||||||
|
# both. Reused whenever the same
|
||||||
|
# before/after pair recurs (e.g., a file
|
||||||
|
# unchanged across several FROM versions
|
||||||
|
# being patched to the same TO).
|
||||||
|
#
|
||||||
|
# Both entries are written even when only one is ultimately packaged, so a file
|
||||||
|
# that loses the patch-vs-full size comparison in one build still seeds the
|
||||||
|
# cache for the next. <tag> is get_cache_tag(), so a toolchain/settings change
|
||||||
|
# starts a fresh namespace rather than reusing stale output. Entries are touched
|
||||||
|
# on use and expire via the time-based cleanup in build_autoupdate.sh.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Print a SHA-256 content hash to use as a cache key
|
||||||
|
hash_file() {
|
||||||
|
if command -v sha256sum > /dev/null 2>&1; then
|
||||||
|
sha256sum "$1" | awk '{print $1}'
|
||||||
|
else
|
||||||
|
shasum -a 256 "$1" | awk '{print $1}'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print a SHA-256 hash of stdin
|
||||||
|
hash_stdin() {
|
||||||
|
if command -v sha256sum > /dev/null 2>&1; then
|
||||||
|
sha256sum | awk '{print $1}'
|
||||||
|
else
|
||||||
|
shasum -a 256 | awk '{print $1}'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print a short tag identifying the toolchain and options that produce cached
|
||||||
|
# files, so that entries are invalidated when any of them change. The cache
|
||||||
|
# keys files by input content only, on the assumption that the same inputs
|
||||||
|
# always compress/diff to the same output; this tag makes that assumption hold
|
||||||
|
# across xz/mbsdiff upgrades and XZ_OPT/BCJ_OPTIONS changes. (A change to any
|
||||||
|
# input invalidates both the full and patch caches, which is more than strictly
|
||||||
|
# necessary but keeps this simple; a stale build is just a cold rebuild.)
|
||||||
|
# Stale-tag entries are removed by the time-based cleanup in build_autoupdate.sh.
|
||||||
|
get_cache_tag() {
|
||||||
|
local mbsdiff_bin
|
||||||
|
mbsdiff_bin="$(command -v "$MBSDIFF" 2>/dev/null)"
|
||||||
|
{
|
||||||
|
$XZ --version 2>/dev/null | head -1
|
||||||
|
echo "XZ_OPT=$XZ_OPT"
|
||||||
|
echo "BCJ_OPTIONS=${BCJ_OPTIONS:-}"
|
||||||
|
# mbsdiff has no --version, so identify it by its binary contents
|
||||||
|
if [ -n "$mbsdiff_bin" ]; then
|
||||||
|
hash_file "$mbsdiff_bin"
|
||||||
|
else
|
||||||
|
echo "MBSDIFF=$MBSDIFF"
|
||||||
|
fi
|
||||||
|
} | hash_stdin | cut -c 1-16
|
||||||
|
}
|
||||||
|
|
||||||
|
# Atomically store file $2 in the cache as $1
|
||||||
|
cache_store() {
|
||||||
|
mkdir -p "$(dirname "$1")"
|
||||||
|
cp "$2" "$1.tmp.$$" && mv -f "$1.tmp.$$" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# xz-compress $1 to $2, reusing a cached result when one exists (see the cache
|
||||||
|
# overview above)
|
||||||
|
compress_full_file() {
|
||||||
|
local src="$1"
|
||||||
|
local dest="$2"
|
||||||
|
local key=""
|
||||||
|
|
||||||
|
if [ -n "${UPDATE_CACHE_DIR:-}" ]; then
|
||||||
|
key="$UPDATE_CACHE_DIR/full-${UPDATE_CACHE_TAG:-}-$(hash_file "$src").xz"
|
||||||
|
if [ -f "$key" ]; then
|
||||||
|
# Keep entries that are still in use from expiring
|
||||||
|
touch -c "$key" 2>/dev/null || true
|
||||||
|
cp "$key" "$dest"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
$XZ $XZ_OPT --compress $BCJ_OPTIONS --lzma2 --format=xz --check=crc64 --force --stdout "$src" > "$dest"
|
||||||
|
|
||||||
|
if [ -n "$key" ]; then
|
||||||
|
cache_store "$key" "$dest"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process a single task line from run_parallel_tasks():
|
||||||
|
#
|
||||||
|
# full - compress the new file into the work directory
|
||||||
|
# diff - if the file changed, generate a binary diff and keep the smaller of
|
||||||
|
# the compressed patch ($f.patch) and the compressed file ($f)
|
||||||
|
#
|
||||||
|
# Expects newdir and workdir in the environment, plus olddir for diff tasks.
|
||||||
|
# The results are assembled into the manifest serially by the caller based on
|
||||||
|
# which files exist in the work directory. Diffs and compressed files are
|
||||||
|
# cached when enabled -- see the cache overview above.
|
||||||
|
process_update_task() {
|
||||||
|
local task="$1"
|
||||||
|
local tab=$(printf '\t')
|
||||||
|
local type="${task%%"$tab"*}"
|
||||||
|
local f="${task#*"$tab"}"
|
||||||
|
local oldfile_path newfile_path patch_path patchsize fullsize full_pid patchkey
|
||||||
|
|
||||||
|
if [ "$type" = "diff" ]; then
|
||||||
|
if diff "$olddir/$f" "$newdir/$f" > /dev/null; then
|
||||||
|
# Unchanged
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$workdir/$f")"
|
||||||
|
verbose_notice "diffing \"$f\""
|
||||||
|
|
||||||
|
# Compress the full new file in the background while diffing, since both
|
||||||
|
# are needed to decide which to package
|
||||||
|
compress_full_file "$newdir/$f" "$workdir/$f" &
|
||||||
|
full_pid=$!
|
||||||
|
|
||||||
|
patchkey=""
|
||||||
|
if [ -n "${UPDATE_CACHE_DIR:-}" ]; then
|
||||||
|
patchkey="$UPDATE_CACHE_DIR/patch-${UPDATE_CACHE_TAG:-}-$(hash_file "$olddir/$f")-$(hash_file "$newdir/$f").xz"
|
||||||
|
fi
|
||||||
|
if [ -n "$patchkey" ] && [ -f "$patchkey" ]; then
|
||||||
|
# Keep entries that are still in use from expiring
|
||||||
|
touch -c "$patchkey" 2>/dev/null || true
|
||||||
|
cp "$patchkey" "$workdir/$f.patch.xz"
|
||||||
|
else
|
||||||
|
# mbsdiff doesn't like POSIX paths on Windows
|
||||||
|
if [ ${WIN_NATIVE:-0} -eq 1 ]; then
|
||||||
|
oldfile_path=$(cygpath -m "$olddir/$f")
|
||||||
|
newfile_path=$(cygpath -m "$newdir/$f")
|
||||||
|
patch_path=$(cygpath -m "$workdir/$f.patch")
|
||||||
|
else
|
||||||
|
oldfile_path="$olddir/$f"
|
||||||
|
newfile_path="$newdir/$f"
|
||||||
|
patch_path="$workdir/$f.patch"
|
||||||
|
fi
|
||||||
|
$MBSDIFF "$oldfile_path" "$newfile_path" "$patch_path"
|
||||||
|
$XZ $XZ_OPT --compress --lzma2 --format=xz --check=crc64 --force "$workdir/$f.patch"
|
||||||
|
if [ -n "$patchkey" ]; then
|
||||||
|
cache_store "$patchkey" "$workdir/$f.patch.xz"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
wait $full_pid
|
||||||
|
copy_perm "$newdir/$f" "$workdir/$f"
|
||||||
|
|
||||||
|
patchsize=$(get_file_size "$workdir/$f.patch.xz")
|
||||||
|
fullsize=$(get_file_size "$workdir/$f")
|
||||||
|
|
||||||
|
if [ $patchsize -lt $fullsize ]; then
|
||||||
|
mv -f "$workdir/$f.patch.xz" "$workdir/$f.patch"
|
||||||
|
rm -f "$workdir/$f"
|
||||||
|
else
|
||||||
|
rm -f "$workdir/$f.patch.xz"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mkdir -p "$(dirname "$workdir/$f")"
|
||||||
|
compress_full_file "$newdir/$f" "$workdir/$f"
|
||||||
|
copy_perm "$newdir/$f" "$workdir/$f"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# List all files in the current directory, stripping leading "./"
|
||||||
|
# Pass a variable name and it will be filled as an array.
|
||||||
|
list_files() {
|
||||||
|
count=0
|
||||||
|
temp_filelist=$(mktemp)
|
||||||
|
find . -type f \
|
||||||
|
! -name "update.manifest" \
|
||||||
|
! -name "updatev2.manifest" \
|
||||||
|
! -name "updatev3.manifest" \
|
||||||
|
| sed 's/\.\/\(.*\)/\1/' \
|
||||||
|
| sort -r > "${temp_filelist}"
|
||||||
|
while read file; do
|
||||||
|
eval "${1}[$count]=\"$file\""
|
||||||
|
# Changed for Zotero to avoid eval as 1
|
||||||
|
#(( count++ ))
|
||||||
|
(( ++count ))
|
||||||
|
done < "${temp_filelist}"
|
||||||
|
rm "${temp_filelist}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# List all directories in the current directory, stripping leading "./"
|
||||||
|
list_dirs() {
|
||||||
|
count=0
|
||||||
|
temp_dirlist=$(mktemp)
|
||||||
|
find . -type d \
|
||||||
|
! -name "." \
|
||||||
|
! -name ".." \
|
||||||
|
| sed 's/\.\/\(.*\)/\1/' \
|
||||||
|
| sort -r > "${temp_dirlist}"
|
||||||
|
while read dir; do
|
||||||
|
eval "${1}[$count]=\"$dir\""
|
||||||
|
# Changed for Zotero
|
||||||
|
#(( count++ ))
|
||||||
|
(( ++count ))
|
||||||
|
done < "${temp_dirlist}"
|
||||||
|
rm "${temp_dirlist}"
|
||||||
|
}
|
||||||
145
app/update-packaging/make_full_update.sh
Executable file
145
app/update-packaging/make_full_update.sh
Executable file
|
|
@ -0,0 +1,145 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This tool generates full update packages for the update system.
|
||||||
|
# Author: Darin Fisher
|
||||||
|
#
|
||||||
|
|
||||||
|
# Added for Zotero
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
. $(dirname "$0")/common.sh
|
||||||
|
|
||||||
|
# Process a single file task when invoked from run_parallel_tasks()
|
||||||
|
if [ "${1:-}" = "--run-task" ]; then
|
||||||
|
process_update_task "$2"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
print_usage() {
|
||||||
|
notice "Usage: $(basename $0) [OPTIONS] ARCHIVE DIRECTORY"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# = 0 ]; then
|
||||||
|
print_usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $1 = -h ]; then
|
||||||
|
print_usage
|
||||||
|
notice ""
|
||||||
|
notice "The contents of DIRECTORY will be stored in ARCHIVE."
|
||||||
|
notice ""
|
||||||
|
notice "Options:"
|
||||||
|
notice " -h show this help text"
|
||||||
|
notice " -q be less verbose"
|
||||||
|
notice ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $1 = -q ]; then
|
||||||
|
QUIET=1
|
||||||
|
export QUIET
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mar_command="$MAR -V ${MOZ_PRODUCT_VERSION:?} -H ${MAR_CHANNEL_ID:?}"
|
||||||
|
|
||||||
|
archive="$1"
|
||||||
|
targetdir="$2"
|
||||||
|
# Prevent the workdir from being inside the targetdir so it isn't included in
|
||||||
|
# the update mar.
|
||||||
|
if [ $(echo "$targetdir" | grep -c '/$') = 1 ]; then
|
||||||
|
# Remove the /
|
||||||
|
targetdir=$(echo "$targetdir" | sed -e 's:\/$::')
|
||||||
|
fi
|
||||||
|
workdir="$targetdir.work"
|
||||||
|
updatemanifestv3="$workdir/updatev3.manifest"
|
||||||
|
targetfiles="updatev3.manifest"
|
||||||
|
|
||||||
|
mkdir -p "$workdir"
|
||||||
|
|
||||||
|
# Generate a list of all files in the target directory.
|
||||||
|
pushd "$targetdir"
|
||||||
|
if test $? -ne 0 ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "precomplete" ]; then
|
||||||
|
if [ ! -f "Contents/Resources/precomplete" ]; then
|
||||||
|
notice "precomplete file is missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
list_files files
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Add the type of update to the beginning of the update manifests.
|
||||||
|
> "$updatemanifestv3"
|
||||||
|
notice ""
|
||||||
|
notice "Adding type instruction to update manifests"
|
||||||
|
notice " type complete"
|
||||||
|
echo "type \"complete\"" >> "$updatemanifestv3"
|
||||||
|
|
||||||
|
notice ""
|
||||||
|
notice "Adding file add instructions to update manifests"
|
||||||
|
num_files=${#files[*]}
|
||||||
|
|
||||||
|
# Compress the files in parallel via run_parallel_tasks() in
|
||||||
|
# common.sh, and then assemble the manifest and archive list serially in the
|
||||||
|
# original order
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
taskfile="$tmpdir/tasks"
|
||||||
|
TAB="$(printf '\t')"
|
||||||
|
> "$taskfile"
|
||||||
|
|
||||||
|
for ((i=0; $i<$num_files; i=$i+1)); do
|
||||||
|
echo "full$TAB${files[$i]}" >> "$taskfile"
|
||||||
|
done
|
||||||
|
|
||||||
|
newdir="$targetdir"
|
||||||
|
export newdir workdir BCJ_OPTIONS QUIET
|
||||||
|
run_parallel_tasks "$taskfile" "$targetdir" "$0"
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
|
||||||
|
for ((i=0; $i<$num_files; i=$i+1)); do
|
||||||
|
f="${files[$i]}"
|
||||||
|
|
||||||
|
if check_for_add_if_not_update "$f"; then
|
||||||
|
make_add_if_not_instruction "$f" "$updatemanifestv3"
|
||||||
|
else
|
||||||
|
make_add_instruction "$f" "$updatemanifestv3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
targetfiles="$targetfiles \"$f\""
|
||||||
|
done
|
||||||
|
|
||||||
|
# Append remove instructions for any dead files.
|
||||||
|
notice ""
|
||||||
|
notice "Adding file and directory remove instructions from file 'removed-files'"
|
||||||
|
append_remove_instructions "$targetdir" "$updatemanifestv3"
|
||||||
|
|
||||||
|
$XZ $XZ_OPT --compress $BCJ_OPTIONS --lzma2 --format=xz --check=crc64 --force "$updatemanifestv3" && mv -f "$updatemanifestv3.xz" "$updatemanifestv3"
|
||||||
|
|
||||||
|
# Changed for Zotero -- -C is unreliable
|
||||||
|
pushd "$workdir" > /dev/null
|
||||||
|
mar_command="$mar_command -c output.mar"
|
||||||
|
eval "$mar_command $targetfiles"
|
||||||
|
popd > /dev/null
|
||||||
|
mv -f "$workdir/output.mar" "$archive"
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
rm -fr "$workdir"
|
||||||
|
|
||||||
|
notice ""
|
||||||
|
notice "Finished"
|
||||||
|
notice ""
|
||||||
301
app/update-packaging/make_incremental_update.sh
Executable file
301
app/update-packaging/make_incremental_update.sh
Executable file
|
|
@ -0,0 +1,301 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#
|
||||||
|
# This tool generates incremental update packages for the update system.
|
||||||
|
# Author: Darin Fisher
|
||||||
|
#
|
||||||
|
|
||||||
|
# Added for Zotero
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
. $(dirname "$0")/common.sh
|
||||||
|
|
||||||
|
# Process a single file task when invoked from run_parallel_tasks()
|
||||||
|
if [ "${1:-}" = "--run-task" ]; then
|
||||||
|
process_update_task "$2"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
print_usage() {
|
||||||
|
notice "Usage: $(basename $0) [OPTIONS] ARCHIVE FROMDIR TODIR"
|
||||||
|
notice ""
|
||||||
|
notice "The differences between FROMDIR and TODIR will be stored in ARCHIVE."
|
||||||
|
notice ""
|
||||||
|
notice "Options:"
|
||||||
|
notice " -h show this help text"
|
||||||
|
notice " -f clobber this file in the installation"
|
||||||
|
notice " Must be a path to a file to clobber in the partial update."
|
||||||
|
notice " -q be less verbose"
|
||||||
|
notice ""
|
||||||
|
}
|
||||||
|
|
||||||
|
check_for_forced_update() {
|
||||||
|
force_list="$1"
|
||||||
|
forced_file_chk="$2"
|
||||||
|
|
||||||
|
local f
|
||||||
|
|
||||||
|
if [ "$forced_file_chk" = "precomplete" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$forced_file_chk" = "Contents/Resources/precomplete" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$forced_file_chk" = "removed-files" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$forced_file_chk" = "Contents/Resources/removed-files" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
# notarization ticket
|
||||||
|
if [ "$forced_file_chk" = "Contents/CodeResources" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${forced_file_chk##*.}" = "chk" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
|
||||||
|
for f in $force_list; do
|
||||||
|
#echo comparing $forced_file_chk to $f
|
||||||
|
if [ "$forced_file_chk" = "$f" ]; then
|
||||||
|
## "true" *giggle*
|
||||||
|
return 0;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
## 'false'... because this is bash. Oh yay!
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# = 0 ]; then
|
||||||
|
print_usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
requested_forced_updates='Contents/MacOS/firefox'
|
||||||
|
|
||||||
|
while getopts "hqf:" flag
|
||||||
|
do
|
||||||
|
case "$flag" in
|
||||||
|
h) print_usage; exit 0
|
||||||
|
;;
|
||||||
|
q) QUIET=1
|
||||||
|
;;
|
||||||
|
f) requested_forced_updates="$requested_forced_updates $OPTARG"
|
||||||
|
;;
|
||||||
|
?) print_usage; exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mar_command="$MAR -V ${MOZ_PRODUCT_VERSION:?} -H ${MAR_CHANNEL_ID:?}"
|
||||||
|
|
||||||
|
# Added for -e for Zotero
|
||||||
|
set +e
|
||||||
|
let arg_start=$OPTIND-1
|
||||||
|
shift $arg_start
|
||||||
|
set -e
|
||||||
|
|
||||||
|
archive="$1"
|
||||||
|
olddir="$2"
|
||||||
|
newdir="$3"
|
||||||
|
# Prevent the workdir from being inside the targetdir so it isn't included in
|
||||||
|
# the update mar.
|
||||||
|
if [ $(echo "$newdir" | grep -c '/$') = 1 ]; then
|
||||||
|
# Remove the /
|
||||||
|
newdir=$(echo "$newdir" | sed -e 's:\/$::')
|
||||||
|
fi
|
||||||
|
workdir="$(mktemp -d)"
|
||||||
|
updatemanifestv3="$workdir/updatev3.manifest"
|
||||||
|
archivefiles="updatev3.manifest"
|
||||||
|
|
||||||
|
mkdir -p "$workdir"
|
||||||
|
|
||||||
|
# Generate a list of all files in the target directory.
|
||||||
|
pushd "$olddir"
|
||||||
|
if test $? -ne 0 ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
list_files oldfiles
|
||||||
|
list_dirs olddirs
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
pushd "$newdir"
|
||||||
|
if test $? -ne 0 ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "precomplete" ]; then
|
||||||
|
if [ ! -f "Contents/Resources/precomplete" ]; then
|
||||||
|
notice "precomplete file is missing!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
list_dirs newdirs
|
||||||
|
list_files newfiles
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Add the type of update to the beginning of the update manifests.
|
||||||
|
notice ""
|
||||||
|
notice "Adding type instruction to update manifests"
|
||||||
|
> $updatemanifestv3
|
||||||
|
notice " type partial"
|
||||||
|
echo "type \"partial\"" >> $updatemanifestv3
|
||||||
|
|
||||||
|
notice ""
|
||||||
|
notice "Adding file patch and add instructions to update manifests"
|
||||||
|
|
||||||
|
num_oldfiles=${#oldfiles[*]}
|
||||||
|
remove_array=
|
||||||
|
num_removes=0
|
||||||
|
|
||||||
|
# The main file loop is split into three passes so that the
|
||||||
|
# CPU-heavy work can run in parallel: classify each file into a task list, run
|
||||||
|
# the diffing/compression tasks in parallel via run_parallel_tasks() in
|
||||||
|
# common.sh, and then assemble the manifest and archive list serially in the
|
||||||
|
# original order based on the files the tasks left in the work directory.
|
||||||
|
#
|
||||||
|
# (This also drops the unused MBSDIFF_HOOK/funsize path from the upstream
|
||||||
|
# script -- the diff behavior itself is unchanged and now lives in
|
||||||
|
# process_update_task() in common.sh.)
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
taskfile="$tmpdir/tasks"
|
||||||
|
TAB="$(printf '\t')"
|
||||||
|
> "$taskfile"
|
||||||
|
|
||||||
|
for ((i=0; $i<$num_oldfiles; i=$i+1)); do
|
||||||
|
f="${oldfiles[$i]}"
|
||||||
|
|
||||||
|
# If this file exists in the new directory as well, then check if it differs.
|
||||||
|
if [ -f "$newdir/$f" ]; then
|
||||||
|
if check_for_add_if_not_update "$f"; then
|
||||||
|
echo "full$TAB$f" >> "$taskfile"
|
||||||
|
elif check_for_forced_update "$requested_forced_updates" "$f"; then
|
||||||
|
echo "full$TAB$f" >> "$taskfile"
|
||||||
|
else
|
||||||
|
echo "diff$TAB$f" >> "$taskfile"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Newly added files -- in the new directory but not the old one. (This replaces
|
||||||
|
# the O(n^2) nested skip loop from the upstream script.)
|
||||||
|
printf '%s\n' "${oldfiles[@]}" | sort > "$tmpdir/oldlist"
|
||||||
|
printf '%s\n' "${newfiles[@]}" | sort > "$tmpdir/newlist"
|
||||||
|
comm -13 "$tmpdir/oldlist" "$tmpdir/newlist" | sed '/^$/d' | sort -r > "$tmpdir/newonly"
|
||||||
|
|
||||||
|
while IFS= read -r f; do
|
||||||
|
echo "full$TAB$f" >> "$taskfile"
|
||||||
|
done < "$tmpdir/newonly"
|
||||||
|
|
||||||
|
export olddir newdir workdir MBSDIFF BCJ_OPTIONS QUIET
|
||||||
|
run_parallel_tasks "$taskfile" "$newdir" "$0"
|
||||||
|
|
||||||
|
# Assemble the manifest and archive list in the original order. A diffed file
|
||||||
|
# left $f.patch in the work directory if the patch was smaller, $f if the
|
||||||
|
# compressed file was smaller, and neither if the file was unchanged.
|
||||||
|
for ((i=0; $i<$num_oldfiles; i=$i+1)); do
|
||||||
|
f="${oldfiles[$i]}"
|
||||||
|
|
||||||
|
if [ -f "$newdir/$f" ]; then
|
||||||
|
if check_for_add_if_not_update "$f"; then
|
||||||
|
make_add_if_not_instruction "$f" "$updatemanifestv3"
|
||||||
|
archivefiles="$archivefiles \"$f\""
|
||||||
|
elif check_for_forced_update "$requested_forced_updates" "$f"; then
|
||||||
|
make_add_instruction "$f" "$updatemanifestv3" 1
|
||||||
|
archivefiles="$archivefiles \"$f\""
|
||||||
|
elif [ -f "$workdir/$f.patch" ]; then
|
||||||
|
make_patch_instruction "$f" "$updatemanifestv3"
|
||||||
|
archivefiles="$archivefiles \"$f.patch\""
|
||||||
|
elif [ -f "$workdir/$f" ]; then
|
||||||
|
make_add_instruction "$f" "$updatemanifestv3"
|
||||||
|
archivefiles="$archivefiles \"$f\""
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# remove instructions are added after add / patch instructions for
|
||||||
|
# consistency with make_incremental_updates.py
|
||||||
|
remove_array[$num_removes]=$f
|
||||||
|
# Changed by Zotero for -e
|
||||||
|
#(( num_removes++ ))
|
||||||
|
(( ++num_removes ))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Newly added files
|
||||||
|
notice ""
|
||||||
|
notice "Adding file add instructions to update manifests"
|
||||||
|
|
||||||
|
while IFS= read -r f; do
|
||||||
|
if check_for_add_if_not_update "$f"; then
|
||||||
|
make_add_if_not_instruction "$f" "$updatemanifestv3"
|
||||||
|
else
|
||||||
|
make_add_instruction "$f" "$updatemanifestv3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
archivefiles="$archivefiles \"$f\""
|
||||||
|
done < "$tmpdir/newonly"
|
||||||
|
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
|
||||||
|
notice ""
|
||||||
|
notice "Adding file remove instructions to update manifests"
|
||||||
|
for ((i=0; $i<$num_removes; i=$i+1)); do
|
||||||
|
f="${remove_array[$i]}"
|
||||||
|
verbose_notice " remove \"$f\""
|
||||||
|
echo "remove \"$f\"" >> $updatemanifestv3
|
||||||
|
done
|
||||||
|
|
||||||
|
# Add remove instructions for any dead files.
|
||||||
|
notice ""
|
||||||
|
notice "Adding file and directory remove instructions from file 'removed-files'"
|
||||||
|
append_remove_instructions "$newdir" "$updatemanifestv3"
|
||||||
|
|
||||||
|
notice ""
|
||||||
|
notice "Adding directory remove instructions for directories that no longer exist"
|
||||||
|
num_olddirs=${#olddirs[*]}
|
||||||
|
|
||||||
|
for ((i=0; $i<$num_olddirs; i=$i+1)); do
|
||||||
|
f="${olddirs[$i]}"
|
||||||
|
# If this dir doesn't exist in the new directory remove it.
|
||||||
|
if [ ! -d "$newdir/$f" ]; then
|
||||||
|
verbose_notice " rmdir $f/"
|
||||||
|
echo "rmdir \"$f/\"" >> $updatemanifestv3
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
$XZ $XZ_OPT --compress $BCJ_OPTIONS --lzma2 --format=xz --check=crc64 --force "$updatemanifestv3" && mv -f "$updatemanifestv3.xz" "$updatemanifestv3"
|
||||||
|
|
||||||
|
# Changed for Zotero -- -C is unreliable
|
||||||
|
pushd "$workdir" > /dev/null
|
||||||
|
mar_command="$mar_command -c output.mar"
|
||||||
|
eval "$mar_command $archivefiles"
|
||||||
|
popd > /dev/null
|
||||||
|
mv -f "$workdir/output.mar" "$archive"
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
rm -fr "$workdir"
|
||||||
|
|
||||||
|
notice ""
|
||||||
|
notice "Finished"
|
||||||
|
notice ""
|
||||||
24
app/update-packaging/removed-files_linux-x86_64
Normal file
24
app/update-packaging/removed-files_linux-x86_64
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
application.ini
|
||||||
|
chrome.manifest
|
||||||
|
chrome/*
|
||||||
|
components/*
|
||||||
|
defaults/*
|
||||||
|
deleted.txt
|
||||||
|
dictionaries/*
|
||||||
|
extensions/*
|
||||||
|
fonts/EmojiOneMozilla.ttf
|
||||||
|
gtk2/*
|
||||||
|
icudt58l.dat
|
||||||
|
install.rdf
|
||||||
|
libnssdbm3.chk
|
||||||
|
libnssdbm3.so
|
||||||
|
libsoftokn3.chk
|
||||||
|
pingsender
|
||||||
|
resource/*
|
||||||
|
run-zotero.sh
|
||||||
|
styles.zip
|
||||||
|
test/*
|
||||||
|
translators.index
|
||||||
|
translators.zip
|
||||||
|
xulrunner/*
|
||||||
|
zotero.jar
|
||||||
67
app/update-packaging/removed-files_mac
Normal file
67
app/update-packaging/removed-files_mac
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
Contents/Frameworks/XUL.framework/
|
||||||
|
Contents/MacOS/Info.plist
|
||||||
|
Contents/MacOS/LICENSE
|
||||||
|
Contents/MacOS/README.xulrunner
|
||||||
|
Contents/MacOS/Resources/*
|
||||||
|
Contents/MacOS/active-update.xml
|
||||||
|
Contents/MacOS/chrome.manifest
|
||||||
|
Contents/MacOS/components/
|
||||||
|
Contents/MacOS/crashreporter.app/*
|
||||||
|
Contents/MacOS/defaults/*
|
||||||
|
Contents/MacOS/dependentlibs.list
|
||||||
|
Contents/MacOS/dictionaries/
|
||||||
|
Contents/MacOS/gmp-fake/*
|
||||||
|
Contents/MacOS/js-gdb.py
|
||||||
|
Contents/MacOS/libc++.1.dylib
|
||||||
|
Contents/MacOS/libfreebl.chk
|
||||||
|
Contents/MacOS/libmozsqlite3.dylib
|
||||||
|
Contents/MacOS/libnspr4.dylib
|
||||||
|
Contents/MacOS/libnssdbm3.chk
|
||||||
|
Contents/MacOS/libnssdbm3.dylib
|
||||||
|
Contents/MacOS/libnssutil3.dylib
|
||||||
|
Contents/MacOS/libplc4.dylib
|
||||||
|
Contents/MacOS/libplds4.dylib
|
||||||
|
Contents/MacOS/libplugin_child_interpose.dylib
|
||||||
|
Contents/MacOS/libsmime3.dylib
|
||||||
|
Contents/MacOS/libsoftokn3.chk
|
||||||
|
Contents/MacOS/libssl3.dylib
|
||||||
|
Contents/MacOS/libxpcom.dylib
|
||||||
|
Contents/MacOS/omni.ja
|
||||||
|
Contents/MacOS/pdfinfo
|
||||||
|
Contents/MacOS/pdftotext
|
||||||
|
Contents/MacOS/pingsender
|
||||||
|
Contents/MacOS/platform.ini
|
||||||
|
Contents/MacOS/precomplete
|
||||||
|
Contents/MacOS/res/*
|
||||||
|
Contents/MacOS/update-settings.ini
|
||||||
|
Contents/MacOS/updater.app/Contents/MacOS/updater-bin
|
||||||
|
Contents/MacOS/updates.xml
|
||||||
|
Contents/MacOS/updates/*
|
||||||
|
Contents/MacOS/zotero-bin
|
||||||
|
Contents/Resources/CONTRIBUTING.md
|
||||||
|
Contents/Resources/COPYING
|
||||||
|
Contents/Resources/README.md
|
||||||
|
Contents/Resources/application.ini
|
||||||
|
Contents/Resources/chrome.manifest
|
||||||
|
Contents/Resources/chrome/*
|
||||||
|
Contents/Resources/components/*
|
||||||
|
Contents/Resources/defaults/*
|
||||||
|
Contents/Resources/deleted.txt
|
||||||
|
Contents/Resources/devtools.jar
|
||||||
|
Contents/Resources/dictionaries/*
|
||||||
|
Contents/Resources/extensions/*
|
||||||
|
Contents/Resources/gmp-clearkey/0.1/clearkey.info
|
||||||
|
Contents/Resources/icudt56l.dat
|
||||||
|
Contents/Resources/install.rdf
|
||||||
|
Contents/Resources/poppler-data/*
|
||||||
|
Contents/Resources/resource/*
|
||||||
|
Contents/Resources/styles.zip
|
||||||
|
Contents/Resources/test/*
|
||||||
|
Contents/Resources/translators.index
|
||||||
|
Contents/Resources/translators.zip
|
||||||
|
Contents/Resources/voucher.bin
|
||||||
|
Contents/Resources/zotero.jar
|
||||||
|
Contents/XPCServices/*
|
||||||
|
Contents/_CodeSignature/CodeDirectory
|
||||||
|
Contents/_CodeSignature/CodeRequirements
|
||||||
|
Contents/_CodeSignature/CodeSignature
|
||||||
58
app/update-packaging/removed-files_win32
Normal file
58
app/update-packaging/removed-files_win32
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
Accessible.tlb
|
||||||
|
AccessibleHandler.dll
|
||||||
|
IA2Marshal.dll
|
||||||
|
Microsoft.VC80.CRT.manifest
|
||||||
|
api-ms-win-core-console-l1-1-0.dll
|
||||||
|
api-ms-win-core-datetime-l1-1-0.dll
|
||||||
|
api-ms-win-core-debug-l1-1-0.dll
|
||||||
|
api-ms-win-core-errorhandling-l1-1-0.dll
|
||||||
|
api-ms-win-core-file-l1-1-0.dll
|
||||||
|
api-ms-win-core-handle-l1-1-0.dll
|
||||||
|
api-ms-win-core-heap-l1-1-0.dll
|
||||||
|
api-ms-win-core-interlocked-l1-1-0.dll
|
||||||
|
api-ms-win-core-libraryloader-l1-1-0.dll
|
||||||
|
api-ms-win-core-memory-l1-1-0.dll
|
||||||
|
api-ms-win-core-namedpipe-l1-1-0.dll
|
||||||
|
api-ms-win-core-processenvironment-l1-1-0.dll
|
||||||
|
api-ms-win-core-processthreads-l1-1-0.dll
|
||||||
|
api-ms-win-core-profile-l1-1-0.dll
|
||||||
|
api-ms-win-core-rtlsupport-l1-1-0.dll
|
||||||
|
api-ms-win-core-string-l1-1-0.dll
|
||||||
|
api-ms-win-core-synch-l1-1-0.dll
|
||||||
|
api-ms-win-core-sysinfo-l1-1-0.dll
|
||||||
|
api-ms-win-core-util-l1-1-0.dll
|
||||||
|
application.ini
|
||||||
|
chrome.manifest
|
||||||
|
chrome/*
|
||||||
|
components/*
|
||||||
|
defaults/*
|
||||||
|
deleted.txt
|
||||||
|
dictionaries/*
|
||||||
|
extensions/*
|
||||||
|
firefox.*
|
||||||
|
fonts/EmojiOneMozilla.ttf
|
||||||
|
freebl3.chk
|
||||||
|
gkmedias.dll
|
||||||
|
install.rdf
|
||||||
|
minidump-analyzer.exe
|
||||||
|
mozcrt19.dll
|
||||||
|
mozutils.dll
|
||||||
|
msvcp80.dll
|
||||||
|
msvcp120.dll
|
||||||
|
msvcr80.dll
|
||||||
|
msvcr120.dll
|
||||||
|
nssdbm3.chk
|
||||||
|
nssdbm3.dll
|
||||||
|
pdfinfo.exe
|
||||||
|
pdftotext.exe
|
||||||
|
pingsender.exe
|
||||||
|
plugin-hang-ui.exe
|
||||||
|
poppler-data/*
|
||||||
|
resource/*
|
||||||
|
softokn3.chk
|
||||||
|
styles.zip
|
||||||
|
test/*
|
||||||
|
translators.index
|
||||||
|
translators.zip
|
||||||
|
xulrunner/*
|
||||||
|
zotero.jar
|
||||||
66
app/update-packaging/xz_to_bzip
Executable file
66
app/update-packaging/xz_to_bzip
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
infile=${1:-}
|
||||||
|
outfile=${2:-}
|
||||||
|
if [[ -z "$infile" ]] || [[ -z "$infile" ]]; then
|
||||||
|
echo "Usage: $0 infile.mar outfile.mar"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mar="$APP_ROOT_DIR/xulrunner/bin/mar"
|
||||||
|
if [ ! -f "$mar" ]; then
|
||||||
|
echo "$mar not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmp_dir=`mktemp -d`
|
||||||
|
function cleanup {
|
||||||
|
rm -rf $tmp_dir
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
cd "$tmp_dir"
|
||||||
|
mkdir in
|
||||||
|
cd in
|
||||||
|
|
||||||
|
if [ "`uname -o 2> /dev/null`" = "Cygwin" ]; then
|
||||||
|
infile=$(cygpath -w "$infile")
|
||||||
|
outfile=$(cygpath -w "$outfile")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Extracting MAR"
|
||||||
|
$mar -x "$infile"
|
||||||
|
|
||||||
|
echo "Renaming all files to .xz"
|
||||||
|
find . -type f -exec mv {} {}.xz \;
|
||||||
|
echo "Uncompressing files"
|
||||||
|
find . -type f -exec unxz {} \;
|
||||||
|
echo "Recompressing files with bzip2"
|
||||||
|
find . -type f -exec bzip2 {} \;
|
||||||
|
echo "Removing .bz extension"
|
||||||
|
find . -type f | while read f; do mv "$f" "${f%.bz2}"; done
|
||||||
|
|
||||||
|
channel=$($mar -T "$infile" | sed -n -r 's/.+MAR channel name: ([^\s]+)/\1/p')
|
||||||
|
version=$($mar -T "$infile" | sed -n -r 's/.+Product version: ([^\s]+)/\1/p')
|
||||||
|
|
||||||
|
if [ -z "$channel" ]; then
|
||||||
|
echo "Could not detect channel"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
echo "Could not detect version"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "MAR channel name: $channel"
|
||||||
|
echo "Product version: $version"
|
||||||
|
|
||||||
|
echo "Creating new MAR"
|
||||||
|
find . -type f -print0 | xargs -0 $mar -V $version -H $channel -c "$outfile"
|
||||||
|
echo
|
||||||
|
$mar -T "$outfile"
|
||||||
BIN
app/win/VersionInfo1-updater.rc
Normal file
BIN
app/win/VersionInfo1-updater.rc
Normal file
Binary file not shown.
BIN
app/win/VersionInfo1.rc
Normal file
BIN
app/win/VersionInfo1.rc
Normal file
Binary file not shown.
59
app/win/build
Normal file
59
app/win/build
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
APP_ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$APP_ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
if [ $# -lt 2 ]; then
|
||||||
|
echo "Usage: $0 /path/to/src/firefox x64|arm64|win32" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
gecko_path=$1
|
||||||
|
arch=$2
|
||||||
|
|
||||||
|
if [ ! -d "$gecko_path" ]; then
|
||||||
|
echo "$gecko_path is not a directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install required Rust version
|
||||||
|
rustup toolchain install $RUST_VERSION
|
||||||
|
if [ $arch = "x64" ]; then
|
||||||
|
rust_target=x86_64
|
||||||
|
elif [ $arch = "arm64" ]; then
|
||||||
|
rust_target=aarch64
|
||||||
|
elif [ $arch = "win32" ]; then
|
||||||
|
rust_target=i686
|
||||||
|
else
|
||||||
|
echo "Unknown architecture $arch" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rustup default $RUST_VERSION
|
||||||
|
rustup target add $rust_target-pc-windows-msvc
|
||||||
|
|
||||||
|
cp "$SCRIPT_DIR/mozconfig" "$gecko_path"
|
||||||
|
|
||||||
|
if [[ $arch == "arm64" || $arch == "win32" ]]; then
|
||||||
|
export Z_ARCH=$arch
|
||||||
|
export RUST_TARGET=$rust_target-pc-windows-msvc
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$gecko_path"
|
||||||
|
./mach build
|
||||||
|
./mach package
|
||||||
|
|
||||||
|
# Copy the packaged ZIP back to app/win/ for launcher/xul.dll extraction
|
||||||
|
case $arch in
|
||||||
|
x64) zip_suffix=win64 ;;
|
||||||
|
arm64) zip_suffix=win64-aarch64 ;;
|
||||||
|
win32) zip_suffix=win32 ;;
|
||||||
|
esac
|
||||||
|
zip_file=$(ls "$gecko_path"/obj-*/dist/firefox-*.en-US.${zip_suffix}.zip 2>/dev/null | head -1) || true
|
||||||
|
if [ -z "$zip_file" ] || [ ! -f "$zip_file" ]; then
|
||||||
|
echo "Could not find packaged zip for $arch in $gecko_path/obj-*/dist/" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cp "$zip_file" "$SCRIPT_DIR/"
|
||||||
|
echo "Copied $(basename "$zip_file") to $SCRIPT_DIR"
|
||||||
59
app/win/download-nsis-plugins
Executable file
59
app/win/download-nsis-plugins
Executable file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||||
|
. "$ROOT_DIR/config.sh"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Turns out we need older versions from Mozilla, not the official ZIPs
|
||||||
|
#
|
||||||
|
#plugins=$(cat <<EOF
|
||||||
|
#http://nsis.sourceforge.net/mediawiki/images/d/d4/AppAssocReg-0.4.zip
|
||||||
|
#https://github.com/connectiblutz/NSIS-ApplicationID/releases/download/1.1/NSIS-ApplicationID.zip
|
||||||
|
#http://nsis.sourceforge.net/mediawiki/images/c/ca/InvokeShellVerb-1.0.zip
|
||||||
|
#http://nsis.sourceforge.net/mediawiki/images/6/6c/Shelllink.zip
|
||||||
|
#http://nsis.sourceforge.net/mediawiki/images/8/8f/UAC.zip
|
||||||
|
#EOF
|
||||||
|
#)
|
||||||
|
#
|
||||||
|
#mkdir -p nsis
|
||||||
|
#cd nsis
|
||||||
|
#for plugin in $plugins; do
|
||||||
|
# curl -fsSLO $plugin
|
||||||
|
#done
|
||||||
|
#
|
||||||
|
#unzip_cmd="unzip -d Plugins -j"
|
||||||
|
#for zip in AppAssocReg*.zip InvokeShellVerb*.zip; do
|
||||||
|
# $unzip_cmd $zip 'Plugins/Unicode/*.dll'
|
||||||
|
#done
|
||||||
|
#$unzip_cmd Shelllink*.zip Unicode/Plugins/ShellLink.dll
|
||||||
|
#$unzip_cmd NSIS-ApplicationID*.zip 'ReleaseUnicode/ApplicationID*'
|
||||||
|
#$unzip_cmd UAC.zip Plugins/x86-unicode/UAC.dll
|
||||||
|
#
|
||||||
|
#rm *.zip
|
||||||
|
#
|
||||||
|
#echo
|
||||||
|
#echo
|
||||||
|
#echo "Files extracted to ./nsis/Plugins -- move to ${NSIS_DIR}Plugins"
|
||||||
|
#echo
|
||||||
|
#ls -la Plugins
|
||||||
|
|
||||||
|
mkdir -p Plugins
|
||||||
|
cd Plugins
|
||||||
|
plugins="AccessControl AppAssocReg ApplicationID InvokeShellVerb ShellLink UAC"
|
||||||
|
for plugin in $plugins; do
|
||||||
|
curl https://hg.mozilla.org/mozilla-central/raw-file/052d53200cf8/other-licenses/nsis/Plugins/$plugin.dll > $plugin.dll
|
||||||
|
done
|
||||||
|
|
||||||
|
# From https://nsis.sourceforge.io/NsProcess_plugin
|
||||||
|
curl https://download.zotero.org/dev/win/NsProcess-1.6.zip > NsProcess.zip
|
||||||
|
7z e NsProcess.zip "Plugin/nsProcessW.dll"
|
||||||
|
mv nsProcessW.dll nsProcess.dll
|
||||||
|
rm NsProcess.zip
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "Files downloaded to ./Plugins -- move to ${NSIS_DIR}Plugins"
|
||||||
|
echo
|
||||||
|
ls -la
|
||||||
84
app/win/extract_xul_dll
Executable file
84
app/win/extract_xul_dll
Executable file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Extract xul.dll from custom Firefox build ZIPs in current folder and create a
|
||||||
|
# ZIP for each platform with its own SHA256 hash in the filename. The files
|
||||||
|
# should then be uploaded and their hashes updated in config.sh so that
|
||||||
|
# fetch_xulrunner will download and use the custom xul.dll.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <version>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
version="$1"
|
||||||
|
|
||||||
|
# Input ZIP filenames
|
||||||
|
files=(
|
||||||
|
"firefox-$version.en-US.win32.zip"
|
||||||
|
"firefox-$version.en-US.win64-aarch64.zip"
|
||||||
|
"firefox-$version.en-US.win64.zip"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Corresponding architecture labels and output names
|
||||||
|
arches=(
|
||||||
|
"win32"
|
||||||
|
"arm64"
|
||||||
|
"x64"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Platform-specific SHA command
|
||||||
|
if [[ "$(uname)" = "Darwin" ]]; then
|
||||||
|
shasum_cmd="shasum -a 256"
|
||||||
|
else
|
||||||
|
shasum_cmd="sha256sum"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up any old artifacts
|
||||||
|
rm -f "$version"-*.zip
|
||||||
|
|
||||||
|
# Process whichever arch ZIPs are present
|
||||||
|
processed=0
|
||||||
|
for i in "${!files[@]}"; do
|
||||||
|
file="${files[$i]}"
|
||||||
|
arch="${arches[$i]}"
|
||||||
|
temp_zip="xul-temp-$arch.zip"
|
||||||
|
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
dlls=(xul.dll)
|
||||||
|
|
||||||
|
# TEMP: Fix startup error on win32 due to missing export numSamples@RLBoxSoundTouch
|
||||||
|
if [[ $arch == "win32" ]]; then
|
||||||
|
dlls+=(lgpllibs.dll)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Extracting ${dlls[*]} from $file"
|
||||||
|
for dll in "${dlls[@]}"; do
|
||||||
|
unzip -p "$file" "firefox/$dll" > "$dll"
|
||||||
|
done
|
||||||
|
|
||||||
|
zip -q "$temp_zip" "${dlls[@]}"
|
||||||
|
|
||||||
|
# Calculate hash
|
||||||
|
sum=$($shasum_cmd "$temp_zip" | awk '{print $1}')
|
||||||
|
|
||||||
|
# Rename to final output
|
||||||
|
final_zip="$version-$arch-$sum.zip"
|
||||||
|
mv "$temp_zip" "$final_zip"
|
||||||
|
rm -f xul.dll lgpllibs.dll
|
||||||
|
|
||||||
|
echo "Created $final_zip"
|
||||||
|
processed=$((processed + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $processed -eq 0 ]; then
|
||||||
|
echo "No firefox-$version.en-US.*.zip files found in $SCRIPT_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue