Compare commits
918 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5605553e3a | ||
|
|
b5384c9ad7 | ||
|
|
8c77bfad93 | ||
|
|
235e314da7 | ||
|
|
628daeadfe | ||
|
|
2a55b20b8d | ||
|
|
6c818ac3c7 | ||
|
|
f283c0c59c | ||
|
|
0d83d7cb68 | ||
|
|
2e10cec2cb | ||
|
|
3802131bad | ||
|
|
5467950f62 | ||
|
|
3ba5bb52f3 | ||
|
|
5c011c5c21 | ||
|
|
532e975687 | ||
|
|
7efc3220f4 | ||
|
|
b5444def55 | ||
|
|
c7ba898fe0 | ||
|
|
7a8c8b19c2 | ||
|
|
72c9d207a0 | ||
|
|
1e4727cfec | ||
|
|
8237c5be69 | ||
|
|
63877d5293 | ||
|
|
737353a017 | ||
|
|
528b5e3108 | ||
|
|
5d098140e7 | ||
|
|
aeb4eed7b5 | ||
|
|
c68b112858 | ||
|
|
b4f2c3c369 | ||
|
|
084f522de1 | ||
|
|
5d5e0220b4 | ||
|
|
7b5ce24302 | ||
|
|
19e33d0924 | ||
|
|
f8a4994307 | ||
|
|
04fb952814 | ||
|
|
8d6e9523bb | ||
|
|
b317cc18d0 | ||
|
|
03a5833e29 | ||
|
|
91a9c65173 | ||
|
|
edabed9594 | ||
|
|
838beded20 | ||
|
|
7dcfe9993c | ||
|
|
b73e2fbdab | ||
|
|
d49771b43a | ||
|
|
928cdf4f4f | ||
|
|
8da6fc40a1 | ||
|
|
6e84a8d420 | ||
|
|
29557ea550 | ||
|
|
37a93dca63 | ||
|
|
b632b7e0fa | ||
|
|
fc8e3b0914 | ||
|
|
861d777899 | ||
|
|
ff3e3ce886 | ||
|
|
567f7eb205 | ||
|
|
c3c8ab85ec | ||
|
|
d1c887d754 | ||
|
|
991f4faafb | ||
|
|
371acb296d | ||
|
|
1119bcf539 | ||
|
|
d67018311f | ||
|
|
eaecec418e | ||
|
|
ab27bcacdf | ||
|
|
536a051460 | ||
|
|
259a117db5 | ||
|
|
167939a8c9 | ||
|
|
41ebfb635e | ||
|
|
017b8e9de3 | ||
|
|
6453c57979 | ||
|
|
a01c73be19 | ||
|
|
f63737ecb0 | ||
|
|
dd87799a82 | ||
|
|
da6b515bfc | ||
|
|
f9a03fa288 | ||
|
|
a5c66cf289 | ||
|
|
41b908e293 | ||
|
|
6ffed87b08 | ||
|
|
bd5ea43547 | ||
|
|
8ba27cb0f1 | ||
|
|
1ab8bb62ae | ||
|
|
6f8248ebfd | ||
|
|
33306dcc38 | ||
|
|
888818a9f7 | ||
|
|
d90229242e | ||
|
|
b14ba325d5 | ||
|
|
628e310501 | ||
|
|
131647442f | ||
|
|
01b79f2ff1 | ||
|
|
73062e21a3 | ||
|
|
e7e6584cab | ||
|
|
7373c68aeb | ||
|
|
13f1122c50 | ||
|
|
ba5fb5aca7 | ||
|
|
55a91926c1 | ||
|
|
b5e129aa6b | ||
|
|
9fc175231d | ||
|
|
4dd0a75cce | ||
|
|
3cfd502f7e | ||
|
|
452a99f7d3 | ||
|
|
a9d37a0784 | ||
|
|
22b19636e9 | ||
|
|
6ee3310e2b | ||
|
|
065b1eed11 | ||
|
|
dbc2d4a8b6 | ||
|
|
7eb2dc21af | ||
|
|
8fb9700869 | ||
|
|
f95e044206 | ||
|
|
795ab29514 | ||
|
|
72262b565e | ||
|
|
06a86033c1 | ||
|
|
e17d5defe3 | ||
|
|
959d60e957 | ||
|
|
31f516f390 | ||
|
|
b6835186a3 | ||
|
|
c32ba4aee3 | ||
|
|
e720f84005 | ||
|
|
48ef2e4563 | ||
|
|
a0d9fc4354 | ||
|
|
e4b2d27c65 | ||
|
|
c846a329a8 | ||
|
|
c1bf90ddad | ||
|
|
b418bf6db4 | ||
|
|
72363155d8 | ||
|
|
f254ee3211 | ||
|
|
497b327d43 | ||
|
|
d831369f86 | ||
|
|
c1a1e55207 | ||
|
|
c3dbb20ce3 | ||
|
|
ba4712c922 | ||
|
|
a19eb59461 | ||
|
|
484ec95596 | ||
|
|
6f5b3eb4d7 | ||
|
|
a32b3e565b | ||
|
|
a8a6f82270 | ||
|
|
24d6fda360 | ||
|
|
d4106b9a88 | ||
|
|
d0713d018c | ||
|
|
a33fc2a0db | ||
|
|
ca200e788e | ||
|
|
c454d626b6 | ||
|
|
4cf7ca4162 | ||
|
|
c22e3aaa4b | ||
|
|
7d70f1becb | ||
|
|
a476c5420a | ||
|
|
cdd8d10940 | ||
|
|
883deb1c5d | ||
|
|
e389fcaecb | ||
|
|
9078d9cfab | ||
|
|
51b662fdfe | ||
|
|
b6d74ad753 | ||
|
|
5656323434 | ||
|
|
81baebf113 | ||
|
|
f7c884d4d1 | ||
|
|
7aa9af08c3 | ||
|
|
15803d1837 | ||
|
|
c0c10fd5f1 | ||
|
|
e2d4a38639 | ||
|
|
f89676d4bb | ||
|
|
b9c167fc13 | ||
|
|
3bac06d6e5 | ||
|
|
504e11b5bb | ||
|
|
b80ba97154 | ||
|
|
e3e38f3eac | ||
|
|
93c9f4316b | ||
|
|
47a7000121 | ||
|
|
6c9026e330 | ||
|
|
d59c609a73 | ||
|
|
6ee48c8f15 | ||
|
|
6af823b36a | ||
|
|
8c7ea61623 | ||
|
|
067508c082 | ||
|
|
79065ba5c6 | ||
|
|
3fbd156c83 | ||
|
|
8fb191afcf | ||
|
|
ab37856a91 | ||
|
|
69e81e8f65 | ||
|
|
46e796303e | ||
|
|
298f1ab570 | ||
|
|
79dd8e9074 | ||
|
|
8d5afff0a4 | ||
|
|
b357003a95 | ||
|
|
5cc3b526e8 | ||
|
|
1b2a8ba6b0 | ||
|
|
75676f8830 | ||
|
|
530853c988 | ||
|
|
dcf0baa9de | ||
|
|
3e294d5339 | ||
|
|
36573a5c6f | ||
|
|
9a835af7ce | ||
|
|
ca48ff793c | ||
|
|
fc8c88be41 | ||
|
|
3485109125 | ||
|
|
a1136e7695 | ||
|
|
ceac18c554 | ||
|
|
99f32dcb99 | ||
|
|
ac937030f0 | ||
|
|
67d77dd6ce | ||
|
|
755ef0119a | ||
|
|
1a1ab92ed9 | ||
|
|
b29e9b931d | ||
|
|
0479322c1d | ||
|
|
0be7b6fe1f | ||
|
|
ee98daf9ea | ||
|
|
f2beaba3e9 | ||
|
|
823c7469e1 | ||
|
|
10efe1faee | ||
|
|
e0954b0999 | ||
|
|
5ff3e448f5 | ||
|
|
58bcbba841 | ||
|
|
30e3932af8 | ||
|
|
e86937e2e2 | ||
|
|
6276d9290d | ||
|
|
cde6589af8 | ||
|
|
482d538559 | ||
|
|
6cc5ce7a66 | ||
|
|
7a80fe4939 | ||
|
|
b8444053b8 | ||
|
|
753d7addb4 | ||
|
|
c0ae96e7a8 | ||
|
|
e99d64011e | ||
|
|
72809ef5b1 | ||
|
|
7a790c88e8 | ||
|
|
01377f6ea9 | ||
|
|
96dede4e84 | ||
|
|
72783aa068 | ||
|
|
658a8c0609 | ||
|
|
e7a91a1169 | ||
|
|
14a51458ab | ||
|
|
86c2e9e825 | ||
|
|
480932a58a | ||
|
|
529bcab009 | ||
|
|
9a4871abeb | ||
|
|
40665c05ac | ||
|
|
63cf0e347b | ||
|
|
2192386d86 | ||
|
|
e694ffcd03 | ||
|
|
eff401d418 | ||
|
|
7049ccd7ab | ||
|
|
8fb2167fca | ||
|
|
d0b8528022 | ||
|
|
13d80beb83 | ||
|
|
06ce8dd8bd | ||
|
|
9a1ea67a35 | ||
|
|
e616f904b6 | ||
|
|
bff24ffd2f | ||
|
|
2cdc969cc5 | ||
|
|
b13fd786b6 | ||
|
|
89d55d0af8 | ||
|
|
d46335aba1 | ||
|
|
e417a4b159 | ||
|
|
b0f986c740 | ||
|
|
18091f99d4 | ||
|
|
3ae2071129 | ||
|
|
820ebf4b6e | ||
|
|
161f6baba6 | ||
|
|
89d7dbf2cf | ||
|
|
b1972e56fa | ||
|
|
7d10f9829e | ||
|
|
d2723bc0ac | ||
|
|
a0d43f8ba6 | ||
|
|
37c5612aee | ||
|
|
f2e73c0887 | ||
|
|
aca36cc1ac | ||
|
|
9af6e29f42 | ||
|
|
d6db77cce8 | ||
|
|
71d2e3de74 | ||
|
|
a7e07239e3 | ||
|
|
3608114ec1 | ||
|
|
c9d5a9cea2 | ||
|
|
354cdfdbc1 | ||
|
|
4dbe9d4113 | ||
|
|
7963a8322d | ||
|
|
6ac44f05cd | ||
|
|
64a84fda38 | ||
|
|
8eec79680c | ||
|
|
0968d74dad | ||
|
|
876a1c5140 | ||
|
|
1455636169 | ||
|
|
7ea9a5ca4e | ||
|
|
2d2ec2a576 | ||
|
|
e4612ca5d4 | ||
|
|
15af5878b6 | ||
|
|
c36043a175 | ||
|
|
ee63b36ed3 | ||
|
|
35d28294cd | ||
|
|
c6bd3ab31a | ||
|
|
9c7ee6ef85 | ||
|
|
f3ea375083 | ||
|
|
15b02547e8 | ||
|
|
13b1f8b33e | ||
|
|
ccd32c04a9 | ||
|
|
df19b20d07 | ||
|
|
f41c9fbb7f | ||
|
|
a0e50670de | ||
|
|
984631d807 | ||
|
|
a9761a8976 | ||
|
|
84d8624e03 | ||
|
|
9866010b4c | ||
|
|
a3c1052cae | ||
|
|
726cbc160c | ||
|
|
bf39343920 | ||
|
|
af24b4132d | ||
|
|
d339b68715 | ||
|
|
eadc791795 | ||
|
|
408cf11b2b | ||
|
|
e3ba8d3209 | ||
|
|
17b1c83ae5 | ||
|
|
b2a8ffc577 | ||
|
|
e2711224ed | ||
|
|
2ac7e0200a | ||
|
|
e6b971b316 | ||
|
|
111bb485ec | ||
|
|
e10775d34f | ||
|
|
30957479a3 | ||
|
|
b4ab53dd32 | ||
|
|
a314eeb892 | ||
|
|
644ddf318c | ||
|
|
f598ac89ac | ||
|
|
3f7b3ca962 | ||
|
|
104c6edcde | ||
|
|
94b673dc8e | ||
|
|
096cd348f0 | ||
|
|
01c2ffe2ae | ||
|
|
0a4370236d | ||
|
|
fe8d2b397e | ||
|
|
92e90f9c55 | ||
|
|
3eb2642b11 | ||
|
|
99192a6dec | ||
|
|
cffc1fd1c4 | ||
|
|
b8f7c6daae | ||
|
|
cd07865da6 | ||
|
|
315e38e814 | ||
|
|
95b90271b6 | ||
|
|
90befac901 | ||
|
|
22f71ce17e | ||
|
|
0931f25747 | ||
|
|
971f2391cf | ||
|
|
43a26eb50a | ||
|
|
99d406072f | ||
|
|
3a1a56c7ad | ||
|
|
57cbba81e7 | ||
|
|
e48d55d126 | ||
|
|
1c03fa8642 | ||
|
|
670ff36024 | ||
|
|
6b3f6d9860 | ||
|
|
ac5876e94e | ||
|
|
b13f44023d | ||
|
|
2f15d8aef5 | ||
|
|
ecaa37efbe | ||
|
|
33e421473c | ||
|
|
eb1a96c164 | ||
|
|
2afcac763d | ||
|
|
28fe903aee | ||
|
|
253d197ccb | ||
|
|
0ceb806f1a | ||
|
|
800b9cf167 | ||
|
|
1da398e6c6 | ||
|
|
074cb132bb | ||
|
|
2df74fd9d7 | ||
|
|
d68b07dfc7 | ||
|
|
a52dff713b | ||
|
|
041c5e6d44 | ||
|
|
a2ce739192 | ||
|
|
ca4ad58a06 | ||
|
|
89df8fb692 | ||
|
|
9a021d2279 | ||
|
|
82e87805c3 | ||
|
|
844bfc5f25 | ||
|
|
706c68f69c | ||
|
|
13e0cc6b50 | ||
|
|
7af81f7665 | ||
|
|
278129b286 | ||
|
|
54c522c861 | ||
|
|
a034ee894c | ||
|
|
6f46764daa | ||
|
|
e1d482ea7c | ||
|
|
c34ec00d3a | ||
|
|
090abdee87 | ||
|
|
ce04a76b17 | ||
|
|
2953eed729 | ||
|
|
bf2b089c5c | ||
|
|
3107e63040 | ||
|
|
2ec8194d01 | ||
|
|
d113498c7b | ||
|
|
d8206ccbc7 | ||
|
|
fbd8de1c24 | ||
|
|
81d9f94a29 | ||
|
|
382cc444f0 | ||
|
|
0cec6f08ca | ||
|
|
2112e16cca | ||
|
|
35f80bd439 | ||
|
|
1dc44c0f62 | ||
|
|
eae3f7ce0a | ||
|
|
aa322d41aa | ||
|
|
95d23b1914 | ||
|
|
0464cdb43f | ||
|
|
35e4fe061d | ||
|
|
02924ad83e | ||
|
|
ff4213b59f | ||
|
|
c4e51247d8 | ||
|
|
1218a38f2c | ||
|
|
797f8087bc | ||
|
|
bf77ac6ba5 | ||
|
|
eafb006649 | ||
|
|
a9bf7a90ed | ||
|
|
ee7593bbe3 | ||
|
|
30843cd368 | ||
|
|
53195b064a | ||
|
|
dca2664707 | ||
|
|
e1dfc38a90 | ||
|
|
2e90e9c35b | ||
|
|
8f5110900c | ||
|
|
5e332983e2 | ||
|
|
6e240a3e9c | ||
|
|
a1f1775d15 | ||
|
|
5fbed0d1cd | ||
|
|
bd25225045 | ||
|
|
013eba0e79 | ||
|
|
78212e03d6 | ||
|
|
a8ea7b0858 | ||
|
|
0e97770c47 | ||
|
|
3d7bd7583b | ||
|
|
bfacac8683 | ||
|
|
d66c2b5fae | ||
|
|
72e44ce3d7 | ||
|
|
0806e0466c | ||
|
|
c05ca51238 | ||
|
|
1a4a5bfc57 | ||
|
|
be5d5aea6d | ||
|
|
8635b8ac84 | ||
|
|
d1b8370a4a | ||
|
|
1f57fd0407 | ||
|
|
671599c8b2 | ||
|
|
0b4fd52d63 | ||
|
|
e05f5fc50d | ||
|
|
da6250fc1f | ||
|
|
7d075cdcb7 | ||
|
|
3a55ff2119 | ||
|
|
b5b055e1ae | ||
|
|
0c99673581 | ||
|
|
709aa27031 | ||
|
|
5b01d63491 | ||
|
|
46b3d41b20 | ||
|
|
0b7ad2c804 | ||
|
|
8392d6c136 | ||
|
|
4ced7e9c80 | ||
|
|
3d120983da | ||
|
|
70aafd74a8 | ||
|
|
66415831ea | ||
|
|
2b7919fb3a | ||
|
|
09173fb727 | ||
|
|
de5de6284c | ||
|
|
de8ab35cb3 | ||
|
|
237b597e19 | ||
|
|
2d7a4bdb06 | ||
|
|
6f270a3648 | ||
|
|
8be2aaa751 | ||
|
|
5ede5ab4ce | ||
|
|
506f7c0764 | ||
|
|
4b686a4394 | ||
|
|
a18a601291 | ||
|
|
92fc50d4b0 | ||
|
|
57c812bc00 | ||
|
|
715b8c4683 | ||
|
|
b1bb7ec1a8 | ||
|
|
f6136dd036 | ||
|
|
cb49635231 | ||
|
|
e8f7adc7ca | ||
|
|
ab8061a57f | ||
|
|
f414355680 | ||
|
|
6dd043659c | ||
|
|
704ca366b3 | ||
|
|
cf15cbf0b3 | ||
|
|
de7c301654 | ||
|
|
48d2fc1599 | ||
|
|
839361594d | ||
|
|
40abe3f370 | ||
|
|
7a5a706397 | ||
|
|
59ea79d9e6 | ||
|
|
4e5898efd7 | ||
|
|
a512586140 | ||
|
|
28a0971cdf | ||
|
|
5c9827a33c | ||
|
|
f0362b2332 | ||
|
|
5bf48bc68f | ||
|
|
6e47d9a2e5 | ||
|
|
a480a318fd | ||
|
|
251f1d0047 | ||
|
|
1c3127e43b | ||
|
|
20a979173f | ||
|
|
4aad318446 | ||
|
|
13a5653c4e | ||
|
|
119ecb4259 | ||
|
|
8bd047174a | ||
|
|
416393a794 | ||
|
|
9e36cabcbf | ||
|
|
3731eba9b6 | ||
|
|
f707a43b3c | ||
|
|
7a96e8a292 | ||
|
|
90cce0ab56 | ||
|
|
41ed603abf | ||
|
|
cdce7f2044 | ||
|
|
6ae88514d8 | ||
|
|
c043840cb1 | ||
|
|
a831164d65 | ||
|
|
a41dc00160 | ||
|
|
5a1bf7d8fe | ||
|
|
075c423c62 | ||
|
|
d9813dbc90 | ||
|
|
50874eecfa | ||
|
|
3cea550d08 | ||
|
|
5e9d6f1cbd | ||
|
|
b1363d1a79 | ||
|
|
520923b5a7 | ||
|
|
2ba46e05ee | ||
|
|
90ed57f478 | ||
|
|
ab580103c7 | ||
|
|
1c6a83d0dd | ||
|
|
06f3a70f9a | ||
|
|
1fb68e8711 | ||
|
|
bd107e133f | ||
|
|
1c2d5f16c8 | ||
|
|
5738110cb6 | ||
|
|
6be122edc4 | ||
|
|
7979342edf | ||
|
|
2cdf5517cb | ||
|
|
7adcb76f68 | ||
|
|
acf65b4c23 | ||
|
|
d099c2a8db | ||
|
|
20f1257e88 | ||
|
|
fe0de111fd | ||
|
|
e7a0c1b6d0 | ||
|
|
da54b3d7e5 | ||
|
|
971abaea80 | ||
|
|
a76670f3b8 | ||
|
|
e13b618a65 | ||
|
|
cd1b89475c | ||
|
|
5d90b48790 | ||
|
|
c3cb186952 | ||
|
|
5ca743dd25 | ||
|
|
c9db5d234f | ||
|
|
4fd773d4ae | ||
|
|
5d67271acd | ||
|
|
d34dbbdb0b | ||
|
|
f52cefaa94 | ||
|
|
1c9b51c330 | ||
|
|
122854af77 | ||
|
|
2c127ae2d5 | ||
|
|
7db4455592 | ||
|
|
a5ace5e71d | ||
|
|
0d926f7632 | ||
|
|
af4f1083b7 | ||
|
|
186f16e688 | ||
|
|
99b1f69271 | ||
|
|
e54be1c4ee | ||
|
|
411621bf03 | ||
|
|
ca2ffd4fb3 | ||
|
|
3b20684dc7 | ||
|
|
b6db9789ee | ||
|
|
7a4daf799a | ||
|
|
389499d639 | ||
|
|
7b58a82840 | ||
|
|
9d818066a7 | ||
|
|
0238a29c7c | ||
|
|
383ba63c5a | ||
|
|
4e5e290ec2 | ||
|
|
d01065b9a1 | ||
|
|
607287a9d6 | ||
|
|
01b3cde79b | ||
|
|
5b0fea195d | ||
|
|
ce8341ca1f | ||
|
|
9493e8f42e | ||
|
|
b1aaf055b1 | ||
|
|
34e75f80bc | ||
|
|
f4d1a07b72 | ||
|
|
0db095e02a | ||
|
|
99f5580c37 | ||
|
|
30095a0c3f | ||
|
|
946c6967e9 | ||
|
|
d1e00099dc | ||
|
|
f49985697b | ||
|
|
d018d460e3 | ||
|
|
851a3128e4 | ||
|
|
bdb8a4a0cb | ||
|
|
2a410217e2 | ||
|
|
2c0e820d9a | ||
|
|
2326ea77e6 | ||
|
|
e6984f4058 | ||
|
|
aeea27b57b | ||
|
|
0f70bd7913 | ||
|
|
e8f95743cc | ||
|
|
fd0b8f3583 | ||
|
|
2a52b087fd | ||
|
|
c70cdd61ca | ||
|
|
5979db1270 | ||
|
|
0edc29dc72 | ||
|
|
5e4aaab91b | ||
|
|
59bbbd5e66 | ||
|
|
1e98ba27c6 | ||
|
|
2244b35a6d | ||
|
|
15ee7b39ac | ||
|
|
6a298d180d | ||
|
|
cb7d74a063 | ||
|
|
bc946053a3 | ||
|
|
bfe095b065 | ||
|
|
30bcd45a14 | ||
|
|
cd5ad7db64 | ||
|
|
1332e7d66a | ||
|
|
f44d3914ef | ||
|
|
949e8e5f51 | ||
|
|
1e78a14f1a | ||
|
|
4291ea47f7 | ||
|
|
b50706a7aa | ||
|
|
b20f87eef3 | ||
|
|
bc2e1a53cb | ||
|
|
e7d4d12e16 | ||
|
|
f348a7d4f4 | ||
|
|
9c82c36c71 | ||
|
|
480388133e | ||
|
|
5d24a2dc0f | ||
|
|
8160963110 | ||
|
|
d50d8b86cf | ||
|
|
b28e06608c | ||
|
|
cd411e5fb1 | ||
|
|
9daef50ce6 | ||
|
|
fae178f70b | ||
|
|
744208f701 | ||
|
|
85d8ae6b93 | ||
|
|
ff79cc9107 | ||
|
|
5100a2daf1 | ||
|
|
6e57b0219e | ||
|
|
3a002a1ddf | ||
|
|
4b0d956b3d | ||
|
|
85408961ba | ||
|
|
04b6794318 | ||
|
|
e86b6b2246 | ||
|
|
3314a472c3 | ||
|
|
aeeb408c74 | ||
|
|
18c39197e5 | ||
|
|
7eb8219419 | ||
|
|
2f915af690 | ||
|
|
272898a792 | ||
|
|
63c40b45e4 | ||
|
|
c17a678385 | ||
|
|
e2e56f45af | ||
|
|
05c1dcef9b | ||
|
|
cc5fe558ba | ||
|
|
68ee08440e | ||
|
|
b02b99003a | ||
|
|
e3306abbcb | ||
|
|
3d93527a8e | ||
|
|
8a19f2ac65 | ||
|
|
b7fa50be4c | ||
|
|
61d05fa4d7 | ||
|
|
42751f87d9 | ||
|
|
0fc3df45ce | ||
|
|
78dede2ac4 | ||
|
|
577a2715bd | ||
|
|
f88431adbf | ||
|
|
56de50de28 | ||
|
|
a48785ee5e | ||
|
|
3be73ad1ca | ||
|
|
03aa7e3044 | ||
|
|
91f6cae168 | ||
|
|
ddd584077c | ||
|
|
8201f0b6ea | ||
|
|
f2b5fcd706 | ||
|
|
950439e5b8 | ||
|
|
f24cdf5a05 | ||
|
|
d3b00532b1 | ||
|
|
b7ed0fce2a | ||
|
|
c1d2a9ab92 | ||
|
|
87a7642381 | ||
|
|
57d965aeba | ||
|
|
9b4e00c3fc | ||
|
|
97a4302b58 | ||
|
|
bac5121221 | ||
|
|
3462b1d1a3 | ||
|
|
54cc1cdcf7 | ||
|
|
0fd678e9a6 | ||
|
|
580762b4e6 | ||
|
|
5eaae83a01 | ||
|
|
c50136d675 | ||
|
|
494ea5c78c | ||
|
|
c8d0f788e0 | ||
|
|
ae263d60bd | ||
|
|
df3fe25702 | ||
|
|
566e6c813e | ||
|
|
c09a828f7b | ||
|
|
c5a0ce5a43 | ||
|
|
6d74601cf3 | ||
|
|
ee4892e345 | ||
|
|
557931f207 | ||
|
|
7fd2f292e7 | ||
|
|
b68d982619 | ||
|
|
cf058bc537 | ||
|
|
cc9680c1e8 | ||
|
|
b7553d5bdf | ||
|
|
4ad190a558 | ||
|
|
3a193655b3 | ||
|
|
e10a08f64d | ||
|
|
84e9400742 | ||
|
|
cc94c772cd | ||
|
|
4b6edaa01a | ||
|
|
45f831da4c | ||
|
|
8da7919a43 | ||
|
|
f52d66a954 | ||
|
|
55dfbb9446 | ||
|
|
4d3212b31f | ||
|
|
973dc9e1e2 | ||
|
|
8e1422fb37 | ||
|
|
881641f0b7 | ||
|
|
6a378a6362 | ||
|
|
879dadba78 | ||
|
|
5266720c62 | ||
|
|
dca2b67338 | ||
|
|
d1b1da3414 | ||
|
|
48a359b69e | ||
|
|
2a8f9a7c04 | ||
|
|
ea691aa2a0 | ||
|
|
3da1e9a4b9 | ||
|
|
f1b42cedda | ||
|
|
2598579d84 | ||
|
|
c5b6ec209a | ||
|
|
13705999f7 | ||
|
|
fbe812b9bc | ||
|
|
4697f0274f | ||
|
|
9597c2b808 | ||
|
|
3817202b9c | ||
|
|
ed960e5a71 | ||
|
|
8b08ca2d00 | ||
|
|
aff8008baf | ||
|
|
c922015521 | ||
|
|
b20adf2281 | ||
|
|
4ed9edb104 | ||
|
|
bb244d527c | ||
|
|
7f1d13dfbf | ||
|
|
3185b0940b | ||
|
|
d709a47b93 | ||
|
|
b02f724e7e | ||
|
|
013a0e25d5 | ||
|
|
6d2f77851e | ||
|
|
131055aefc | ||
|
|
0682f8793c | ||
|
|
fdf4a53283 | ||
|
|
ccc1db02a0 | ||
|
|
3db8d3dfb6 | ||
|
|
4e15e2055c | ||
|
|
72a3e08907 | ||
|
|
f8c0e796df | ||
|
|
fd40113e48 | ||
|
|
ca8b961e60 | ||
|
|
b6e3709e74 | ||
|
|
4202387c52 | ||
|
|
cd4e647816 | ||
|
|
fd97a09e64 | ||
|
|
42d2594071 | ||
|
|
ff70cf9b5f | ||
|
|
3a31694147 | ||
|
|
05236f0a7a | ||
|
|
a475526805 | ||
|
|
3c1a2cde33 | ||
|
|
a1f7168d2a | ||
|
|
1e1c2f8de2 | ||
|
|
76e67db04b | ||
|
|
9d06e99b58 | ||
|
|
70c3514996 | ||
|
|
9aeb587d6c | ||
|
|
51041d0f15 | ||
|
|
543e8a224c | ||
|
|
ea378fe837 | ||
|
|
de9ee295be | ||
|
|
3a8d6a6f16 | ||
|
|
5ac58d3b83 | ||
|
|
ada2be94f2 | ||
|
|
866991df4c | ||
|
|
7613938181 | ||
|
|
4eb4069c15 | ||
|
|
f097e472f4 | ||
|
|
c46b97ec37 | ||
|
|
1994cd7ba2 | ||
|
|
8cb3a77022 | ||
|
|
1ed4eb46f2 | ||
|
|
7c31da5a95 | ||
|
|
1f245b3791 | ||
|
|
4af45394f9 | ||
|
|
c1c5a488d0 | ||
|
|
554d1b88fc | ||
|
|
5e18d5cf4e | ||
|
|
8a639d39fc | ||
|
|
e43425cf16 | ||
|
|
26af3ce525 | ||
|
|
5f316f8b96 | ||
|
|
35060f4954 | ||
|
|
0b2f1dda48 | ||
|
|
1a555449ec | ||
|
|
5ba61e5399 | ||
|
|
0809703d2b | ||
|
|
55b423fbb5 | ||
|
|
e08ec11fd4 | ||
|
|
0c2f65a939 | ||
|
|
29e34bd2c0 | ||
|
|
6abc2bf72d | ||
|
|
a10fe84a83 | ||
|
|
7d9c4d052c | ||
|
|
f8d69dfe8e | ||
|
|
2841714817 | ||
|
|
35af03b2e5 | ||
|
|
ce735d8d68 | ||
|
|
ae018eab42 | ||
|
|
484c8397e3 | ||
|
|
b8de36c585 | ||
|
|
59ba292edd | ||
|
|
bc9c4fe17b | ||
|
|
7253f64d26 | ||
|
|
28e9c56a4b | ||
|
|
68f0f1b404 | ||
|
|
96f152d57c | ||
|
|
f1a35527ee | ||
|
|
039ff0ca8e | ||
|
|
85afa4788b | ||
|
|
53c5f03c32 | ||
|
|
e86499d990 | ||
|
|
3ca071c612 | ||
|
|
88e0f97798 | ||
|
|
d78b84a12f | ||
|
|
5c2b185374 | ||
|
|
8339ff3c1c | ||
|
|
73e58fa090 | ||
|
|
e2cda2dc65 | ||
|
|
090d02a65f | ||
|
|
a0e88477c1 | ||
|
|
4e70a14c29 | ||
|
|
da45d99b8f | ||
|
|
14131cf020 | ||
|
|
dd5b36779d | ||
|
|
f67989afea | ||
|
|
14fef4a0d3 | ||
|
|
d3439d5526 | ||
|
|
34bb950889 | ||
|
|
489efa24f7 | ||
|
|
9840ae9e96 | ||
|
|
d375e9b86c | ||
|
|
722918abd6 | ||
|
|
48fe8d1cb8 | ||
|
|
1000cdda09 | ||
|
|
d71b59b817 | ||
|
|
95b92c12ac | ||
|
|
4597201560 | ||
|
|
a60370255e | ||
|
|
21909cae04 | ||
|
|
176ea20fef | ||
|
|
574435687d | ||
|
|
1a279ca158 | ||
|
|
0ed929f24b | ||
|
|
41eeed981f | ||
|
|
8e68e0321c | ||
|
|
881b32521b | ||
|
|
b98876e265 | ||
|
|
dbb5bcb784 | ||
|
|
fce194ce08 | ||
|
|
d95b43f347 | ||
|
|
9ca9773e9d | ||
|
|
13b2568358 | ||
|
|
7a2d12bb47 | ||
|
|
2152bc5fca | ||
|
|
11aecf1af2 | ||
|
|
903d6c80fe | ||
|
|
585221c58c | ||
|
|
8ef11a38c9 | ||
|
|
5204524691 | ||
|
|
9af7e8cff0 | ||
|
|
f94a15b0fa | ||
|
|
5e33898a08 | ||
|
|
9c83c57f1c | ||
|
|
1a98b49f1b | ||
|
|
0e8f0481d4 | ||
|
|
1d0ef83078 | ||
|
|
4ab217ba04 | ||
|
|
6580af65c1 | ||
|
|
cdf16dd905 | ||
|
|
4a1a5fa076 | ||
|
|
298684aaa0 | ||
|
|
005c027274 | ||
|
|
f4495c5c80 | ||
|
|
f862c626a1 | ||
|
|
6487bb071b | ||
|
|
e7296d03d3 | ||
|
|
139bb8f094 | ||
|
|
d30ed7fb8a | ||
|
|
13df7fcee0 | ||
|
|
84ecbc4c89 | ||
|
|
4a010ce7cd | ||
|
|
40698c8fd0 | ||
|
|
3adaf44f7b | ||
|
|
6e4ecd11a1 | ||
|
|
3983fecaf1 | ||
|
|
7effcff245 | ||
|
|
793a994ce6 | ||
|
|
19bf5e2ff1 | ||
|
|
16ad3d5c88 | ||
|
|
ff2d98596f | ||
|
|
072698d606 | ||
|
|
0b098045f1 | ||
|
|
ddb6b3b262 | ||
|
|
7f2470f1f6 | ||
|
|
488b964c52 | ||
|
|
b4d3f696bf | ||
|
|
9cc4d363b2 | ||
|
|
b646caffd0 | ||
|
|
b9bc3e36b8 | ||
|
|
24aaf7a034 | ||
|
|
80f2e40e67 | ||
|
|
e95b73dfac | ||
|
|
c00e3e8c0a | ||
|
|
2a12610a46 | ||
|
|
d466a05915 | ||
|
|
e05d6bfcdc | ||
|
|
b49dd02e3d |
63
.clang-format
Normal file
@@ -0,0 +1,63 @@
|
||||
# Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
|
||||
#
|
||||
# You may use this file under the terms of the 3-clause BSD license.
|
||||
# See the file LICENSE from this package for details.
|
||||
|
||||
# This is the clang-format configuration style to be used by Qt,
|
||||
# based on the rules from https://wiki.qt.io/Qt_Coding_Style and
|
||||
# https://wiki.qt.io/Coding_Conventions
|
||||
|
||||
---
|
||||
# Webkit style was loosely based on the Qt style
|
||||
BasedOnStyle: WebKit
|
||||
|
||||
Standard: Cpp11
|
||||
ColumnLimit: 0
|
||||
|
||||
# Disable reflow of qdoc comments: indentation rules are different.
|
||||
# Translation comments are also excluded
|
||||
CommentPragmas: "^!|^:"
|
||||
|
||||
# We want a space between the type and the star for pointer types
|
||||
PointerBindsToType: false
|
||||
|
||||
# We want to break before the operators, but not before a '='
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
|
||||
# Braces are usually attached, but not after functions or classes declaration
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
|
||||
# The coding style does not specify the following, but this is what gives
|
||||
# results closest to the existing code.
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
|
||||
# Ideally we should also allow less short function in a single line, but
|
||||
# clang-format does not handle that
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
|
||||
# The coding style specifies some include order categories, but also tells to
|
||||
# separate categories with an empty line. It does not specify the order within
|
||||
# the categories. Since the SortInclude feature of clang-format does not
|
||||
# re-order includes separated by empty lines, the feature is not used.
|
||||
SortIncludes: false
|
||||
|
||||
# macros for which the opening brace stays attached
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ]
|
||||
|
||||
# Allow two empty lines for structuring
|
||||
MaxEmptyLinesToKeep: 2
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
|
||||
91
.drone.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
#
|
||||
# We are building GCC with make and Clang with ninja, the combinations are more
|
||||
# or less arbitrarily chosen. We just want to check that both compilers and both
|
||||
# CMake generators work. It's unlikely that a specific generator only breaks
|
||||
# with a specific compiler.
|
||||
#
|
||||
|
||||
workspace:
|
||||
base: /drone
|
||||
path: src/github.com/owncloud/client
|
||||
|
||||
branches:
|
||||
- master
|
||||
- 2.4
|
||||
|
||||
clone:
|
||||
git:
|
||||
image: plugins/git
|
||||
pull: true
|
||||
tags: false
|
||||
|
||||
pipeline:
|
||||
prepare-clang:
|
||||
image: owncloudci/client:latest
|
||||
pull: true
|
||||
environment:
|
||||
- LC_ALL=C.UTF-8
|
||||
commands:
|
||||
- mkdir clang-build
|
||||
- cd clang-build
|
||||
- cmake -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE="Debug" -DUNIT_TESTING=1 ..
|
||||
|
||||
building-clang:
|
||||
image: owncloudci/client:latest
|
||||
pull: true
|
||||
environment:
|
||||
- LC_ALL=C.UTF-8
|
||||
commands:
|
||||
- cd clang-build
|
||||
- ninja -j4
|
||||
|
||||
testing-clang:
|
||||
image: owncloudci/client:latest
|
||||
pull: true
|
||||
environment:
|
||||
- LC_ALL=C.UTF-8
|
||||
commands:
|
||||
- cd clang-build
|
||||
- useradd -m -s /bin/bash tester
|
||||
- chown -R tester:tester .
|
||||
- su-exec tester ctest --output-on-failure
|
||||
|
||||
prepare-gcc:
|
||||
image: owncloudci/client:latest
|
||||
pull: true
|
||||
environment:
|
||||
- LC_ALL=C.UTF-8
|
||||
commands:
|
||||
- mkdir gcc-build
|
||||
- cd gcc-build
|
||||
- cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE="Debug" -DUNIT_TESTING=1 ..
|
||||
|
||||
building-gcc:
|
||||
image: owncloudci/client:latest
|
||||
pull: true
|
||||
environment:
|
||||
- LC_ALL=C.UTF-8
|
||||
commands:
|
||||
- cd gcc-build
|
||||
- make -j4
|
||||
|
||||
testing-gcc:
|
||||
image: owncloudci/client:latest
|
||||
pull: true
|
||||
environment:
|
||||
- LC_ALL=C.UTF-8
|
||||
commands:
|
||||
- cd gcc-build
|
||||
- useradd -m -s /bin/bash tester
|
||||
- chown -R tester:tester .
|
||||
- su-exec tester ctest --output-on-failure
|
||||
|
||||
notify-slack:
|
||||
image: plugins/slack
|
||||
pull: true
|
||||
secrets: [ slack_webhook ]
|
||||
channel: desktop
|
||||
when:
|
||||
local: false
|
||||
status: [ changed, failure ]
|
||||
event: [ push ]
|
||||
1
.git-blame-ignore-revs
Normal file
@@ -0,0 +1 @@
|
||||
c8d0f788e00bdae125a26d9159ce9efdd6325cd2 # Initial application of clang-format
|
||||
@@ -2,7 +2,7 @@
|
||||
Please try to only report a bug if it happens with the latest version
|
||||
The latest version can be seen by checking the ChangeLog: https://owncloud.org/changelog/desktop/
|
||||
|
||||
For support try: https://central.owncloud.org/c/help/desktop-file-sync
|
||||
For support try: https://central.owncloud.org/c/desktop-client
|
||||
--->
|
||||
|
||||
|
||||
108
.github/release_template.md
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
This is the template for new release issues.
|
||||
(originated from https://github.com/owncloud/client/wiki/Release%20Checklist%20Template)
|
||||
-->
|
||||
|
||||
Copy below text into a task and tick the items:
|
||||
|
||||
```
|
||||
Some weeks before the release:
|
||||
* [ ] Check if we should update the bundled sqlite3 (https://github.com/owncloud/client/tree/master/src/3rdparty/sqlite3)
|
||||
* [ ] Check if we should update Sparkle on build machine (https://github.com/sparkle-project/Sparkle/releases)
|
||||
* [ ] Ensure NSIS is up to date on the build machine
|
||||
* [ ] Ensure up-to-date dependencies (e.g. [latest Qt version](http://qt-project.org/downloads#qt-lib) is installed on the machine and picked up (cmake output)
|
||||
* [ ] Ensure the crash reporter server is up
|
||||
* [ ] Check crash reporter for bad crashes
|
||||
* [ ] Ensure Windows Overlay DLLs are rebuilt
|
||||
* [ ] Check nightly builds are up and running, that is Jenkins jobs ownCloud-client-linux, ownCloud-client-osx and ownCloud-client-win32 all green.
|
||||
* [ ] Ensure Linux nightlies are built too for all distros https://build.opensuse.org/package/show/isv:ownCloud:community:nightly/owncloud-client
|
||||
* [ ] Build branded clients through the scripting machine and smoke test one or two branded clients (especially with predefined url)
|
||||
* [ ] Upload a nightly build of the windows version to virustotal.com
|
||||
* Contact AV vendors whom's engine reports a virus
|
||||
* [ ] Documentation should be online before the release http://doc.owncloud.org/desktop/1.X/
|
||||
* [ ] QA goes over https://github.com/owncloud/mirall/wiki/Testing-Scenarios
|
||||
* [ ] Make sure to have `client/ChangeLog` updated
|
||||
* use `git log --format=oneline v<lastrelease>...master` if your memory fails you
|
||||
* [ ] check if enterprise issues are fixed
|
||||
|
||||
One week before the release:
|
||||
* [ ] Communicate the release schedule on mailinglist release-coordination@owncloud.com. Give a high level overview of the upcoming new features, changes etc.
|
||||
* [ ] Ensure marketing is aware (marketing@owncloud.com) and prepared for the release (social, .com website, cust. communications)
|
||||
* [ ] Inform GCX knows the next version is about 1 week out (gcx@owncloud.com)
|
||||
|
||||
For all Betas and RCs:
|
||||
* [ ] Branch off a release branch called VERSION-rcX or VERSION-betaX (without v, v is for tags)
|
||||
* [ ] Edit ```VERSION.cmake``` to set the suffix to beta1, beta2 etc. Commit the result to the release branch only
|
||||
* [ ] Create build for Windows using rotor job owncloud-client-win32 (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Create build for Mac using rotor, job owncloud-client-osx (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Create the beta tarball using Jenkins job ownCloud-client-source
|
||||
* [ ] Create Linux builds using rotor job owncloud-client-linux building (this magically interacts with the ownCloud-client-source job)
|
||||
* [ ] theme 'ownCloud' -> isv:ownCloud:community:testing
|
||||
* [ ] theme 'testpilotcould' -> isv:ownCloud:testpilot:testing
|
||||
* [ ] Copy builds from ```daily``` to ```testing``` on download.owncloud.com, double check the download links.
|
||||
* [ ] Create a pull request to the owncloud.org repository to update the install page (strings.php, page-desktop.php) and the changelog on owncloud.org. From now on download packages from the staging webserver.
|
||||
* [ ] Inform community mailinglists devel@owncloud.org and testpilots@owncloud.org
|
||||
* [ ] Announce on https://central.owncloud.org
|
||||
* [ ] Create a signed tag using ```git tag -u E94E7B37 tagname``` (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
|
||||
* [ ] Check crash reporter
|
||||
|
||||
For first Beta of a Major or Minor release:
|
||||
* [ ] branch off master to new version branch (e.g. master -> 2.1, when releasing 2.1)
|
||||
* [ ] Adjust `VERSION.cmake` in master and count up (e.g. 2.2)
|
||||
* [ ] Adjust translation jobs for [client](https://ci.owncloud.org/view/translation-sync/job/translation-sync-client/) and [NSIS](https://ci.owncloud.org/view/translation-sync/job/translation-sync-client-nsis/) to point to the release branch (e.g. 2.1).
|
||||
* [ ] Make sure there is a job for the docs of the new master branch and the current release branch on rotor.
|
||||
|
||||
Day before Release:
|
||||
* [ ] Check the translations coming from transifex: All synchronized?
|
||||
* [ ] Run the tx.pl scripts on the final code tag
|
||||
* [ ] Run ```make test```
|
||||
* [ ] Run smashbox on the final code tag
|
||||
* [ ] Inform product management and marketing that we are 1 day out
|
||||
|
||||
On Release Day (for final release):
|
||||
* [ ] Branch off a release branch called like the version (without v, v is for tags)
|
||||
* [ ] Double check ```VERSION.cmake```: Check the version number settings and suffix (beta etc.) to be removed. Commit change to release branch only!
|
||||
* [ ] Make sure to increase the version number of the branched of release, e.g. if you release 2.3.2 then you should change VERSION.cmake in 2.3 to 2.3.3 since that branch now will be 2.3.3
|
||||
* [ ] Add last updates to Changelog in the client source repository.
|
||||
* [ ] Create tar ball (automated by `ownCloud-client-source` jenkins job) and **immediately** sign it (asc file). (https://github.com/owncloud/enterprise/wiki/Desktop-Signing-Knowledge)
|
||||
* [ ] Create build for Windows using rotor job owncloud-client-win32 (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Create build for Mac using rotor, job owncloud-client-osx (uncheck the "nightly build" checkbox, check the "sign package" checkboxes) both themes 'ownCloud' and 'testpilotcould'
|
||||
* [ ] Stop publishing on OBS
|
||||
* [ ] Branch isv:ownCloud:desktop to isv:ownCloud:desktop:client-X.Y.Z before overwriting https://github.com/owncloud/administration/blob/master/jenkins/obs_integration/obs-backup-prj.sh
|
||||
* [ ] Create Linux builds using rotor job owncloud-client-linux (this magically interacts with the ownCloud-client-source job)
|
||||
* Check if patches still apply in the linux packages
|
||||
* Update [OBS repository](https://build.opensuse.org/project/show?project=isv%3AownCloud%3Adesktop) `isv:ownCloud:desktop`
|
||||
* [ ] theme 'ownCloud' -> isv:ownCloud:desktop
|
||||
* [ ] theme 'testpilotcloud' -> isv:ownCloud:testpilot
|
||||
* [ ] Linux: Update the testing repository to the latest stable version.
|
||||
* [ ] Inform GCX that a new tarball is available.
|
||||
* [ ] Copy builds and source tar ball from ```daily``` to ```stable``` on download.owncloud.com, double check the download links.
|
||||
* [ ] Check if the following packages are on download.owncloud.com/desktop/stable:
|
||||
* Windows binary package
|
||||
* Mac binary package
|
||||
* source tarballs
|
||||
* [ ] Create a pull request to the owncloud.org repository to update the install page (strings.php, page-desktop.php) and the changelog on owncloud.org. From now on download packages from the staging webserver.
|
||||
* [ ] Re-download Mac builds and check signature. Interactive in installer window
|
||||
* [ ] Re-download Win build check signature. From Mac or Linux: ```osslsigncode verify ownCloud-version-setup.exe```
|
||||
* [ ] Mac: Perform smoke test (Install, make sure it does not explode, and check if all version indicators are correct)
|
||||
* [ ] Win: Perform smoke test (Install, make sure it does not explode, and check if all version indicators are correct)
|
||||
* [ ] Linux: Smoke test
|
||||
* [ ] Linux: Re-enable OBS publishing
|
||||
* Let obs build and publish exactly once. then
|
||||
* [ ] disable publishing and rebuild for the owncloud-client package and all its dependencies.
|
||||
* [ ] double-check that there are no _aggregatepac from other projects, if so disable rebuilding there too.
|
||||
* [ ] Update ASCII Changelog on http://download.owncloud.com/download/changelog-client
|
||||
* [ ] Announce on https://central.owncloud.org
|
||||
* [ ] Announce on announcements@owncloud.org
|
||||
* [ ] Create git signed tag in client repository using ```git tag -u E94E7B37 tagname```
|
||||
* [ ] Send out Social (tweet, blog, other)
|
||||
* [ ] Send out customer communication (if any)
|
||||
* [ ] Inform GCX that the new version is released (gcx@owncloud.com)
|
||||
* [ ] Inform release-coordination@owncloud.com
|
||||
* [ ] Ensure marketing is aware (marketing@owncloud.com)
|
||||
* [ ] Take pride and celebrate!
|
||||
* [ ] Also update the testpilotcloud builds for that release version and make sure they show up on the download page
|
||||
* [ ] Days later: Update the updater script ```clientupdater.php``` (check the crash reporter if auto update is a good idea or we need a new release)
|
||||
* [ ] Tell GCX to increment the minimum supported version for enterprise customers
|
||||
* [ ] Check if minimum.supported.desktop.version (https://github.com/owncloud/core/blob/master/config/config.sample.php#L1152) needs to be updated in server
|
||||
```
|
||||
6
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
||||
[submodule "doc/ocdoc"]
|
||||
path = doc/ocdoc
|
||||
url = https://github.com/owncloud/documentation
|
||||
[submodule "src/3rdparty/qtmacgoodies"]
|
||||
path = src/3rdparty/qtmacgoodies
|
||||
url = https://github.com/guruz/qtmacgoodies.git
|
||||
@@ -10,6 +7,3 @@
|
||||
[submodule "src/3rdparty/libcrashreporter-qt"]
|
||||
path = src/3rdparty/libcrashreporter-qt
|
||||
url = git://github.com/dschmidt/libcrashreporter-qt.git
|
||||
[submodule "src/3rdparty/qtkeychain"]
|
||||
path = src/3rdparty/qtkeychain
|
||||
url = https://github.com/frankosterfeld/qtkeychain.git
|
||||
|
||||
37
.travis.yml
@@ -1,37 +0,0 @@
|
||||
sudo: required
|
||||
|
||||
language: cpp
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
branches:
|
||||
only:
|
||||
- coverity_scan
|
||||
|
||||
before_install:
|
||||
- sudo sh -c "echo 'deb http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- sudo sh -c "echo 'deb-src http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_14.04/ /' >> /etc/apt/sources.list.d/owncloud-client.list"
|
||||
- wget http://download.opensuse.org/repositories/isv:ownCloud:desktop/Ubuntu_14.04/Release.key
|
||||
- sudo apt-key add - < Release.key
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y build-dep owncloud-client
|
||||
- checkout=$(git show-ref --head --hash head)
|
||||
- cd ../
|
||||
- wget https://scan.coverity.com/download/linux-64 --post-data "token=$token&project=owncloud%2Fmirall" -O coverity_tool.tgz
|
||||
- mkdir coverity
|
||||
- tar -xvf coverity_tool.tgz -C coverity --strip-components=1
|
||||
- export PATH=$PATH:$PWD/coverity/bin/
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
|
||||
install:
|
||||
- cd ../
|
||||
- mkdir client-build
|
||||
- cd client-build
|
||||
- cmake -DCMAKE_BUILD_TYPE="Debug" $TRAVIS_BUILD_DIR
|
||||
- cov-build --dir cov-int make
|
||||
- tar czvf client.tgz cov-int
|
||||
- curl --form token=$token --form email=lukas@statuscode.ch --form file=@$PWD/client.tgz --form version="$checkout" --form description="$checkout" https://scan.coverity.com/builds?project=owncloud%2Fmirall
|
||||
|
||||
# Hack to stop processing
|
||||
script: true
|
||||
133
CMakeLists.txt
@@ -22,16 +22,19 @@ else()
|
||||
set(APPLICATION_REV_DOMAIN_INSTALLER ${APPLICATION_REV_DOMAIN})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED APPLICATION_SHORTNAME)
|
||||
set ( APPLICATION_SHORTNAME ${APPLICATION_NAME} )
|
||||
endif()
|
||||
|
||||
# For usage in XML files we preprocess
|
||||
string(REPLACE "&" "&" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME}")
|
||||
string(REPLACE "<" "<" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME_XML_ESCAPED}")
|
||||
string(REPLACE ">" ">" APPLICATION_NAME_XML_ESCAPED "${APPLICATION_NAME_XML_ESCAPED}")
|
||||
|
||||
set(PACKAGE "${APPLICATION_SHORTNAME}-client")
|
||||
if (NOT DEFINED LINUX_PACKAGE_SHORTNAME)
|
||||
set(LINUX_PACKAGE_SHORTNAME "${APPLICATION_SHORTNAME}")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED PACKAGE)
|
||||
set(PACKAGE "${LINUX_PACKAGE_SHORTNAME}-client")
|
||||
endif()
|
||||
|
||||
set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
|
||||
|
||||
if(NOT CRASHREPORTER_EXECUTABLE)
|
||||
@@ -41,7 +44,13 @@ endif()
|
||||
include(Warnings)
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/VERSION.cmake)
|
||||
# For config.h
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
# Allows includes based on src/ like #include "common/utility.h" or #include "csync/csync.h"
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src
|
||||
)
|
||||
|
||||
# disable the crashreporter if libcrashreporter-qt is not available or we're building for ARM
|
||||
if( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" OR NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/3rdparty/libcrashreporter-qt/CMakeLists.txt")
|
||||
@@ -120,7 +129,22 @@ if(NO_MSG_HANDLER)
|
||||
add_definitions(-DNO_MSG_HANDLER=1)
|
||||
endif()
|
||||
|
||||
# this option creates only libocsync and libowncloudsync
|
||||
# this option builds the shell integration
|
||||
option(BUILD_SHELL_INTEGRATION "BUILD_SHELL_INTEGRATION" ON)
|
||||
|
||||
# this option builds/installs the generic shell integration icons
|
||||
option(BUILD_SHELL_INTEGRATION_ICONS "BUILD_SHELL_INTEGRATION_ICONS" ON)
|
||||
|
||||
# this options builds the dolphin integration plugin
|
||||
option(BUILD_SHELL_INTEGRATION_DOLPHIN "BUILD_SHELL_INTEGRATION_DOLPHIN" ON)
|
||||
|
||||
# this options builds the nautilus (like) integration plugins
|
||||
option(BUILD_SHELL_INTEGRATION_NAUTILUS "BUILD_SHELL_INTEGRATION_NAUTILUS" ON)
|
||||
|
||||
# this option builds the client
|
||||
option(BUILD_CLIENT "BUILD_CLIENT" ON)
|
||||
|
||||
# this option creates only libocsync and libowncloudsync (NOTE: BUILD_CLIENT needs to be on)
|
||||
option(BUILD_LIBRARIES_ONLY "BUILD_LIBRARIES_ONLY" OFF)
|
||||
|
||||
# When this option is enabled, 5xx errors are not added to the blacklist
|
||||
@@ -153,34 +177,34 @@ if(APPLE)
|
||||
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL 1.0.0 REQUIRED)
|
||||
if(BUILD_CLIENT)
|
||||
if(APPLE)
|
||||
find_package(Sparkle)
|
||||
endif(APPLE)
|
||||
|
||||
if(APPLE)
|
||||
find_package(Sparkle)
|
||||
endif(APPLE)
|
||||
|
||||
if(UNIX)
|
||||
find_package(INotify REQUIRED)
|
||||
else()
|
||||
find_package(INotify)
|
||||
endif()
|
||||
find_package(Sphinx)
|
||||
find_package(PdfLatex)
|
||||
|
||||
find_package(SQLite3 3.8.0 REQUIRED)
|
||||
# On some OS, we want to use our own, not the system sqlite
|
||||
if (USE_OUR_OWN_SQLITE3)
|
||||
include_directories(BEFORE ${SQLITE3_INCLUDE_DIR})
|
||||
if (WIN32)
|
||||
add_definitions(-DSQLITE_API=__declspec\(dllimport\))
|
||||
if(UNIX)
|
||||
find_package(INotify REQUIRED)
|
||||
else()
|
||||
find_package(INotify)
|
||||
endif()
|
||||
find_package(Sphinx)
|
||||
find_package(PdfLatex)
|
||||
|
||||
find_package(SQLite3 3.8.0 REQUIRED)
|
||||
# On some OS, we want to use our own, not the system sqlite
|
||||
if (USE_OUR_OWN_SQLITE3)
|
||||
include_directories(BEFORE ${SQLITE3_INCLUDE_DIR})
|
||||
if (WIN32)
|
||||
add_definitions(-DSQLITE_API=__declspec\(dllimport\))
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
|
||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
configure_file(test/test_journal.db "${CMAKE_BINARY_DIR}/test/test_journal.db" COPYONLY)
|
||||
if (NOT DEFINED APPLICATION_ICON_NAME)
|
||||
set(APPLICATION_ICON_NAME ${APPLICATION_SHORTNAME})
|
||||
endif()
|
||||
|
||||
include(OwnCloudCPack.cmake)
|
||||
|
||||
@@ -191,18 +215,46 @@ add_definitions( -D__USE_MINGW_ANSI_STDIO=1 )
|
||||
add_definitions( -DNOMINMAX )
|
||||
endif( WIN32 )
|
||||
|
||||
include(QtVersionAbstraction)
|
||||
setup_qt()
|
||||
if (${Qt5Core_VERSION_MAJOR} EQUAL "5")
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "6" OR ${Qt5Core_VERSION_MINOR} GREATER 6)
|
||||
else()
|
||||
message(STATUS "If possible compile me with Qt 5.6 or higher.")
|
||||
endif()
|
||||
if (${Qt5Core_VERSION_MINOR} EQUAL "9" OR ${Qt5Core_VERSION_MINOR} GREATER 9)
|
||||
else()
|
||||
message(STATUS "For HTTP2 use Qt 5.9.2 or higher.")
|
||||
endif()
|
||||
endif()
|
||||
message("Qt ${Qt5Core_VERSION} at ${Qt5Core_INCLUDE_DIRS}")
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
|
||||
# Handle Translations, pick all client_* files from trans directory.
|
||||
file( GLOB TRANS_FILES ${CMAKE_SOURCE_DIR}/translations/client_*.ts)
|
||||
set(TRANSLATIONS ${TRANS_FILES})
|
||||
|
||||
add_subdirectory(csync)
|
||||
add_subdirectory(src)
|
||||
if(NOT BUILD_LIBRARIES_ONLY)
|
||||
add_subdirectory(shell_integration)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(doc/dev)
|
||||
add_subdirectory(admin)
|
||||
endif(NOT BUILD_LIBRARIES_ONLY)
|
||||
# Make sure we set this before recursing into child folders.
|
||||
set(WITH_TESTING ${UNIT_TESTING})
|
||||
|
||||
if(BUILD_CLIENT)
|
||||
add_subdirectory(src)
|
||||
if(NOT BUILD_LIBRARIES_ONLY)
|
||||
add_subdirectory(man)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(doc/dev)
|
||||
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/admin)
|
||||
add_subdirectory(admin)
|
||||
endif(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/admin)
|
||||
endif(NOT BUILD_LIBRARIES_ONLY)
|
||||
endif()
|
||||
|
||||
if(BUILD_SHELL_INTEGRATION)
|
||||
add_subdirectory(shell_integration)
|
||||
endif()
|
||||
|
||||
if(UNIT_TESTING)
|
||||
include(CTest)
|
||||
@@ -210,10 +262,13 @@ if(UNIT_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif(UNIT_TESTING)
|
||||
|
||||
configure_file(config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
configure_file(version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||
|
||||
if(BUILD_OWNCLOUD_OSX_BUNDLE)
|
||||
install(FILES sync-exclude.lst DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/)
|
||||
configure_file(sync-exclude.lst bin/${OWNCLOUD_OSX_BUNDLE}/Contents/Resources/sync-exclude.lst COPYONLY)
|
||||
else()
|
||||
elseif(BUILD_CLIENT)
|
||||
install( FILES sync-exclude.lst DESTINATION ${SYSCONFDIR}/${APPLICATION_SHORTNAME} )
|
||||
configure_file(sync-exclude.lst bin/sync-exclude.lst COPYONLY)
|
||||
endif()
|
||||
|
||||
@@ -23,7 +23,7 @@ If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
||||
Help us to maximize the effort we can spend fixing issues and adding new
|
||||
features, by not reporting duplicate issues.
|
||||
|
||||
[template]: https://raw.github.com/owncloud/client/master/issue_template.md
|
||||
[template]: https://raw.github.com/owncloud/client/master/.github/issue_template.md
|
||||
[mailinglist]: https://mail.kde.org/mailman/listinfo/owncloud
|
||||
[forum]: http://forum.owncloud.org/
|
||||
[irc]: http://webchat.freenode.net/?channels=owncloud&uio=d4
|
||||
|
||||
175
ChangeLog
@@ -1,7 +1,178 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
version 2.3.0 (2017-02-xx)
|
||||
version 2.4.3 (2018-08-xx)
|
||||
* Windows: Don't ignore files with FILE_ATTRIBUTE_TEMPORARY (#6696, #6610)
|
||||
* OAuth2: Fix infinite loop when the refresh token is expired
|
||||
* Windows MSI: Fix crash in the auto updater
|
||||
* Nautilus: Guard against None state (#6643)
|
||||
|
||||
version 2.4.2 (2018-07-18)
|
||||
* Linux: Tray workarounds (#6545)
|
||||
* Fix nautilus/nemo shell issues (#6393, #6406)
|
||||
* Updater: Add update channel feature (#6259)
|
||||
* Updater: Support EXE->MSI upgrade
|
||||
* SyncJournal: Fixes for sync folders on removable media (#6049, #6049)
|
||||
* SslButton: Add HTTP/2 info (#3146)
|
||||
* Fix assert when using ownCloud server 5 (which you should not) (#6403)
|
||||
* Normalize local path (#4424)
|
||||
* Blacklisting must prevent parent etag updates (#6411)
|
||||
* macdeployqt: Adjust minimum version based on our Qt (#5932)
|
||||
* macOS: Unload the Finder extension on exit (#5382, #3819)
|
||||
* Upload: Adjust timeout for final job based on file size (#6527)
|
||||
* Sync: When detecting a local move, keep the local mtime (#6629)
|
||||
* Credentials: Retry fetching from the keychain in case the keychain is still starting (#4274, #6522)
|
||||
* OAuth2: Try to refresh the token even if the credentials weren't ready (#6522)
|
||||
|
||||
version 2.4.1 (2018-02-xx)
|
||||
* Ignore files with file names that can't be encoded for the filesystem (#6287, #5676, #5719)
|
||||
* Issues: Speed up insertion and add hard upper limit (#6272)
|
||||
* Notifications: Fix "Dismiss" action
|
||||
* Notifications: Fix timer invocation on macOS
|
||||
* Notifications: Immediately poll when account online
|
||||
* Protocol: Remove entries for auto resolved conflicts (#6316)
|
||||
* owncloudcmd: Set proxy before capabilities call (#6281)
|
||||
* owncloudcmd: Do not do the capability call when --nonshib is passed
|
||||
* Avatars: Use old location for servers <10 (#6279)
|
||||
* Link shares: Change default share name (#6298)
|
||||
* Sharing: Use maximum allowed permissions for new share (#6346)
|
||||
* Nautilus integration: Work with python2 and python3
|
||||
* Windows: Don't delete contents behind directory junctions (#6322)
|
||||
* SyncJournal: Don't use LIKE with paths (#6322)
|
||||
* Fix setting launch-on-startup when the first account is set up (#6347)
|
||||
* HTTP2: Only allow with Qt 5.9.4 (#6285)
|
||||
* Crash fixes
|
||||
|
||||
version 2.4.0 (2017-12-21)
|
||||
* If you're using 2.4.0 alpha1, please upgrade as previous alphas/rcs had an issue with hidden files and renames!
|
||||
* OAuth2 authentication support by opening external browser (#5668)
|
||||
* Shibboleth: Change to use OAuth2 if supported (#6198)
|
||||
* Sharing: Add support for multiple public link shares (#5655)
|
||||
* Sharing: Add option to copy/email private links (#5023, #5627)
|
||||
* Sharing: Add option "show file listing" (#5837)
|
||||
* Sharing: Show warning that links are public (#5747)
|
||||
* Sharing: Sharing dialog redesign: multiple share links support (#5695)
|
||||
* Sharing: Make "can edit" partially checked sometimes (#5642)
|
||||
* Sharing: Trigger a sync for folder affected by a change of sharing (#6098)
|
||||
* Wizard: Never propose an existing folder for syncing (#5597)
|
||||
* Wizard: Don't show last page anymore, go to settings directly (#5726)
|
||||
* Wizard: Handle url-shortener redirects (#5954)
|
||||
* Wizard: Resolve url/ redirects only if url/status.php not found (#5954)
|
||||
* Wizard: Add explanation text when server error is shown (#6157)
|
||||
* Wizard: Update the window size on high dpi screen (#6156)
|
||||
* Wizard: Don't report confusing error message (#6116)
|
||||
* Gui: Display the user server avatar (#5482)
|
||||
* Gui: Use display name of user, not internal name
|
||||
* Server URL: Update configuration in case of permanent redirection (#5972)
|
||||
* Gui: Allow to add multiple sync folder connection of the same folder (#6032)
|
||||
* Tray Menu: More detailed status messages
|
||||
* Tray Menu: Shibboleth: raise the browser when clicking on the tray (#6105)
|
||||
* Activity: Link errors from the account tab, allow filtering by account/folder (#5861)
|
||||
* Activity: Present conflicts more prominently (#5894)
|
||||
* Activity: Allow sorting the columns in issues and protocol tabs (#6093, #6086)
|
||||
* Selective Sync: Open sub folder context menu (#5596)
|
||||
* Selective Sync: Skip excluded folders when reading db (#5772)
|
||||
* Selective Sync: Remove local files of unselected folder despite other modified files (#5783)
|
||||
* Excludes: Remove .htaccess form list of excluded files (#5701)
|
||||
* Excludes: Hardcode desktop.ini
|
||||
* Excludes: Allow escaping "#" (#6012)
|
||||
* Excludes: Use faster matching via QRegularExpression (#6063)
|
||||
* Discovery: Increase the MAX_DEPTH and show deep folders as ignored (#1067)
|
||||
* Discovery: General speed improvements
|
||||
* Downloads: Remove empty temporary if disk space full (#5746)
|
||||
* Downloads: Read Content-MD5 header for object store setups
|
||||
* Checksums: Add global disable environment variable (#5017)
|
||||
* Quota: PropagateUpload: Model of remote quota, avoid some uploads (#5537)
|
||||
* Create favorite also in folder wizard (#455)
|
||||
* Windows: Use the application icon for the Windows 8 sidebar favorite (#2446, #5690)
|
||||
* macOS: Finder sidebar icon (#296)
|
||||
* Overlay Icons: Consider also the "shared by me" as shared (#4788)
|
||||
* Overlay Icons: Update right after sharing (#6115)
|
||||
* Overlay Icons: Fix different case paths not matching (#5257)
|
||||
* Overlay Icons: Detect changes in the shared flag (#6098)
|
||||
* Windows Overlay Icons: Potential hang fixes
|
||||
* Linux Overlay Icons: fix branded nemo and caja shell integration (#5966)
|
||||
* Credentials: Fix behavior for bad password (#5989)
|
||||
* Credentials: Don't create empty client cert keychain entries (#5752)
|
||||
* Credentials: Namespace windows cred keys (#6125)
|
||||
* Credentials: Use per-account keychain entries (#5830, #6126)
|
||||
* AccountSettings: Triggering log in re-ask about previously rejected certificates (#5819)
|
||||
* owncloudcmd: Added bandwidth limit parameter (#5707)
|
||||
* owncloudcmd: Fix timestamps, Fix --logdebug
|
||||
* AccountSettings: Sync with clean discovery on Ctrl-F6 (#5666)
|
||||
* Sync: Dynamic sizing of chunks in chunked uploads for improved big file upload performance (#5852)
|
||||
* Sync: Introduce overall errors that are not tied to a file (#5746)
|
||||
* Sync: Better messaging for 507 Insufficient Storage (#5537)
|
||||
* Sync: Create conflicts by comparing the hash of files with identical mtime/size (#5589)
|
||||
* Sync: Avoid downloads by comparing the hash of files with identical mtime/size (#6153)
|
||||
* Sync: Upload conflict files if OWNCLOUD_UPLOAD_CONFLICT_FILES environment variable is set (#6038)
|
||||
* Sync: Blacklist: Don't let errors become warnings (#5516)
|
||||
* Sync: Check etag again after active sync (#4116)
|
||||
* Sync: Rename handling fixes: duplicate file ids (#6096, #6212)
|
||||
* Sync: Rename handling fixes: File size must be equal
|
||||
* Sync: Rename handling: Fix duplicate files on abort/resume sync (#5949)
|
||||
* Sync: Add capability for invalid filename regexes (#6092)
|
||||
* SyncJournalDB: Fall back to DELETE journal mode if WAL mode does not seem to work (#5723)
|
||||
* SyncJournalDB: Don't crash if the db file is readonly (#6050)
|
||||
* SyncJournalDB: DB close error is not fatal
|
||||
* Fix at least one memory leak
|
||||
* Documentation improvements
|
||||
* Logging improvements (With Qt logging categories) (#5671)
|
||||
* Logging filtering per account (#5672)
|
||||
* Crash fixes
|
||||
* Test improvements
|
||||
* Small UI layout fixes
|
||||
* Performance improvements
|
||||
* Maintenance Mode: Detect maintenance mode (#4485)
|
||||
* Maintenance Mode: Add a 1 to 5 min reconnection delay (#5872)
|
||||
* HTTP: Send a unique X-Request-ID with each request (#5853)
|
||||
* HTTP: Support HTTP2 when built and running with Qt 5.9.x (Official packages still on Qt 5.6.x) (#5659)
|
||||
* owncloudcmd: Don't start if connection or auth fails (#5692)
|
||||
* csync: Switch build from C to C++ (#6033)
|
||||
* csync: Refactor a lot to use common data structures to save memory and memory copying
|
||||
* csync: Switch some data structures to Qt data structures
|
||||
* csync: Switch to using upper layer SyncJournalDB (#6087)
|
||||
* Switch 3rdparty/json usage to Qt5's QJson (#5710)
|
||||
* OpenSSL: Don't require directly, only via Qt (#5833)
|
||||
* Remove iconv dependency, use Qt for file system locale encoding/decoding (emoji filename support on macOS) (#5875)
|
||||
* Compilation: Remove Qt 4 code (#6025, #5702, #5505)
|
||||
* Harmonize source code style with clang-format (#5732)
|
||||
* Switch over to Qt 5 function pointer signal/slot syntax (#6041)
|
||||
* Compile with stack-smashing protection
|
||||
* Updater: Rudimentary support for beta channel (#6048)
|
||||
|
||||
version 2.3.4 (2017-11-02)
|
||||
* Checksums: Use addData function to avoid endless loop CPU load issues with Office files
|
||||
* Packaging: Require ZLIB
|
||||
|
||||
version 2.3.3 (2017-08-29)
|
||||
* Chunking NG: Don't use old chunking on new DAV endpoint (#5855)
|
||||
* Selective Sync: Skip excluded folders when reading DB, don't let them show errors (#5772)
|
||||
* Settings: Make window bigger so Qt version is always visible (#5760)
|
||||
* Share links: Show warning that public link shares are public (#5786)
|
||||
* Downloads: Re-trigger folder discovery on HTTP 404 (#5799)
|
||||
* Overlay Icons: Fix potential hangs on Windows
|
||||
* SyncJournalDB: Don't use ._ as filename pattern if that does not work because of SMB storage settings (#5844)
|
||||
* SyncJournalDB: Log reason for sqlite3 opening errors
|
||||
* Notifications: Proapgate "Dismiss" button action to server (#5922)
|
||||
* Switch Linux build also to Qt 5.6.2 (#5470)
|
||||
* Stopped maintaining Qt 4 buildability
|
||||
|
||||
version 2.3.2 (2017-05-08)
|
||||
* Fix more crashes (thanks to everyone submitting to our crash reporter!)
|
||||
* Improve compatibility with server 10.0 (#5691, X-OC-Total-Size)
|
||||
* Share dialog: UI improvements, Bring to front on tray click
|
||||
* owncloudcmd: Align process return value with sync return value (#3936)
|
||||
* Fix disk free check on Windows when opening the local DB
|
||||
|
||||
version 2.3.1 (2017-03-21)
|
||||
* Fix several crashes (thanks to everyone submitting to our crash reporter!)
|
||||
* Improve HTTP redirect handling (#5555)
|
||||
* Blacklist: Escalate repeated soft error to normal error (#5500)
|
||||
* NTFS: Do not attempt to upload two existing files with similar casing (#5544)
|
||||
* Fix URL for linking to application password generation for ownCloud 10.0 (#5605)
|
||||
|
||||
version 2.3.0 (2017-03-03)
|
||||
* Decreased memory usage during sync
|
||||
* Overlay icons: Lower CPU usage
|
||||
* Allow to not sync the server's external storages by default
|
||||
@@ -101,7 +272,6 @@ version 2.2.0 (release 2016-05-12)
|
||||
* Documentation Improvements, ie. about overlay icons
|
||||
* Translation fixes
|
||||
* Countless other bugfixes
|
||||
* Sqlite Update to recent version
|
||||
* Update of QtKeyChain to support Windows credential store
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distros
|
||||
|
||||
@@ -172,7 +342,6 @@ version 2.1 (release 2015-12-03)
|
||||
* Fixed getting size for selective sync (#3986)
|
||||
* Re-added close button in the settings window (#3713)
|
||||
* Added abililty to handle storage limitations gracefully (#3736)
|
||||
* Updated 3rdparty dependencies: sqlite version 3.9.1
|
||||
* Organized patches to our base Qt version into admin/qt/patches
|
||||
* Plus: A lot of unmentioned improvements and fixes
|
||||
|
||||
|
||||
58
Jenkinsfile
vendored
@@ -1,58 +0,0 @@
|
||||
#!groovy
|
||||
|
||||
node('CLIENT') {
|
||||
stage 'Checkout'
|
||||
checkout scm
|
||||
sh '''git submodule update --init'''
|
||||
|
||||
stage 'Qt4'
|
||||
sh '''rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DUNIT_TESTING=1 -DBUILD_WITH_QT4=ON ..
|
||||
make
|
||||
ctest --output-on-failure'''
|
||||
|
||||
stage 'Qt4 - clang'
|
||||
sh '''rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUNIT_TESTING=1 -DBUILD_WITH_QT4=ON ..
|
||||
make
|
||||
ctest --output-on-failure'''
|
||||
|
||||
stage 'Qt5'
|
||||
sh '''rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DUNIT_TESTING=1 -DBUILD_WITH_QT4=OFF ..
|
||||
make
|
||||
ctest --output-on-failure'''
|
||||
|
||||
stage 'Qt5 - clang'
|
||||
sh '''rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DUNIT_TESTING=1 -DBUILD_WITH_QT4=OFF ..
|
||||
make
|
||||
ctest --output-on-failure'''
|
||||
|
||||
|
||||
stage 'Win32'
|
||||
def win32 = docker.image('guruz/docker-owncloud-client-win32:latest')
|
||||
win32.pull() // make sure we have the latest available from Docker Hub
|
||||
win32.inside {
|
||||
sh '''
|
||||
rm -rf build-win32
|
||||
mkdir build-win32
|
||||
cd build-win32
|
||||
../admin/win/download_runtimes.sh
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../admin/win/Toolchain-mingw32-openSUSE.cmake -DWITH_CRASHREPORTER=ON
|
||||
make -j4
|
||||
make package
|
||||
ctest .
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
set( APPLICATION_NAME "ownCloud" )
|
||||
set( APPLICATION_SHORTNAME "ownCloud" )
|
||||
set( APPLICATION_EXECUTABLE "owncloud" )
|
||||
set( APPLICATION_DOMAIN "owncloud.com" )
|
||||
set( APPLICATION_VENDOR "ownCloud" )
|
||||
set( APPLICATION_UPDATE_URL "https://updates.owncloud.com/client/" CACHE string "URL for updater" )
|
||||
set( APPLICATION_ICON_NAME "owncloud" )
|
||||
|
||||
set( LINUX_PACKAGE_SHORTNAME "owncloud" )
|
||||
|
||||
set( THEME_CLASS "ownCloudTheme" )
|
||||
set( APPLICATION_REV_DOMAIN "com.owncloud.desktopclient" )
|
||||
@@ -15,4 +19,4 @@ set( MAC_INSTALLER_BACKGROUND_FILE "${CMAKE_SOURCE_DIR}/admin/osx/installer-back
|
||||
|
||||
option( WITH_CRASHREPORTER "Build crashreporter" OFF )
|
||||
set( CRASHREPORTER_SUBMIT_URL "https://crash-reports.owncloud.com/submit" CACHE string "URL for crash reporter" )
|
||||
set( CRASHREPORTER_ICON ":/owncloud-icon.png" )
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ if(WIN32)
|
||||
set( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README.md" ) # File used as a description of a project /path/to/project/ReadMe.txt
|
||||
set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "${APPLICATION_NAME} Syncing Client" ) # Description summary of a project
|
||||
# CPACK_PACKAGE_EXECUTABLES List of pairs of executables and labels. Used by the NSIS generator to create Start Menu shortcuts. ccmake;CMake
|
||||
set( CPACK_PACKAGE_INSTALL_DIRECTORY ${APPLICATION_SHORTNAME} ) # Installation directory on the target system -> C:\Program Files\fellody
|
||||
set( CPACK_PACKAGE_INSTALL_DIRECTORY ${APPLICATION_SHORTNAME} ) # Installation directory on the target system -> C:\Program Files\${APPLICATION_SHORTNAME}
|
||||
set( CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${APPLICATION_SHORTNAME} ) # Registry key used when installing this project CMake 2.5.0
|
||||
set( CPACK_PACKAGE_NAME ${APPLICATION_NAME} ) # Package name, defaults to the project name
|
||||
set( CPACK_PACKAGE_VENDOR "http://${APPLICATION_DOMAIN}" ) # Package vendor name
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
# ownCloud Desktop Client
|
||||
|
||||
| Job | State |
|
||||
|-----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| client-build-matrix | [](https://ci.owncloud.org/job/client-build-matrix-linux/) |
|
||||
| client-test-matrix-linux-no-build | [](https://ci.owncloud.org/job/client-test-matrix-linux-no-build/) |
|
||||
| coverity_scan | [](https://scan.coverity.com/projects/owncloud-mirall)
|
||||
[](https://drone.owncloud.com/owncloud/client)
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -27,7 +23,7 @@ https://github.com/owncloud/client.
|
||||
|
||||
## Building the source code
|
||||
|
||||
[Building the Client](http://doc.owncloud.org/desktop/2.2/building.html)
|
||||
[Building the Client](http://doc.owncloud.org/desktop/2.3/building.html)
|
||||
in the ownCloud Desktop Client manual.
|
||||
|
||||
## Maintainers and Contributors
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
set( MIRALL_VERSION_MAJOR 2 )
|
||||
set( MIRALL_VERSION_MINOR 3 )
|
||||
set( MIRALL_VERSION_PATCH 0 )
|
||||
set( MIRALL_VERSION_YEAR 2016 )
|
||||
set( MIRALL_VERSION_MINOR 4 )
|
||||
set( MIRALL_VERSION_PATCH 3 )
|
||||
set( MIRALL_VERSION_YEAR 2018 )
|
||||
set( MIRALL_SOVERSION 0 )
|
||||
|
||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
|
||||
set( MIRALL_VERSION_SUFFIX "") #e.g. beta1, beta2, rc1
|
||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||
|
||||
if( NOT DEFINED MIRALL_VERSION_BUILD )
|
||||
|
||||
8
admin/linux/clean_tarball.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -vrf admin/
|
||||
rm -vrf src/3rdparty/sqlite3 # FIXME: For CentOS6 we have to use our bundled sqlite
|
||||
rm -vrf binary/
|
||||
rm -vrf src/3rdparty/libcrashreporter-qt
|
||||
rm -vrf shell_integration/windows
|
||||
rm -vrf shell_integration/MacOSX
|
||||
@@ -11,6 +11,7 @@ else()
|
||||
set(MAC_INSTALLER_DO_CUSTOM_BACKGROUND "0")
|
||||
endif()
|
||||
|
||||
find_package(Qt5 5.6 COMPONENTS Core REQUIRED)
|
||||
configure_file(create_mac_pkg.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/create_mac.sh)
|
||||
configure_file(macosx.pkgproj ${CMAKE_CURRENT_BINARY_DIR}/macosx.pkgproj)
|
||||
configure_file(pre_install.sh.cmake ${CMAKE_CURRENT_BINARY_DIR}/pre_install.sh)
|
||||
|
||||
@@ -23,7 +23,7 @@ identity="$3"
|
||||
prjfile=$build_path/admin/osx/macosx.pkgproj
|
||||
|
||||
# The name of the installer package
|
||||
installer="@APPLICATION_SHORTNAME@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
|
||||
installer="@APPLICATION_SHORTNAME@-qt@Qt5Core_VERSION@-@MIRALL_VERSION_FULL@@MIRALL_VERSION_SUFFIX@"
|
||||
installer_file="$installer.pkg"
|
||||
installer_file_tar="$installer.pkg.tar"
|
||||
installer_file_tar_bz2="$installer.pkg.tar.bz2"
|
||||
|
||||
@@ -22,6 +22,7 @@ import subprocess
|
||||
import commands
|
||||
import sys
|
||||
from glob import glob
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
def QueryQMake(attrib):
|
||||
return subprocess.check_output([qmake_path, '-query', attrib]).rstrip('\n')
|
||||
@@ -92,6 +93,8 @@ commands.append(['mkdir', '-p', resources_dir])
|
||||
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
|
||||
binaries = [i for i in glob(os.path.join(bundle_dir, 'Contents', 'MacOS', "*")) if is_exe(i)];
|
||||
|
||||
qt_version = QueryQMake('QT_VERSION')
|
||||
print "Using Qt", qt_version
|
||||
|
||||
fixed_libraries = []
|
||||
fixed_frameworks = []
|
||||
@@ -334,9 +337,19 @@ def FindQtPlugin(name):
|
||||
for binary in binaries:
|
||||
FixBinary(binary)
|
||||
|
||||
|
||||
if LooseVersion(qt_version) >= LooseVersion("5.10.0"):
|
||||
QT_PLUGINS.append('styles/libqmacstyle.dylib')
|
||||
for plugin in QT_PLUGINS:
|
||||
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
||||
if LooseVersion(qt_version) >= LooseVersion("5.10.0"):
|
||||
args = ['plutil', '-insert', 'LSMinimumSystemVersion', '-string', '10.10.0', os.path.join(bundle_dir, 'Contents', 'Info.plist')]
|
||||
commands.append(args)
|
||||
else:
|
||||
args = ['plutil', '-insert', 'LSMinimumSystemVersion', '-string', '10.7.0', os.path.join(bundle_dir, 'Contents', 'Info.plist')]
|
||||
commands.append(args)
|
||||
|
||||
if len(sys.argv) <= 2:
|
||||
print 'Will run %d commands:' % len(commands)
|
||||
for command in commands:
|
||||
|
||||
@@ -506,536 +506,6 @@
|
||||
<key>UUID</key>
|
||||
<string>7D7219B7-1897-48C3-8533-842BDEC46F71</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>PACKAGE_FILES</key>
|
||||
<dict>
|
||||
<key>DEFAULT_INSTALL_LOCATION</key>
|
||||
<string>/</string>
|
||||
<key>HIERARCHY</key>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>Utilities</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>Applications</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>509</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>Application Support</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Documentation</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Filesystems</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Frameworks</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Input Methods</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Internet Plug-Ins</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>LaunchAgents</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>LaunchDaemons</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>PreferencePanes</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Preferences</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>Printers</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>PrivilegedHelperTools</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>QuickLook</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>QuickTime</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Screen Savers</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Library/ScriptingAdditions/SyncStateFinder.osax/Contents</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>3</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>SyncStateFinder.osax</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>2</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>ScriptingAdditions</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>2</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Scripts</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Services</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Widgets</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Library</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Extensions</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Library</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>System</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CHILDREN</key>
|
||||
<array/>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>Shared</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>1023</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>80</integer>
|
||||
<key>PATH</key>
|
||||
<string>Users</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GID</key>
|
||||
<integer>0</integer>
|
||||
<key>PATH</key>
|
||||
<string>/</string>
|
||||
<key>PATH_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>PERMISSIONS</key>
|
||||
<integer>493</integer>
|
||||
<key>TYPE</key>
|
||||
<integer>1</integer>
|
||||
<key>UID</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>PAYLOAD_TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>VERSION</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>PACKAGE_SCRIPTS</key>
|
||||
<dict>
|
||||
<key>POSTINSTALL_PATH</key>
|
||||
<dict/>
|
||||
<key>PREINSTALL_PATH</key>
|
||||
<dict/>
|
||||
<key>RESOURCES</key>
|
||||
<array/>
|
||||
</dict>
|
||||
<key>PACKAGE_SETTINGS</key>
|
||||
<dict>
|
||||
<key>AUTHENTICATION</key>
|
||||
<integer>1</integer>
|
||||
<key>CONCLUSION_ACTION</key>
|
||||
<integer>0</integer>
|
||||
<key>IDENTIFIER</key>
|
||||
<string>com.ownCloud.finderPlugin</string>
|
||||
<key>LOCATION</key>
|
||||
<integer>0</integer>
|
||||
<key>NAME</key>
|
||||
<string>Legacy Finder Plugin (OS X 10.9 or older)</string>
|
||||
<key>OVERWRITE_PERMISSIONS</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>@MIRALL_VERSION_FULL@</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>UUID</key>
|
||||
<string>39F61FCD-6EAA-4F3A-81C6-25E3F667DFB5</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PROJECT</key>
|
||||
<dict>
|
||||
@@ -1103,49 +573,6 @@
|
||||
<key>UUID</key>
|
||||
<string>9647ADC0-BD53-4D7D-A561-73D383AACDE1</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>DESCRIPTION</key>
|
||||
<array/>
|
||||
<key>OPTIONS</key>
|
||||
<dict>
|
||||
<key>HIDDEN</key>
|
||||
<false/>
|
||||
<key>STATE</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>PACKAGE_UUID</key>
|
||||
<string>39F61FCD-6EAA-4F3A-81C6-25E3F667DFB5</string>
|
||||
<key>REQUIREMENTS</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BEHAVIOR</key>
|
||||
<integer>1</integer>
|
||||
<key>DICTIONARY</key>
|
||||
<dict>
|
||||
<key>IC_REQUIREMENT_JAVASCRIPT_FUNCTION</key>
|
||||
<string>olderOsx</string>
|
||||
<key>IC_REQUIREMENT_JAVASCRIPT_PARAMETERS</key>
|
||||
<array/>
|
||||
</dict>
|
||||
<key>IDENTIFIER</key>
|
||||
<string>fr.whitebox.Packages.requirement.javascript</string>
|
||||
<key>MESSAGE</key>
|
||||
<array/>
|
||||
<key>NAME</key>
|
||||
<string>JavaScript</string>
|
||||
<key>STATE</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</array>
|
||||
<key>TITLE</key>
|
||||
<array/>
|
||||
<key>TOOLTIP</key>
|
||||
<array/>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>UUID</key>
|
||||
<string>1D2C47E0-5FD3-4623-B934-1347C66782D0</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>REMOVED</key>
|
||||
<dict/>
|
||||
@@ -1450,18 +877,6 @@
|
||||
<string>@CMAKE_INSTALL_DIR@</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SHARED_GLOBAL_DATA</key>
|
||||
<dict>
|
||||
<key>IC_REQUIREMENT_JAVASCRIPT_SHARED_SOURCE_CODE</key>
|
||||
<string>
|
||||
function olderOsx() {
|
||||
if(system.compareVersions(system.version.ProductVersion, '10.10') == -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
<key>VERSION</key>
|
||||
|
||||
@@ -3,7 +3,4 @@
|
||||
# kill the old version. see issue #2044
|
||||
killall @APPLICATION_EXECUTABLE@
|
||||
|
||||
# Unload the Finder plugin. see issue #2105
|
||||
killall Finder
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -8,7 +8,7 @@ ENV HOME /root
|
||||
ENV REFRESHED_AT 20160421
|
||||
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys refresh
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_42.1/windows:mingw.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/windows:/mingw/openSUSE_Leap_42.1/windows:mingw.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys ar http://download.opensuse.org/repositories/isv:ownCloud:toolchains:mingw:win32:2.3/openSUSE_Leap_42.1/isv:ownCloud:toolchains:mingw:win32:2.3.repo
|
||||
RUN zypper --non-interactive --gpg-auto-import-keys install cmake make mingw32-cross-binutils mingw32-cross-cpp mingw32-cross-gcc \
|
||||
mingw32-cross-gcc-c++ mingw32-cross-pkg-config mingw32-filesystem \
|
||||
|
||||
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "Ez desinstalatu"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Dagoeneko Instalatuta"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Hautatu nola nahi duzun ${APPLICATION_NAME} instalatzea."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "${APPLICATION_NAME}ren bertsio berriago bat instalatuta dago! Ez da aholkatzen bertsio zaharrago bat instalatzea. Benetan bertsio zaharrago hau instalatu nahi baduzu, hobe da lehenengo bertsio berria desinstalatzea. Hautatu nahi duzun aukera eta sakatu Hurrengoa jarraitzeko."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} dagoeneko instalatuta dago.$\nHautatu zer operazio egin nahi duzu eta klikatu Hurrengoa jarraitzeko."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Gehitu/Berrinstalatu osagaiak"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalatu ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalatu ${APPLICATION_NAME}"
|
||||
@@ -40,4 +41,3 @@ StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "Desinstalatzaile honek administratzaile b
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Saioa hasteko zerbitzua ez dago martxan, bertan behera uzten!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "Desinstalatzailea dagoeneko martxan da."
|
||||
StrCpy $SectionGroup_Shortcuts "Lasterbideak"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
|
||||
@@ -9,6 +9,7 @@ StrCpy $PageReinstall_NEW_Field_3 "
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Juba paigaldatud"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Vali, kuidas sa soovid paigaldada ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uuem versioon ${APPLICATION_NAME} on juba paigaldatud! Vanema versiooni paigaldus ei ole soovitatav. Kui tõesti tahad paigaldada vanemat versiooni, siis on parem esmalt eemaldada olemasolev. Vali tehtav toiming ning kliki Jätka."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} on juba paigaldatud.$\n$\nVali toiming, mida sa tahad sooritada ning kliki jätkamiseks nuppu Next."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Lisa/Taaspaigalda komponente"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalli ${APPLICATION_NAME}"
|
||||
StrCpy $UNINSTALLER_APPDATA_TITLE "Desinstalli ${APPLICATION_NAME}"
|
||||
@@ -40,4 +41,3 @@ StrCpy $UAC_UNINSTALLER_REQUIRE_ADMIN "See desinstallija vajab admini ligip
|
||||
StrCpy $UAC_ERROR_LOGON_SERVICE "Sisselogimisteenus ei tööta, katkestamine!"
|
||||
StrCpy $INIT_UNINSTALLER_RUNNING "See desinstallija on juba käimas."
|
||||
StrCpy $SectionGroup_Shortcuts "Otseteed"
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} is already installed.$\r$\nSelect the operation you want to perform and click Next to continue."
|
||||
|
||||
@@ -25,7 +25,7 @@ StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Raccourci de lancement rapide"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Création d'un raccourci de lancement rapide"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "Essentiels de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Raccourci de ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Raccourci Bureau de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Raccourci de bureau pour ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Raccourci de lancement rapide de ${APPLICATION_NAME}."
|
||||
StrCpy $UNINSTALLER_FILE_Detail "Écriture du désinstallateur"
|
||||
StrCpy $UNINSTALLER_REGISTRY_Detail "Écriture des clefs de registre du désinstallateur"
|
||||
|
||||
@@ -3,7 +3,7 @@ StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Vis versjonsmerknader"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "Fant ${APPLICATION_EXECUTABLE}-prosess(er) som må stoppes.$\nVil du at installasjonsprogrammet skal stoppe dem for deg?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Terminerer ${APPLICATION_EXECUTABLE}-prosesser."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "Fant ikke prosess som skulle termineres!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "En eldre versjon av ${APPLICATION_NAME} er installert på systemet ditt. Det anbefales at du avnistallerer den versjonen før installering av ny versjon. Velg hva du vil gjøre og klikk Neste for å fortsette."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "En eldre versjon av ${APPLICATION_NAME} er installert på systemet ditt. Det anbefales at du avinstallerer den versjonen før installering av ny versjon. Velg hva du vil gjøre og klikk Neste for å fortsette."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Avinstaller før installering"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Ikke avinstaller"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Allerede installert"
|
||||
|
||||
@@ -8,7 +8,7 @@ StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "Não desinstale"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Já instalado"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_SUBTITLE "Escolha como pretende instalar ${APPLICATION_NAME}."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Uma versão mais recente da aplicação ${APPLICATION_NAME} já está instalada! Não é recomendada a instalação de uma versão mais antiga. Se realmente deseja instalar esta versão, aconselha-se a desinstalação da versão atual primeiro. Selecione a operação que deseja executar e clique em Avançar para continuar."
|
||||
StrCpy $PageReinstall_OLD_Field_1 "Já está instalada uma versão mais recente de ${APPLICATION_NAME}! Não é recomendada a instalação de uma versão mais antiga. Se realmente desejar instalar esta versão antiga, aconselha-se que desinstale primeiro a versão atual. Selecione a operação que deseja executar e clique em $\"Seguinte$\" para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_1 "${APPLICATION_NAME} ${VERSION} já está instalada.$\nSelecione a operação que deseja realizar e clique em 'Seguinte' para continuar."
|
||||
StrCpy $PageReinstall_SAME_Field_2 "Adicionar/Reinstalar Componentes"
|
||||
StrCpy $PageReinstall_SAME_Field_3 "Desinstalar ${APPLICATION_NAME}"
|
||||
@@ -17,8 +17,8 @@ StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Escolha a opção de manute
|
||||
StrCpy $SEC_APPLICATION_DETAILS "A instalar o essencial de ${APPLICATION_NAME}."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integração para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "A instalar integração para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Atalho do progama no Menu Inicial"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "A adicionar o atalho de ${APPLICATION_NAME} ao Menu Inicial."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Atalho do progama no Menu Iniciar"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "A adicionar o atalho de ${APPLICATION_NAME} no Menu Iniciar."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Atalho da área de trabalho"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "A criar atalhos na área de trabalho"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atalho de início rápido"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Auto-generated - do not modify
|
||||
StrCpy $MUI_FINISHPAGE_SHOWREADME_TEXT_STRING "Mostrar las notas de la versión"
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "El/los proceso/s ${APPLICATION_EXECUTABLE} debe/n ser detenidos.$\n¿Quiere que el instalador lo haga por usted?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Deteniendo el/los proceso/s ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_MESSAGEBOX_TEXT "El/los proceso(s) ${APPLICATION_EXECUTABLE} debe(n) ser detenido(s).$\n¿Quiere que el instalador lo haga por usted?"
|
||||
StrCpy $ConfirmEndProcess_KILLING_PROCESSES_TEXT "Deteniendo el/los proceso(s) ${APPLICATION_EXECUTABLE}."
|
||||
StrCpy $ConfirmEndProcess_KILL_NOT_FOUND_TEXT "¡Proceso a finalizar no encontrado!"
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} se encuentra instalada en el sistema. Se recomienda de instalar la versión actual antes de instalar la nueva. Seleccione la operacion deseada y haga click en Siguiente para continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_1 "Una versión anterior de ${APPLICATION_NAME} se encuentra instalada en el sistema. Se recomienda desinstalar la versión actual antes de instalar la nueva. Seleccione la operacion deseada y haga click en Siguiente para continuar."
|
||||
StrCpy $PageReinstall_NEW_Field_2 "Desinstalar antes de instalar"
|
||||
StrCpy $PageReinstall_NEW_Field_3 "No desinstalar"
|
||||
StrCpy $PageReinstall_NEW_MUI_HEADER_TEXT_TITLE "Ya está instalado"
|
||||
@@ -17,13 +17,13 @@ StrCpy $PageReinstall_SAME_MUI_HEADER_TEXT_SUBTITLE "Elija la opcion de mantenim
|
||||
StrCpy $SEC_APPLICATION_DETAILS "Instalando ${APPLICATION_NAME} esenciales."
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_SECTION "Integración para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_SHELL_EXT_DetailPrint "Instalando la integración para Windows Explorer"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo al programa Menú de Inicio"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_SECTION "Acceso directo al programa en Menú de Inicio"
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_DetailPrint "Añadiendo accesos directos para ${APPLICATION_NAME} en el Menú de Inicio."
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_SECTION "Acceso directo de Escritorio"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_DetailPrint "Creando accesos directos de escritorio"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atajo de accceso rápido"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_SECTION "Atajo de acceso rápido"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_DetailPrint "Creando un Acceso Directo al Lanzador Rápido"
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esencial."
|
||||
StrCpy $OPTION_SECTION_SC_APPLICATION_Desc "${APPLICATION_NAME} esenciales."
|
||||
StrCpy $OPTION_SECTION_SC_START_MENU_Desc "Acceso Directo de ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_DESKTOP_Desc "Acceso Directo de Escritorio para ${APPLICATION_NAME}"
|
||||
StrCpy $OPTION_SECTION_SC_QUICK_LAUNCH_Desc "Lanzador Rápido de Accesos Director para ${APPLICATION_NAME}."
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 25 KiB |
2
binary
@@ -70,45 +70,64 @@ macro (KDE4_ADD_APP_ICON appsources pattern)
|
||||
endif(PNG2ICO_EXECUTABLE AND WINDRES_EXECUTABLE)
|
||||
endif(WIN32)
|
||||
if (APPLE)
|
||||
# first convert image to a tiff using the Mac OS X "sips" utility,
|
||||
# then use tiff2icns to convert to an icon
|
||||
find_program(SIPS_EXECUTABLE NAMES sips)
|
||||
find_program(TIFF2ICNS_EXECUTABLE NAMES tiff2icns)
|
||||
if (SIPS_EXECUTABLE AND TIFF2ICNS_EXECUTABLE)
|
||||
file(GLOB_RECURSE files "${pattern}")
|
||||
# we can only test for the 128-icon like that - we don't use patterns anymore
|
||||
foreach (it ${files})
|
||||
if (it MATCHES ".*128.*" )
|
||||
set (_icon ${it})
|
||||
endif (it MATCHES ".*128.*")
|
||||
endforeach (it)
|
||||
file(GLOB_RECURSE files "${pattern}")
|
||||
file(MAKE_DIRECTORY ${appsources}.iconset)
|
||||
|
||||
if (_icon)
|
||||
|
||||
# first, get the basename of our app icon
|
||||
add_custom_command(OUTPUT ${_outfilename}.icns ${outfilename}.tiff
|
||||
COMMAND ${SIPS_EXECUTABLE} -s format tiff ${_icon} --out ${outfilename}.tiff
|
||||
COMMAND ${TIFF2ICNS_EXECUTABLE} ${outfilename}.tiff ${_outfilename}.icns
|
||||
DEPENDS ${_icon}
|
||||
)
|
||||
# List from:
|
||||
# https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW4
|
||||
foreach (it ${files})
|
||||
if (it MATCHES ".*icon-16.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_16x16.png COPYONLY)
|
||||
elseif (it MATCHES ".*icon-32.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_16x16@2x.png COPYONLY)
|
||||
configure_file(${it} ${appsources}.iconset/icon_32x32.png COPYONLY)
|
||||
elseif (it MATCHES ".*icon-64.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_32x32@2x.png COPYONLY)
|
||||
elseif (it MATCHES ".*icon-128.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_128x128.png COPYONLY)
|
||||
elseif (it MATCHES ".*icon-256.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_128x128@2x.png COPYONLY)
|
||||
configure_file(${it} ${appsources}.iconset/icon_256x256.png COPYONLY)
|
||||
elseif (it MATCHES ".*icon-512.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_256x256@2x.png COPYONLY)
|
||||
configure_file(${it} ${appsources}.iconset/icon_512x512.png COPYONLY)
|
||||
elseif (it MATCHES ".*icon-1024.*")
|
||||
configure_file(${it} ${appsources}.iconset/icon_512x512@2x.png COPYONLY)
|
||||
endif()
|
||||
endforeach (it)
|
||||
|
||||
# This will register the icon into the bundle
|
||||
set(MACOSX_BUNDLE_ICON_FILE ${appsources}.icns)
|
||||
# Copy the sidebar icons in the main app bundle for the FinderSync extension to pick.
|
||||
# https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Finder.html#//apple_ref/doc/uid/TP40014214-CH15-SW15
|
||||
foreach (it ${files})
|
||||
if (it MATCHES ".*sidebar-16.*")
|
||||
configure_file(${it} ${appsources}.iconset/sidebar_16x16.png COPYONLY)
|
||||
elseif (it MATCHES ".*sidebar-18.*")
|
||||
configure_file(${it} ${appsources}.iconset/sidebar_18x18.png COPYONLY)
|
||||
elseif (it MATCHES ".*sidebar-32.*")
|
||||
configure_file(${it} ${appsources}.iconset/sidebar_16x16@2x.png COPYONLY)
|
||||
configure_file(${it} ${appsources}.iconset/sidebar_32x32.png COPYONLY)
|
||||
elseif (it MATCHES ".*sidebar-36.*")
|
||||
configure_file(${it} ${appsources}.iconset/sidebar_18x18@2x.png COPYONLY)
|
||||
elseif (it MATCHES ".*sidebar-64.*")
|
||||
configure_file(${it} ${appsources}.iconset/sidebar_32x32@2x.png COPYONLY)
|
||||
endif()
|
||||
endforeach (it)
|
||||
|
||||
# Append the icns file to the sources list so it will be a dependency to the
|
||||
# main target
|
||||
list(APPEND ${appsources} ${_outfilename}.icns)
|
||||
add_custom_command(OUTPUT ${_outfilename}.icns
|
||||
COMMAND echo === Building bundle icns with iconset:
|
||||
COMMAND ls -1 ${appsources}.iconset
|
||||
COMMAND iconutil -c icns -o ${_outfilename}.icns ${appsources}.iconset
|
||||
DEPENDS ${files}
|
||||
)
|
||||
|
||||
# Install the icon into the Resources dir in the bundle
|
||||
set_source_files_properties(${_outfilename}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
# This will register the icon into the bundle
|
||||
set(MACOSX_BUNDLE_ICON_FILE ${appsources}.icns)
|
||||
|
||||
else(_icon)
|
||||
# TODO - try to scale a non-128 icon...? Try to convert an SVG on the fly?
|
||||
message(STATUS "Unable to find an 128x128 icon that matches pattern ${pattern} for variable ${appsources} - application will not have an application icon!")
|
||||
endif(_icon)
|
||||
# Append the icns file to the sources list so it will be a dependency to the
|
||||
# main target
|
||||
list(APPEND ${appsources} ${_outfilename}.icns)
|
||||
|
||||
else(SIPS_EXECUTABLE AND TIFF2ICNS_EXECUTABLE)
|
||||
message(STATUS "Unable to find the sips and tiff2icns utilities - application will not have an application icon!")
|
||||
endif(SIPS_EXECUTABLE AND TIFF2ICNS_EXECUTABLE)
|
||||
# Install the icon into the Resources dir in the bundle
|
||||
set_source_files_properties(${_outfilename}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
endif(APPLE)
|
||||
endmacro (KDE4_ADD_APP_ICON)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
# - Try to find Iconv
|
||||
# Once done this will define
|
||||
#
|
||||
# ICONV_FOUND - system has Iconv
|
||||
# ICONV_INCLUDE_DIRS - the Iconv include directory
|
||||
# ICONV_LIBRARIES - Link these to use Iconv
|
||||
# ICONV_DEFINITIONS - Compiler switches required for using Iconv
|
||||
#
|
||||
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
include(CheckIncludeFile)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckPrototypeDefinition)
|
||||
|
||||
find_path(ICONV_INCLUDE_DIR
|
||||
NAMES
|
||||
iconv.h sys/iconv.h
|
||||
)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
|
||||
check_include_file(iconv.h HAVE_ICONV_H)
|
||||
check_include_file(sys/iconv.h HAVE_SYS_ICONV_H)
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
|
||||
find_library(ICONV_LIBRARY
|
||||
NAMES
|
||||
iconv
|
||||
libiconv
|
||||
PATHS
|
||||
)
|
||||
|
||||
if (ICONV_LIBRARY)
|
||||
get_filename_component(_ICONV_NAME ${ICONV_LIBRARY} NAME)
|
||||
get_filename_component(_ICONV_PATH ${ICONV_LIBRARY} PATH)
|
||||
check_library_exists(${_ICONV_NAME} iconv ${_ICONV_PATH} HAVE_ICONV)
|
||||
else()
|
||||
check_function_exists(iconv HAVE_ICONV)
|
||||
endif()
|
||||
|
||||
if (HAVE_ICONV_H OR HAVE_SYS_ICONV_H)
|
||||
if (HAVE_ICONV_H)
|
||||
set(_ICONV_PROTO_INCLUDE "iconv.h")
|
||||
endif (HAVE_ICONV_H)
|
||||
if (HAVE_SYS_ICONV_H)
|
||||
set(_ICONV_PROTO_INCLUDE "sys/iconv.h")
|
||||
endif (HAVE_SYS_ICONV_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
|
||||
check_prototype_definition(iconv
|
||||
"size_t iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)"
|
||||
"-1"
|
||||
${_ICONV_PROTO_INCLUDE}
|
||||
HAVE_ICONV_CONST)
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
endif (HAVE_ICONV_H OR HAVE_SYS_ICONV_H)
|
||||
|
||||
set(ICONV_INCLUDE_DIRS
|
||||
${ICONV_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (ICONV_LIBRARY)
|
||||
set(ICONV_LIBRARIES
|
||||
${ICONV_LIBRARIES}
|
||||
${ICONV_LIBRARY}
|
||||
)
|
||||
endif (ICONV_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if (ICONV_LIBRARIES)
|
||||
find_package_handle_standard_args(Iconv DEFAULT_MSG ICONV_LIBRARIES ICONV_INCLUDE_DIRS)
|
||||
else()
|
||||
find_package_handle_standard_args(Iconv DEFAULT_MSG ICONV_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
# show the ICONV_INCLUDE_DIRS and ICONV_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ICONV_INCLUDE_DIRS ICONV_LIBRARIES)
|
||||
@@ -1,306 +0,0 @@
|
||||
# - Try to find the OpenSSL encryption library
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
|
||||
#
|
||||
# Read-Only variables:
|
||||
# OPENSSL_FOUND - system has the OpenSSL library
|
||||
# OPENSSL_INCLUDE_DIR - the OpenSSL include directory
|
||||
# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
|
||||
# OPENSSL_VERSION - This is set to $major.$minor.$revision$path (eg. 0.9.8s)
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2006-2009 Kitware, Inc.
|
||||
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
|
||||
# Copyright 2009-2011 Mathieu Malaterre <mathieu.malaterre@gmail.com>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
if (UNIX)
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(_OPENSSL QUIET openssl)
|
||||
endif (UNIX)
|
||||
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
SET(_OPENSSL_ROOT_HINTS
|
||||
$ENV{OPENSSL_ROOT_DIR}
|
||||
${OPENSSL_ROOT_DIR}
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||
)
|
||||
SET(_OPENSSL_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/OpenSSL"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
|
||||
"C:/OpenSSL/"
|
||||
"C:/OpenSSL-Win32/"
|
||||
"C:/OpenSSL-Win64/"
|
||||
)
|
||||
SET(_OPENSSL_ROOT_HINTS_AND_PATHS
|
||||
HINTS ${_OPENSSL_ROOT_HINTS}
|
||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
||||
)
|
||||
|
||||
FIND_PATH(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
HINTS
|
||||
${_OPENSSL_INCLUDEDIR}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
# MINGW should go here too
|
||||
IF(MSVC)
|
||||
# /MD and /MDd are the standard values - if someone wants to use
|
||||
# others, the libnames have to change here too
|
||||
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
|
||||
# TODO: handle /MT and static lib
|
||||
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
|
||||
# * MD for dynamic-release
|
||||
# * MDd for dynamic-debug
|
||||
# * MT for static-release
|
||||
# * MTd for static-debug
|
||||
|
||||
# Implementation details:
|
||||
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
||||
# libeay32MD.lib is identical to ../libeay32.lib, and
|
||||
# ssleay32MD.lib is identical to ../ssleay32.lib
|
||||
FIND_LIBRARY(LIB_EAY_DEBUG
|
||||
NAMES
|
||||
libeay32MDd
|
||||
libeay32
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
FIND_LIBRARY(LIB_EAY_RELEASE
|
||||
NAMES
|
||||
libeay32MD
|
||||
libeay32
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
FIND_LIBRARY(SSL_EAY_DEBUG
|
||||
NAMES
|
||||
ssleay32MDd
|
||||
ssleay32
|
||||
ssl
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
FIND_LIBRARY(SSL_EAY_RELEASE
|
||||
NAMES
|
||||
ssleay32MD
|
||||
ssleay32
|
||||
ssl
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"VC"
|
||||
"lib/VC"
|
||||
)
|
||||
|
||||
if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
|
||||
set( OPENSSL_LIBRARIES
|
||||
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
|
||||
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
|
||||
)
|
||||
else()
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
|
||||
endif()
|
||||
MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE)
|
||||
MARK_AS_ADVANCED(LIB_EAY_DEBUG LIB_EAY_RELEASE)
|
||||
ELSEIF(MINGW)
|
||||
# same player, for MingW
|
||||
FIND_LIBRARY(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
crypto
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"lib/MinGW"
|
||||
)
|
||||
|
||||
FIND_LIBRARY(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
ssl
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
"lib"
|
||||
"lib/MinGW"
|
||||
)
|
||||
|
||||
MARK_AS_ADVANCED(SSL_EAY LIB_EAY)
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
|
||||
ELSE(MSVC)
|
||||
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
||||
FIND_LIBRARY(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
FIND_LIBRARY(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
MARK_AS_ADVANCED(SSL_EAY LIB_EAY)
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
|
||||
ENDIF(MSVC)
|
||||
ELSE(WIN32 AND NOT CYGWIN)
|
||||
|
||||
FIND_LIBRARY(OPENSSL_SSL_LIBRARY
|
||||
NAMES
|
||||
ssl
|
||||
ssleay32
|
||||
ssleay32MD
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
FIND_LIBRARY(OPENSSL_CRYPTO_LIBRARY
|
||||
NAMES
|
||||
crypto
|
||||
HINTS
|
||||
${_OPENSSL_LIBDIR}
|
||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
MARK_AS_ADVANCED(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
|
||||
|
||||
# compat defines
|
||||
SET(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
|
||||
SET(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
|
||||
SET(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY})
|
||||
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
|
||||
function(from_hex HEX DEC)
|
||||
string(TOUPPER "${HEX}" HEX)
|
||||
set(_res 0)
|
||||
string(LENGTH "${HEX}" _strlen)
|
||||
|
||||
while (_strlen GREATER 0)
|
||||
math(EXPR _res "${_res} * 16")
|
||||
string(SUBSTRING "${HEX}" 0 1 NIBBLE)
|
||||
string(SUBSTRING "${HEX}" 1 -1 HEX)
|
||||
if (NIBBLE STREQUAL "A")
|
||||
math(EXPR _res "${_res} + 10")
|
||||
elseif (NIBBLE STREQUAL "B")
|
||||
math(EXPR _res "${_res} + 11")
|
||||
elseif (NIBBLE STREQUAL "C")
|
||||
math(EXPR _res "${_res} + 12")
|
||||
elseif (NIBBLE STREQUAL "D")
|
||||
math(EXPR _res "${_res} + 13")
|
||||
elseif (NIBBLE STREQUAL "E")
|
||||
math(EXPR _res "${_res} + 14")
|
||||
elseif (NIBBLE STREQUAL "F")
|
||||
math(EXPR _res "${_res} + 15")
|
||||
else()
|
||||
math(EXPR _res "${_res} + ${NIBBLE}")
|
||||
endif()
|
||||
|
||||
string(LENGTH "${HEX}" _strlen)
|
||||
endwhile()
|
||||
|
||||
set(${DEC} ${_res} PARENT_SCOPE)
|
||||
endfunction(from_hex)
|
||||
|
||||
if (OPENSSL_INCLUDE_DIR)
|
||||
if (_OPENSSL_VERSION)
|
||||
set(OPENSSL_VERSION "${_OPENSSL_VERSION}")
|
||||
elseif(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
|
||||
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
|
||||
REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
|
||||
|
||||
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
|
||||
# The status gives if this is a developer or prerelease and is ignored here.
|
||||
# Major, minor, and fix directly translate into the version numbers shown in
|
||||
# the string. The patch field translates to the single character suffix that
|
||||
# indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
|
||||
# on.
|
||||
|
||||
string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
|
||||
"\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
|
||||
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
|
||||
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
|
||||
from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
|
||||
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
|
||||
from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
|
||||
list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
|
||||
|
||||
if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
|
||||
from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
|
||||
# 96 is the ASCII code of 'a' minus 1
|
||||
math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
|
||||
unset(_tmp)
|
||||
# Once anyone knows how OpenSSL would call the patch versions beyond 'z'
|
||||
# this should be updated to handle that, too. This has not happened yet
|
||||
# so it is simply ignored here for now.
|
||||
string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
|
||||
endif (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
|
||||
|
||||
set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
|
||||
endif (_OPENSSL_VERSION)
|
||||
endif (OPENSSL_INCLUDE_DIR)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if (OPENSSL_VERSION)
|
||||
find_package_handle_standard_args(OpenSSL
|
||||
REQUIRED_VARS
|
||||
OPENSSL_LIBRARIES
|
||||
OPENSSL_INCLUDE_DIR
|
||||
VERSION_VAR
|
||||
OPENSSL_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
|
||||
)
|
||||
else (OPENSSL_VERSION)
|
||||
find_package_handle_standard_args(OpenSSL "Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
|
||||
OPENSSL_LIBRARIES
|
||||
OPENSSL_INCLUDE_DIR
|
||||
)
|
||||
endif (OPENSSL_VERSION)
|
||||
|
||||
MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
|
||||
@@ -9,9 +9,19 @@
|
||||
# QTKEYCHAIN_LIBRARIES - The libraries needed to use QtKeychain
|
||||
# QTKEYCHAIN_DEFINITIONS - Compiler switches required for using LibXml2
|
||||
|
||||
# When we build our own Qt we also need to build QtKeychain with it
|
||||
# so that it doesn't pull a different Qt version. For that reason
|
||||
# first look in the Qt lib directory for QtKeychain.
|
||||
get_target_property(_QTCORE_LIB_PATH Qt5::Core IMPORTED_LOCATION_RELEASE)
|
||||
|
||||
# Use PATH here because Debian 7.0 has CMake 2.8.9 and DIRECTORY is only available from 2.8.12+
|
||||
get_filename_component(QT_LIB_DIR "${_QTCORE_LIB_PATH}" PATH)
|
||||
|
||||
find_path(QTKEYCHAIN_INCLUDE_DIR
|
||||
NAMES
|
||||
keychain.h
|
||||
HINTS
|
||||
${QT_LIB_DIR}/../include
|
||||
PATH_SUFFIXES
|
||||
qt5keychain
|
||||
)
|
||||
@@ -20,6 +30,8 @@ find_library(QTKEYCHAIN_LIBRARY
|
||||
NAMES
|
||||
qt5keychain
|
||||
lib5qtkeychain
|
||||
HINTS
|
||||
${QT_LIB_DIR}
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/lib/${CMAKE_ARCH_TRIPLET}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# (c) 2014 Copyright ownCloud GmbH
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
# - Try to find QtKeychain
|
||||
# Once done this will define
|
||||
# QTKEYCHAIN_FOUND - System has QtKeychain
|
||||
# QTKEYCHAIN_INCLUDE_DIRS - The QtKeychain include directories
|
||||
# QTKEYCHAIN_LIBRARIES - The libraries needed to use QtKeychain
|
||||
# QTKEYCHAIN_DEFINITIONS - Compiler switches required for using LibXml2
|
||||
|
||||
find_path(QTKEYCHAIN_INCLUDE_DIR
|
||||
NAMES
|
||||
keychain.h
|
||||
PATH_SUFFIXES
|
||||
qtkeychain
|
||||
)
|
||||
|
||||
|
||||
find_library(QTKEYCHAIN_LIBRARY
|
||||
NAMES
|
||||
qtkeychain
|
||||
libqtkeychain
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/lib/${CMAKE_ARCH_TRIPLET}
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set QTKEYCHAIN_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(QtKeychain DEFAULT_MSG
|
||||
QTKEYCHAIN_LIBRARY QTKEYCHAIN_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(QTKEYCHAIN_INCLUDE_DIR QTKEYCHAIN_LIBRARY)
|
||||
@@ -27,11 +27,9 @@
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@MIRALL_VERSION_STRING@</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>(C) 2014-2016 @APPLICATION_VENDOR@</string>
|
||||
<string>(C) 2014-2018 @APPLICATION_VENDOR@</string>
|
||||
<key>SUShowReleaseNotes</key>
|
||||
<false/>
|
||||
<key>LSMinimumBundleVersion</key>
|
||||
<string>10.7.0</string>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>dsa_pub.pem</string>
|
||||
</dict>
|
||||
|
||||
@@ -116,8 +116,9 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
|
||||
!define MUI_HEADERIMAGE
|
||||
!define MUI_HEADERIMAGE_BITMAP ${WIN_SETUP_BITMAP_PATH}/page_header.bmp
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
!define MUI_FINISHPAGE_LINK "${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://${APPLICATION_DOMAIN}"
|
||||
; We removed this, h1 issue 191687
|
||||
;!define MUI_FINISHPAGE_LINK "${APPLICATION_DOMAIN}"
|
||||
;!define MUI_FINISHPAGE_LINK_LOCATION "http://${APPLICATION_DOMAIN}"
|
||||
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
|
||||
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
|
||||
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
|
||||
|
||||
@@ -5,67 +5,47 @@
|
||||
include (MacroOptionalFindPackage)
|
||||
include (MacroLogFeature)
|
||||
|
||||
option(BUILD_WITH_QT4 "Build with Qt4 no matter if Qt5 was found" OFF)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
if(UNIT_TESTING)
|
||||
find_package(Qt5Test REQUIRED)
|
||||
endif()
|
||||
|
||||
if( BUILD_WITH_QT4 )
|
||||
message(STATUS "Search for Qt5 was disabled by option BUILD_WITH_QT4")
|
||||
else( BUILD_WITH_QT4 )
|
||||
find_package(Qt5Core QUIET)
|
||||
endif( BUILD_WITH_QT4 )
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
if(APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif(APPLE)
|
||||
|
||||
if( Qt5Core_FOUND )
|
||||
message(STATUS "Found Qt5 core, checking for further dependencies...")
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
if(UNIT_TESTING)
|
||||
find_package(Qt5Test REQUIRED)
|
||||
endif()
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
if(APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif(APPLE)
|
||||
|
||||
if(NOT NO_SHIBBOLETH)
|
||||
find_package(Qt5WebKitWidgets)
|
||||
find_package(Qt5WebKit)
|
||||
if(NOT Qt5WebKitWidgets_FOUND)
|
||||
message(FATAL_ERROR "Qt5WebKit required for Shibboleth. Use -DNO_SHIBBOLETH=1 to disable it.")
|
||||
endif()
|
||||
if(NOT NO_SHIBBOLETH)
|
||||
find_package(Qt5WebKitWidgets)
|
||||
find_package(Qt5WebKit)
|
||||
if(NOT Qt5WebKitWidgets_FOUND)
|
||||
message(FATAL_ERROR "Qt5WebKit required for Shibboleth. Use -DNO_SHIBBOLETH=1 to disable it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
else( Qt5Core_FOUND )
|
||||
if(WIN32 OR APPLE)
|
||||
if (NOT BUILD_WITH_QT4)
|
||||
message(FATAL_ERROR "Qt 5 not found, but application depends on Qt5 on Windows and Mac OS X")
|
||||
endif ()
|
||||
endif(WIN32 OR APPLE)
|
||||
endif( Qt5Core_FOUND )
|
||||
|
||||
|
||||
if( Qt5Core_FOUND )
|
||||
message(STATUS "Using Qt 5!")
|
||||
|
||||
# We need this to find the paths to qdbusxml2cpp and co
|
||||
if (WITH_DBUS)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
include_directories(${Qt5DBus_INCLUDES})
|
||||
add_definitions(${Qt5DBus_DEFINITIONS})
|
||||
endif (WITH_DBUS)
|
||||
include_directories(${Qt5Core_INCLUDES})
|
||||
add_definitions(${Qt5Core_DEFINITIONS})
|
||||
if (NOT WIN32) #implied on Win32
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
endif(NOT WIN32)
|
||||
# We need this to find the paths to qdbusxml2cpp and co
|
||||
if (WITH_DBUS)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
include_directories(${Qt5DBus_INCLUDES})
|
||||
add_definitions(${Qt5DBus_DEFINITIONS})
|
||||
endif (WITH_DBUS)
|
||||
include_directories(${Qt5Core_INCLUDES})
|
||||
add_definitions(${Qt5Core_DEFINITIONS})
|
||||
if (NOT WIN32) #implied on Win32
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
endif(NOT WIN32)
|
||||
# set(CMAKE_CXX_FLAGS "${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
||||
|
||||
if(APPLE AND NOT TOKEN_AUTH_ONLY)
|
||||
include_directories(${Qt5MacExtras_INCLUDE_DIRS})
|
||||
add_definitions(${Qt5MacExtras_DEFINITIONS})
|
||||
set (QT_LIBRARIES ${QT_LIBRARIES} ${Qt5MacExtras_LIBRARIES})
|
||||
endif()
|
||||
if(APPLE AND NOT TOKEN_AUTH_ONLY)
|
||||
include_directories(${Qt5MacExtras_INCLUDE_DIRS})
|
||||
add_definitions(${Qt5MacExtras_DEFINITIONS})
|
||||
set (QT_LIBRARIES ${QT_LIBRARIES} ${Qt5MacExtras_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT BUILD_LIBRARIES_ONLY)
|
||||
macro(qt_wrap_ui)
|
||||
@@ -76,9 +56,9 @@ else()
|
||||
SET(QT_UIC_EXECUTABLE "")
|
||||
endif()
|
||||
|
||||
macro(qt_add_resources)
|
||||
qt5_add_resources(${ARGN})
|
||||
endmacro()
|
||||
macro(qt_add_resources)
|
||||
qt5_add_resources(${ARGN})
|
||||
endmacro()
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
find_package(Qt5LinguistTools)
|
||||
@@ -95,103 +75,30 @@ else()
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
macro(qt_add_dbus_interface)
|
||||
qt5_add_dbus_interface(${ARGN})
|
||||
endmacro()
|
||||
macro(qt_add_dbus_interface)
|
||||
qt5_add_dbus_interface(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_add_dbus_adaptor)
|
||||
qt5_add_dbus_adaptor(${ARGN})
|
||||
endmacro()
|
||||
macro(qt_add_dbus_adaptor)
|
||||
qt5_add_dbus_adaptor(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_wrap_cpp)
|
||||
qt5_wrap_cpp(${ARGN})
|
||||
endmacro()
|
||||
macro(qt_wrap_cpp)
|
||||
qt5_wrap_cpp(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(install_qt_executable)
|
||||
install_qt5_executable(${ARGN})
|
||||
endmacro()
|
||||
macro(install_qt_executable)
|
||||
install_qt5_executable(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(setup_qt)
|
||||
endmacro()
|
||||
macro(setup_qt)
|
||||
endmacro()
|
||||
|
||||
set(QT_RCC_EXECUTABLE "${Qt5Core_RCC_EXECUTABLE}")
|
||||
set(QT_RCC_EXECUTABLE "${Qt5Core_RCC_EXECUTABLE}")
|
||||
|
||||
#Enable deprecated symbols
|
||||
add_definitions("-DQT_DISABLE_DEPRECATED_BEFORE=0")
|
||||
#Enable deprecated symbols
|
||||
add_definitions("-DQT_DISABLE_DEPRECATED_BEFORE=0")
|
||||
|
||||
add_definitions("-DQT_USE_QSTRINGBUILDER") #optimize string concatenation
|
||||
add_definitions("-DQT_MESSAGELOGCONTEXT") #enable function name and line number in debug output
|
||||
endif( Qt5Core_FOUND )
|
||||
add_definitions("-DQT_USE_QSTRINGBUILDER") #optimize string concatenation
|
||||
add_definitions("-DQT_MESSAGELOGCONTEXT") #enable function name and line number in debug output
|
||||
|
||||
if(NOT Qt5Core_FOUND)
|
||||
message(STATUS "Could not find Qt5, searching for Qt4 instead...")
|
||||
|
||||
set(NEEDED_QT4_COMPONENTS "QtCore" "QtXml" "QtNetwork" "QtGui" "QtWebkit")
|
||||
if( BUILD_TESTS )
|
||||
list(APPEND NEEDED_QT4_COMPONENTS "QtTest")
|
||||
endif()
|
||||
|
||||
find_package(Qt4 4.7.0 COMPONENTS ${NEEDED_QT4_COMPONENTS} )
|
||||
macro_log_feature(QT4_FOUND "Qt" "A cross-platform application and UI framework" "http://www.qt-project.org" TRUE "" "If you see this, although libqt4-devel is installed, check whether the \n qtwebkit-devel package and whatever contains QtUiTools is installed too")
|
||||
|
||||
macro(qt5_use_modules)
|
||||
endmacro()
|
||||
|
||||
macro(qt_wrap_ui)
|
||||
qt4_wrap_ui(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_add_resources)
|
||||
qt4_add_resources(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_add_translation)
|
||||
qt4_add_translation(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_add_dbus_interface)
|
||||
qt4_add_dbus_interface(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_add_dbus_adaptor)
|
||||
qt4_add_dbus_adaptor(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(qt_wrap_cpp)
|
||||
qt4_wrap_cpp(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(install_qt_executable)
|
||||
install_qt4_executable(${ARGN})
|
||||
endmacro()
|
||||
|
||||
macro(setup_qt)
|
||||
set(QT_USE_QTGUI TRUE)
|
||||
set(QT_USE_QTSQL TRUE)
|
||||
set(QT_USE_QTNETWORK TRUE)
|
||||
set(QT_USE_QTXML TRUE)
|
||||
set(QT_USE_QTWEBKIT TRUE)
|
||||
set(QT_USE_QTDBUS TRUE)
|
||||
|
||||
include( ${QT_USE_FILE} )
|
||||
endmacro()
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
if (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)
|
||||
add_definitions("-DQ_DECL_OVERRIDE=override")
|
||||
else()
|
||||
add_definitions("-DQ_DECL_OVERRIDE=")
|
||||
endif()
|
||||
else() #clang or others
|
||||
add_definitions("-DQ_DECL_OVERRIDE=override")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if( Qt5Core_DIR )
|
||||
set( HAVE_QT5 TRUE )
|
||||
else( Qt5Core_DIR )
|
||||
set( HAVE_QT5 FALSE )
|
||||
endif( Qt5Core_DIR )
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# For details see the accompanying COPYING* file.
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-long-long -Wno-gnu-zero-variadic-macro-arguments")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
#cmakedefine APPLICATION_SHORTNAME "@APPLICATION_SHORTNAME@"
|
||||
#cmakedefine APPLICATION_EXECUTABLE "@APPLICATION_EXECUTABLE@"
|
||||
#cmakedefine APPLICATION_UPDATE_URL "@APPLICATION_UPDATE_URL@"
|
||||
#cmakedefine APPLICATION_ICON_NAME "@APPLICATION_ICON_NAME@"
|
||||
|
||||
#cmakedefine ZLIB_FOUND @ZLIB_FOUND@
|
||||
|
||||
#cmakedefine SYSCONFDIR "@SYSCONFDIR@"
|
||||
#cmakedefine SHAREDIR "@SHAREDIR@"
|
||||
|
||||
#cmakedefine WITH_UNIT_TESTING 1
|
||||
#cmakedefine WITH_TESTING 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
|
||||
# global needed variables
|
||||
set(APPLICATION_NAME "ocsync")
|
||||
|
||||
set(LIBRARY_VERSION ${MIRALL_VERSION})
|
||||
set(LIBRARY_SOVERSION "0")
|
||||
|
||||
# add definitions
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
include(DefineOptions.cmake)
|
||||
|
||||
include(DefineInstallationPaths)
|
||||
|
||||
# add macros
|
||||
include(MacroAddPlugin)
|
||||
include(MacroCopyFile)
|
||||
|
||||
if (NOT WIN32)
|
||||
find_package(Iconv)
|
||||
endif (NOT WIN32)
|
||||
|
||||
find_package(SQLite3 3.8.0 REQUIRED)
|
||||
|
||||
include(ConfigureChecks.cmake)
|
||||
|
||||
|
||||
set(SOURCE_DIR ${CMAKE_SOURCE_DIR})
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
|
||||
|
||||
if (MEM_NULL_TESTS)
|
||||
add_definitions(-DCSYNC_MEM_NULL_TESTS)
|
||||
endif (MEM_NULL_TESTS)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
set(WITH_TESTING ON)
|
||||
|
||||
find_package(CMocka)
|
||||
if (CMOCKA_FOUND)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
endif (CMOCKA_FOUND)
|
||||
endif (UNIT_TESTING)
|
||||
|
||||
configure_file(config_csync.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_csync.h)
|
||||
configure_file(config_test.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_test.h)
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
set(UPDATE_TYPE "true")
|
||||
|
||||
set(MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind-csync.supp)
|
||||
|
||||
set(CTEST_PROJECT_NAME "csync")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "mock.cryptomilk.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=${CTEST_PROJECT_NAME}")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
set(CTEST_CUSTOM_MEMCHECK_IGNORE
|
||||
${CTEST_CUSTOM_MEMCHECK_IGNORE}
|
||||
check_std_c_jhash
|
||||
)
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
/* mind to have trailing slashes! */
|
||||
|
||||
#define TESTFILES_DIR "@SOURCE_DIR@/csync/tests/ownCloud/testfiles/"
|
||||
|
||||
#define TEST_CONFIG_DIR "@SOURCE_DIR@/csync/tests/ownCloud/"
|
||||
|
||||
@@ -1,676 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ICONV_H
|
||||
#include <sys/iconv.h>
|
||||
#endif
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync_private.h"
|
||||
#include "csync_exclude.h"
|
||||
#include "csync_statedb.h"
|
||||
#include "csync_time.h"
|
||||
#include "csync_util.h"
|
||||
#include "csync_misc.h"
|
||||
#include "std/c_private.h"
|
||||
|
||||
#include "csync_update.h"
|
||||
#include "csync_reconcile.h"
|
||||
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#include "csync_log.h"
|
||||
#include "csync_rename.h"
|
||||
#include "c_jhash.h"
|
||||
|
||||
static int _key_cmp(const void *key, const void *data) {
|
||||
uint64_t a;
|
||||
csync_file_stat_t *b;
|
||||
|
||||
a = *(uint64_t *) (key);
|
||||
b = (csync_file_stat_t *) data;
|
||||
|
||||
if (a < b->phash) {
|
||||
return -1;
|
||||
} else if (a > b->phash) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _data_cmp(const void *key, const void *data) {
|
||||
csync_file_stat_t *a, *b;
|
||||
|
||||
a = (csync_file_stat_t *) key;
|
||||
b = (csync_file_stat_t *) data;
|
||||
|
||||
if (a->phash < b->phash) {
|
||||
return -1;
|
||||
} else if (a->phash > b->phash) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void csync_create(CSYNC **csync, const char *local) {
|
||||
CSYNC *ctx;
|
||||
size_t len = 0;
|
||||
|
||||
ctx = c_malloc(sizeof(CSYNC));
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
/* remove trailing slashes */
|
||||
len = strlen(local);
|
||||
while(len > 0 && local[len - 1] == '/') --len;
|
||||
|
||||
ctx->local.uri = c_strndup(local, len);
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
ctx->current_fs = NULL;
|
||||
|
||||
ctx->abort = false;
|
||||
|
||||
ctx->ignore_hidden_files = true;
|
||||
|
||||
*csync = ctx;
|
||||
}
|
||||
|
||||
void csync_init(CSYNC *ctx, const char *db_file) {
|
||||
assert(ctx);
|
||||
/* Do not initialize twice */
|
||||
|
||||
assert(!(ctx->status & CSYNC_STATUS_INIT));
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
ctx->local.type = LOCAL_REPLICA;
|
||||
|
||||
ctx->remote.type = REMOTE_REPLICA;
|
||||
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
ctx->statedb.file = c_strdup(db_file);
|
||||
|
||||
c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
|
||||
c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
|
||||
|
||||
ctx->remote.root_perms = 0;
|
||||
|
||||
ctx->status = CSYNC_STATUS_INIT;
|
||||
|
||||
/* initialize random generator */
|
||||
srand(time(NULL));
|
||||
}
|
||||
|
||||
int csync_update(CSYNC *ctx) {
|
||||
int rc = -1;
|
||||
struct timespec start, finish;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
/* Path of database file is set in csync_init */
|
||||
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
csync_memstat_check();
|
||||
|
||||
if (!ctx->excludes) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "No exclude file loaded or defined!");
|
||||
}
|
||||
|
||||
/* update detection for local replica */
|
||||
csync_gettime(&start);
|
||||
ctx->current = LOCAL_REPLICA;
|
||||
ctx->replica = ctx->local.type;
|
||||
|
||||
rc = csync_ftw(ctx, ctx->local.uri, csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Update detection for local replica took %.2f seconds walking %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->local.tree));
|
||||
csync_memstat_check();
|
||||
|
||||
/* update detection for remote replica */
|
||||
csync_gettime(&start);
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
|
||||
rc = csync_ftw(ctx, "", csync_walker, MAX_DEPTH);
|
||||
if (rc < 0) {
|
||||
if(ctx->status_code == CSYNC_STATUS_OK) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_UPDATE_ERROR);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Update detection for remote replica took %.2f seconds "
|
||||
"walking %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
|
||||
csync_memstat_check();
|
||||
|
||||
ctx->status |= CSYNC_STATUS_UPDATE;
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
csync_statedb_close(ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_reconcile(CSYNC *ctx) {
|
||||
int rc = -1;
|
||||
struct timespec start, finish;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
/* Reconciliation for local replica */
|
||||
csync_gettime(&start);
|
||||
|
||||
if (csync_statedb_load(ctx, ctx->statedb.file, &ctx->statedb.db) < 0) {
|
||||
rc = -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
ctx->current = LOCAL_REPLICA;
|
||||
ctx->replica = ctx->local.type;
|
||||
|
||||
rc = csync_reconcile_updates(ctx);
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Reconciliation for local replica took %.2f seconds visiting %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->local.tree));
|
||||
|
||||
if (rc < 0) {
|
||||
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = csync_errno_to_status( errno, CSYNC_STATUS_RECONCILE_ERROR );
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Reconciliation for remote replica */
|
||||
csync_gettime(&start);
|
||||
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
ctx->replica = ctx->remote.type;
|
||||
|
||||
rc = csync_reconcile_updates(ctx);
|
||||
|
||||
csync_gettime(&finish);
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"Reconciliation for remote replica took %.2f seconds visiting %zu files.",
|
||||
c_secdiff(finish, start), c_rbtree_size(ctx->remote.tree));
|
||||
|
||||
if (rc < 0) {
|
||||
if (!CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_RECONCILE_ERROR );
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx->status |= CSYNC_STATUS_RECONCILE;
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
csync_statedb_close(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* local visitor which calls the user visitor with repacked stat info.
|
||||
*/
|
||||
static int _csync_treewalk_visitor(void *obj, void *data) {
|
||||
int rc = 0;
|
||||
csync_file_stat_t *cur = NULL;
|
||||
CSYNC *ctx = NULL;
|
||||
c_rbtree_visit_func *visitor = NULL;
|
||||
_csync_treewalk_context *twctx = NULL;
|
||||
TREE_WALK_FILE trav;
|
||||
c_rbtree_t *other_tree = NULL;
|
||||
c_rbnode_t *other_node = NULL;
|
||||
|
||||
cur = (csync_file_stat_t *) obj;
|
||||
ctx = (CSYNC *) data;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we need the opposite tree! */
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
other_tree = ctx->remote.tree;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
other_tree = ctx->local.tree;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
other_node = c_rbtree_find(other_tree, &cur->phash);
|
||||
|
||||
if (!other_node) {
|
||||
/* Check the renamed path as well. */
|
||||
int len;
|
||||
uint64_t h = 0;
|
||||
char *renamed_path = csync_rename_adjust_path(ctx, cur->path);
|
||||
|
||||
if (!c_streq(renamed_path, cur->path)) {
|
||||
len = strlen( renamed_path );
|
||||
h = c_jhash64((uint8_t *) renamed_path, len, 0);
|
||||
other_node = c_rbtree_find(other_tree, &h);
|
||||
}
|
||||
SAFE_FREE(renamed_path);
|
||||
}
|
||||
|
||||
if (!other_node) {
|
||||
/* Check the source path as well. */
|
||||
int len;
|
||||
uint64_t h = 0;
|
||||
char *renamed_path = csync_rename_adjust_path_source(ctx, cur->path);
|
||||
|
||||
if (!c_streq(renamed_path, cur->path)) {
|
||||
len = strlen( renamed_path );
|
||||
h = c_jhash64((uint8_t *) renamed_path, len, 0);
|
||||
other_node = c_rbtree_find(other_tree, &h);
|
||||
}
|
||||
SAFE_FREE(renamed_path);
|
||||
}
|
||||
|
||||
if (obj == NULL || data == NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
twctx = (_csync_treewalk_context*) ctx->callbacks.userdata;
|
||||
if (twctx == NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (twctx->instruction_filter > 0 &&
|
||||
!(twctx->instruction_filter & cur->instruction) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
visitor = (c_rbtree_visit_func*)(twctx->user_visitor);
|
||||
if (visitor != NULL) {
|
||||
trav.path = cur->path;
|
||||
trav.size = cur->size;
|
||||
trav.modtime = cur->modtime;
|
||||
trav.mode = cur->mode;
|
||||
trav.type = cur->type;
|
||||
trav.instruction = cur->instruction;
|
||||
trav.rename_path = cur->destpath;
|
||||
trav.etag = cur->etag;
|
||||
trav.file_id = cur->file_id;
|
||||
trav.remotePerm = cur->remotePerm;
|
||||
trav.directDownloadUrl = cur->directDownloadUrl;
|
||||
trav.directDownloadCookies = cur->directDownloadCookies;
|
||||
trav.inode = cur->inode;
|
||||
|
||||
trav.error_status = cur->error_status;
|
||||
trav.has_ignored_files = cur->has_ignored_files;
|
||||
trav.checksum = cur->checksum;
|
||||
trav.checksumTypeId = cur->checksumTypeId;
|
||||
|
||||
if( other_node ) {
|
||||
csync_file_stat_t *other_stat = (csync_file_stat_t*)other_node->data;
|
||||
trav.other.etag = other_stat->etag;
|
||||
trav.other.file_id = other_stat->file_id;
|
||||
trav.other.instruction = other_stat->instruction;
|
||||
trav.other.modtime = other_stat->modtime;
|
||||
trav.other.size = other_stat->size;
|
||||
} else {
|
||||
trav.other.etag = 0;
|
||||
trav.other.file_id = 0;
|
||||
trav.other.instruction = CSYNC_INSTRUCTION_NONE;
|
||||
trav.other.modtime = 0;
|
||||
trav.other.size = 0;
|
||||
}
|
||||
|
||||
rc = (*visitor)(&trav, twctx->userdata);
|
||||
cur->instruction = trav.instruction;
|
||||
if (trav.etag != cur->etag) { // FIXME It would be nice to have this documented
|
||||
SAFE_FREE(cur->etag);
|
||||
cur->etag = c_strdup(trav.etag);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* treewalk function, called from its wrappers below.
|
||||
*
|
||||
* it encapsulates the user visitor function, the filter and the userdata
|
||||
* into a treewalk_context structure and calls the rb treewalk function,
|
||||
* which calls the local _csync_treewalk_visitor in this module.
|
||||
* The user visitor is called from there.
|
||||
*/
|
||||
static int _csync_walk_tree(CSYNC *ctx, c_rbtree_t *tree, csync_treewalk_visit_func *visitor, int filter)
|
||||
{
|
||||
_csync_treewalk_context tw_ctx;
|
||||
int rc = -1;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (visitor == NULL || tree == NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return rc;
|
||||
}
|
||||
|
||||
tw_ctx.userdata = ctx->callbacks.userdata;
|
||||
tw_ctx.user_visitor = visitor;
|
||||
tw_ctx.instruction_filter = filter;
|
||||
|
||||
ctx->callbacks.userdata = &tw_ctx;
|
||||
|
||||
rc = c_rbtree_walk(tree, (void*) ctx, _csync_treewalk_visitor);
|
||||
if( rc < 0 ) {
|
||||
if( ctx->status_code == CSYNC_STATUS_OK )
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_TREE_ERROR);
|
||||
}
|
||||
ctx->callbacks.userdata = tw_ctx.userdata;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* wrapper function for treewalk on the remote tree
|
||||
*/
|
||||
int csync_walk_remote_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter)
|
||||
{
|
||||
c_rbtree_t *tree = NULL;
|
||||
int rc = -1;
|
||||
|
||||
if(ctx != NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
ctx->current = REMOTE_REPLICA;
|
||||
tree = ctx->remote.tree;
|
||||
}
|
||||
|
||||
/* all error handling in the called function */
|
||||
rc = _csync_walk_tree(ctx, tree, visitor, filter);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* wrapper function for treewalk on the local tree
|
||||
*/
|
||||
int csync_walk_local_tree(CSYNC *ctx, csync_treewalk_visit_func *visitor, int filter)
|
||||
{
|
||||
c_rbtree_t *tree = NULL;
|
||||
int rc = -1;
|
||||
|
||||
if (ctx != NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
ctx->current = LOCAL_REPLICA;
|
||||
tree = ctx->local.tree;
|
||||
}
|
||||
|
||||
/* all error handling in the called function */
|
||||
rc = _csync_walk_tree(ctx, tree, visitor, filter);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void _tree_destructor(void *data) {
|
||||
csync_file_stat_t *freedata = NULL;
|
||||
|
||||
freedata = (csync_file_stat_t *) data;
|
||||
csync_file_stat_free(freedata);
|
||||
}
|
||||
|
||||
/* reset all the list to empty.
|
||||
* used by csync_commit and csync_destroy */
|
||||
static void _csync_clean_ctx(CSYNC *ctx)
|
||||
{
|
||||
/* destroy the rbtrees */
|
||||
if (c_rbtree_size(ctx->local.tree) > 0) {
|
||||
c_rbtree_destroy(ctx->local.tree, _tree_destructor);
|
||||
}
|
||||
|
||||
if (c_rbtree_size(ctx->remote.tree) > 0) {
|
||||
c_rbtree_destroy(ctx->remote.tree, _tree_destructor);
|
||||
}
|
||||
|
||||
csync_rename_destroy(ctx);
|
||||
|
||||
/* free memory */
|
||||
c_rbtree_free(ctx->local.tree);
|
||||
c_rbtree_free(ctx->remote.tree);
|
||||
|
||||
SAFE_FREE(ctx->remote.root_perms);
|
||||
}
|
||||
|
||||
int csync_commit(CSYNC *ctx) {
|
||||
int rc = 0;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->statedb.db != NULL
|
||||
&& csync_statedb_close(ctx) < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ERR: closing of statedb failed.");
|
||||
rc = -1;
|
||||
}
|
||||
ctx->statedb.db = NULL;
|
||||
|
||||
_csync_clean_ctx(ctx);
|
||||
|
||||
ctx->remote.read_from_db = 0;
|
||||
ctx->read_remote_from_db = true;
|
||||
ctx->db_is_empty = false;
|
||||
|
||||
|
||||
/* Create new trees */
|
||||
c_rbtree_create(&ctx->local.tree, _key_cmp, _data_cmp);
|
||||
c_rbtree_create(&ctx->remote.tree, _key_cmp, _data_cmp);
|
||||
|
||||
|
||||
ctx->status = CSYNC_STATUS_INIT;
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
rc = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_destroy(CSYNC *ctx) {
|
||||
int rc = 0;
|
||||
|
||||
if (ctx == NULL) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
ctx->status_code = CSYNC_STATUS_OK;
|
||||
|
||||
if (ctx->statedb.db != NULL
|
||||
&& csync_statedb_close(ctx) < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ERR: closing of statedb failed.");
|
||||
rc = -1;
|
||||
}
|
||||
ctx->statedb.db = NULL;
|
||||
|
||||
_csync_clean_ctx(ctx);
|
||||
|
||||
SAFE_FREE(ctx->statedb.file);
|
||||
SAFE_FREE(ctx->local.uri);
|
||||
SAFE_FREE(ctx->error_string);
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
c_close_iconv();
|
||||
#endif
|
||||
|
||||
SAFE_FREE(ctx);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void *csync_get_userdata(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return ctx->callbacks.userdata;
|
||||
}
|
||||
|
||||
int csync_set_userdata(CSYNC *ctx, void *userdata) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->callbacks.userdata = userdata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
csync_auth_callback csync_get_auth_callback(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx->callbacks.auth_function;
|
||||
}
|
||||
|
||||
int csync_set_status(CSYNC *ctx, int status) {
|
||||
if (ctx == NULL || status < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->status = status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CSYNC_STATUS csync_get_status(CSYNC *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ctx->status_code;
|
||||
}
|
||||
|
||||
const char *csync_get_status_string(CSYNC *ctx)
|
||||
{
|
||||
return csync_vio_get_status_string(ctx);
|
||||
}
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
int csync_set_iconv_codec(const char *from)
|
||||
{
|
||||
c_close_iconv();
|
||||
|
||||
if (from != NULL) {
|
||||
c_setup_iconv(from);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void csync_request_abort(CSYNC *ctx)
|
||||
{
|
||||
if (ctx != NULL) {
|
||||
ctx->abort = true;
|
||||
}
|
||||
}
|
||||
|
||||
void csync_resume(CSYNC *ctx)
|
||||
{
|
||||
if (ctx != NULL) {
|
||||
ctx->abort = false;
|
||||
}
|
||||
}
|
||||
|
||||
int csync_abort_requested(CSYNC *ctx)
|
||||
{
|
||||
if (ctx != NULL) {
|
||||
return ctx->abort;
|
||||
} else {
|
||||
return (1 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void csync_file_stat_free(csync_file_stat_t *st)
|
||||
{
|
||||
if (st) {
|
||||
SAFE_FREE(st->directDownloadUrl);
|
||||
SAFE_FREE(st->directDownloadCookies);
|
||||
SAFE_FREE(st->etag);
|
||||
SAFE_FREE(st->destpath);
|
||||
SAFE_FREE(st->checksum);
|
||||
SAFE_FREE(st);
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file csync_private.h
|
||||
*
|
||||
* @brief Private interface of csync
|
||||
*
|
||||
* @defgroup csyncInternalAPI csync internal API
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CSYNC_PRIVATE_H
|
||||
#define _CSYNC_PRIVATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "config_csync.h"
|
||||
#include "std/c_lib.h"
|
||||
#include "std/c_private.h"
|
||||
#include "csync.h"
|
||||
#include "csync_misc.h"
|
||||
|
||||
#ifdef WITH_ICONV
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICONV_H
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_ICONV_H
|
||||
#include <sys/iconv.h>
|
||||
#endif
|
||||
|
||||
#include "csync_macros.h"
|
||||
|
||||
/**
|
||||
* How deep to scan directories.
|
||||
*/
|
||||
#define MAX_DEPTH 50
|
||||
|
||||
#define CSYNC_STATUS_INIT 1 << 0
|
||||
#define CSYNC_STATUS_UPDATE 1 << 1
|
||||
#define CSYNC_STATUS_RECONCILE 1 << 2
|
||||
#define CSYNC_STATUS_PROPAGATE 1 << 3
|
||||
|
||||
#define CSYNC_STATUS_DONE (CSYNC_STATUS_INIT | \
|
||||
CSYNC_STATUS_UPDATE | \
|
||||
CSYNC_STATUS_RECONCILE | \
|
||||
CSYNC_STATUS_PROPAGATE)
|
||||
|
||||
enum csync_replica_e {
|
||||
LOCAL_REPLICA,
|
||||
REMOTE_REPLICA
|
||||
};
|
||||
|
||||
typedef struct csync_file_stat_s csync_file_stat_t;
|
||||
|
||||
/**
|
||||
* @brief csync public structure
|
||||
*/
|
||||
struct csync_s {
|
||||
struct {
|
||||
csync_auth_callback auth_function;
|
||||
void *userdata;
|
||||
csync_update_callback update_callback;
|
||||
void *update_callback_userdata;
|
||||
|
||||
/* hooks for checking the white list (uses the update_callback_userdata) */
|
||||
int (*checkSelectiveSyncBlackListHook)(void*, const char*);
|
||||
int (*checkSelectiveSyncNewFolderHook)(void*, const char* /* path */, const char* /* remotePerm */);
|
||||
|
||||
|
||||
csync_vio_opendir_hook remote_opendir_hook;
|
||||
csync_vio_readdir_hook remote_readdir_hook;
|
||||
csync_vio_closedir_hook remote_closedir_hook;
|
||||
void *vio_userdata;
|
||||
|
||||
/* hook for comparing checksums of files during discovery */
|
||||
csync_checksum_hook checksum_hook;
|
||||
void *checksum_userdata;
|
||||
|
||||
} callbacks;
|
||||
c_strlist_t *excludes;
|
||||
|
||||
struct {
|
||||
char *file;
|
||||
sqlite3 *db;
|
||||
int exists;
|
||||
|
||||
sqlite3_stmt* by_hash_stmt;
|
||||
sqlite3_stmt* by_fileid_stmt;
|
||||
sqlite3_stmt* by_inode_stmt;
|
||||
|
||||
int lastReturnValue;
|
||||
} statedb;
|
||||
|
||||
struct {
|
||||
char *uri;
|
||||
c_rbtree_t *tree;
|
||||
enum csync_replica_e type;
|
||||
} local;
|
||||
|
||||
struct {
|
||||
c_rbtree_t *tree;
|
||||
enum csync_replica_e type;
|
||||
int read_from_db;
|
||||
const char *root_perms; /* Permission of the root folder. (Since the root folder is not in the db tree, we need to keep a separate entry.) */
|
||||
} remote;
|
||||
|
||||
|
||||
#if defined(HAVE_ICONV) && defined(WITH_ICONV)
|
||||
struct {
|
||||
iconv_t iconv_cd;
|
||||
} options;
|
||||
#endif
|
||||
|
||||
/* replica we are currently walking */
|
||||
enum csync_replica_e current;
|
||||
|
||||
/* replica we want to work on */
|
||||
enum csync_replica_e replica;
|
||||
|
||||
/* Used in the update phase so changes in the sub directories can be notified to
|
||||
parent directories */
|
||||
csync_file_stat_t *current_fs;
|
||||
|
||||
/* csync error code */
|
||||
enum csync_status_codes_e status_code;
|
||||
|
||||
char *error_string;
|
||||
|
||||
int status;
|
||||
volatile int abort;
|
||||
void *rename_info;
|
||||
|
||||
/**
|
||||
* Specify if it is allowed to read the remote tree from the DB (default to enabled)
|
||||
*/
|
||||
bool read_remote_from_db;
|
||||
|
||||
/**
|
||||
* If true, the DB is considered empty and all reads are skipped. (default is false)
|
||||
* This is useful during the initial local discovery as it speeds it up significantly.
|
||||
*/
|
||||
bool db_is_empty;
|
||||
|
||||
bool ignore_hidden_files;
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct csync_file_stat_s {
|
||||
uint64_t phash; /* u64 */
|
||||
time_t modtime; /* u64 */
|
||||
int64_t size; /* u64 */
|
||||
size_t pathlen; /* u64 */
|
||||
uint64_t inode; /* u64 */
|
||||
mode_t mode; /* u32 */
|
||||
unsigned int type : 4;
|
||||
unsigned int child_modified : 1;
|
||||
unsigned int has_ignored_files : 1; /* specify that a directory, or child directory contains ignored files */
|
||||
|
||||
char *destpath; /* for renames */
|
||||
const char *etag;
|
||||
char file_id[FILE_ID_BUF_SIZE+1]; /* the ownCloud file id is fixed width in ownCloud. */
|
||||
char *directDownloadUrl;
|
||||
char *directDownloadCookies;
|
||||
char remotePerm[REMOTE_PERM_BUF_SIZE+1];
|
||||
|
||||
const char *checksum;
|
||||
uint32_t checksumTypeId;
|
||||
|
||||
CSYNC_STATUS error_status;
|
||||
|
||||
enum csync_instructions_e instruction; /* u32 */
|
||||
char path[1]; /* u8 */
|
||||
}
|
||||
#if !defined(__SUNPRO_C) && !defined(_MSC_VER)
|
||||
__attribute__ ((packed))
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack()
|
||||
#endif
|
||||
;
|
||||
|
||||
OCSYNC_EXPORT void csync_file_stat_free(csync_file_stat_t *st);
|
||||
|
||||
/*
|
||||
* context for the treewalk function
|
||||
*/
|
||||
struct _csync_treewalk_context_s
|
||||
{
|
||||
csync_treewalk_visit_func *user_visitor;
|
||||
int instruction_filter;
|
||||
void *userdata;
|
||||
};
|
||||
typedef struct _csync_treewalk_context_s _csync_treewalk_context;
|
||||
|
||||
void set_errno_from_http_errcode( int err );
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _CSYNC_PRIVATE_H */
|
||||
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
|
||||
@@ -1,385 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "csync_private.h"
|
||||
#include "csync_reconcile.h"
|
||||
#include "csync_util.h"
|
||||
#include "csync_statedb.h"
|
||||
#include "csync_rename.h"
|
||||
#include "c_jhash.h"
|
||||
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.reconciler"
|
||||
#include "csync_log.h"
|
||||
|
||||
#include "inttypes.h"
|
||||
|
||||
/* Check if a file is ignored because one parent is ignored.
|
||||
* return the node of the ignored directoy if it's the case, or NULL if it is not ignored */
|
||||
static c_rbnode_t *_csync_check_ignored(c_rbtree_t *tree, const char *path, int pathlen) {
|
||||
uint64_t h = 0;
|
||||
c_rbnode_t *node = NULL;
|
||||
|
||||
/* compute the size of the parent directory */
|
||||
int parentlen = pathlen - 1;
|
||||
while (parentlen > 0 && path[parentlen] != '/') {
|
||||
parentlen--;
|
||||
}
|
||||
if (parentlen <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h = c_jhash64((uint8_t *) path, parentlen, 0);
|
||||
node = c_rbtree_find(tree, &h);
|
||||
if (node) {
|
||||
csync_file_stat_t *n = (csync_file_stat_t*)node->data;
|
||||
if (n->instruction == CSYNC_INSTRUCTION_IGNORE) {
|
||||
/* Yes, we are ignored */
|
||||
return node;
|
||||
} else {
|
||||
/* Not ignored */
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
/* Try if the parent itself is ignored */
|
||||
return _csync_check_ignored(tree, path, parentlen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function in the reconcile pass.
|
||||
*
|
||||
* It's called for each entry in the local and remote rbtrees by
|
||||
* csync_reconcile()
|
||||
*
|
||||
* Before the reconcile phase the trees already know about changes
|
||||
* relative to the sync journal. This function's job is to spot conflicts
|
||||
* between local and remote changes and adjust the nodes accordingly.
|
||||
*
|
||||
* See doc/dev/sync-algorithm.md for an overview.
|
||||
*
|
||||
*
|
||||
* Older detail comment:
|
||||
*
|
||||
* We merge replicas at the file level. The merged replica contains the
|
||||
* superset of files that are on the local machine and server copies of
|
||||
* the replica. In the case where the same file is in both the local
|
||||
* and server copy, the file that was modified most recently is used.
|
||||
* This means that new files are not deleted, and updated versions of
|
||||
* existing files are not overwritten.
|
||||
*
|
||||
* When a file is updated, the merge algorithm compares the destination
|
||||
* file with the the source file. If the destination file is newer
|
||||
* (timestamp is newer), it is not overwritten. If both files, on the
|
||||
* source and the destination, have been changed, the newer file wins.
|
||||
*/
|
||||
static int _csync_merge_algorithm_visitor(void *obj, void *data) {
|
||||
csync_file_stat_t *cur = NULL;
|
||||
csync_file_stat_t *other = NULL;
|
||||
csync_file_stat_t *tmp = NULL;
|
||||
uint64_t h = 0;
|
||||
int len = 0;
|
||||
|
||||
CSYNC *ctx = NULL;
|
||||
c_rbtree_t *tree = NULL;
|
||||
c_rbnode_t *node = NULL;
|
||||
|
||||
cur = (csync_file_stat_t *) obj;
|
||||
ctx = (CSYNC *) data;
|
||||
|
||||
/* we need the opposite tree! */
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
tree = ctx->remote.tree;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
tree = ctx->local.tree;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
node = c_rbtree_find(tree, &cur->phash);
|
||||
|
||||
if (!node) {
|
||||
/* Check the renamed path as well. */
|
||||
char *renamed_path = csync_rename_adjust_path(ctx, cur->path);
|
||||
if (!c_streq(renamed_path, cur->path)) {
|
||||
len = strlen( renamed_path );
|
||||
h = c_jhash64((uint8_t *) renamed_path, len, 0);
|
||||
node = c_rbtree_find(tree, &h);
|
||||
}
|
||||
SAFE_FREE(renamed_path);
|
||||
}
|
||||
if (!node) {
|
||||
/* Check if it is ignored */
|
||||
node = _csync_check_ignored(tree, cur->path, cur->pathlen);
|
||||
/* If it is ignored, other->instruction will be IGNORE so this one will also be ignored */
|
||||
}
|
||||
|
||||
/* file only found on current replica */
|
||||
if (node == NULL) {
|
||||
switch(cur->instruction) {
|
||||
/* file has been modified */
|
||||
case CSYNC_INSTRUCTION_EVAL:
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
break;
|
||||
/* file has been removed on the opposite replica */
|
||||
case CSYNC_INSTRUCTION_NONE:
|
||||
case CSYNC_INSTRUCTION_UPDATE_METADATA:
|
||||
if (cur->has_ignored_files) {
|
||||
/* Do not remove a directory that has ignored files */
|
||||
break;
|
||||
}
|
||||
if (cur->child_modified) {
|
||||
/* re-create directory that has modified contents */
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
break;
|
||||
}
|
||||
cur->instruction = CSYNC_INSTRUCTION_REMOVE;
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_EVAL_RENAME:
|
||||
if(ctx->current == LOCAL_REPLICA ) {
|
||||
/* use the old name to find the "other" node */
|
||||
tmp = csync_statedb_get_stat_by_inode(ctx, cur->inode);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Finding opposite temp through inode %" PRIu64 ": %s",
|
||||
cur->inode, tmp ? "true":"false");
|
||||
} else if( ctx->current == REMOTE_REPLICA ) {
|
||||
tmp = csync_statedb_get_stat_by_file_id(ctx, cur->file_id);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Finding opposite temp through file ID %s: %s",
|
||||
cur->file_id, tmp ? "true":"false");
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unknown replica...");
|
||||
}
|
||||
|
||||
if( tmp ) {
|
||||
len = strlen( tmp->path );
|
||||
if( len > 0 ) {
|
||||
h = c_jhash64((uint8_t *) tmp->path, len, 0);
|
||||
/* First, check that the file is NOT in our tree (another file with the same name was added) */
|
||||
node = c_rbtree_find(ctx->current == REMOTE_REPLICA ? ctx->remote.tree : ctx->local.tree, &h);
|
||||
if (node) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Origin found in our tree : %s", tmp->path);
|
||||
} else {
|
||||
/* Find the temporar file in the other tree. */
|
||||
node = c_rbtree_find(tree, &h);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "PHash of temporary opposite (%s): %" PRIu64 " %s",
|
||||
tmp->path , h, node ? "found": "not found" );
|
||||
if (node) {
|
||||
other = (csync_file_stat_t*)node->data;
|
||||
} else {
|
||||
/* the renamed file could not be found in the opposite tree. That is because it
|
||||
* is not longer existing there, maybe because it was renamed or deleted.
|
||||
* The journal is cleaned up later after propagation.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!other) {
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
} else if (other->instruction == CSYNC_INSTRUCTION_NONE
|
||||
|| other->instruction == CSYNC_INSTRUCTION_UPDATE_METADATA
|
||||
|| cur->type == CSYNC_FTW_TYPE_DIR) {
|
||||
other->instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
other->destpath = c_strdup( cur->path );
|
||||
if( !c_streq(cur->file_id, "") ) {
|
||||
csync_vio_set_file_id( other->file_id, cur->file_id );
|
||||
}
|
||||
other->inode = cur->inode;
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else if (other->instruction == CSYNC_INSTRUCTION_REMOVE) {
|
||||
other->instruction = CSYNC_INSTRUCTION_RENAME;
|
||||
other->destpath = c_strdup( cur->path );
|
||||
|
||||
if( !c_streq(cur->file_id, "") ) {
|
||||
csync_vio_set_file_id( other->file_id, cur->file_id );
|
||||
}
|
||||
other->inode = cur->inode;
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else if (other->instruction == CSYNC_INSTRUCTION_NEW) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "OOOO=> NEW detected in other tree!");
|
||||
cur->instruction = CSYNC_INSTRUCTION_CONFLICT;
|
||||
} else {
|
||||
assert(other->type != CSYNC_FTW_TYPE_DIR);
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
other->instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
}
|
||||
csync_file_stat_free(tmp);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bool is_conflict = true;
|
||||
/*
|
||||
* file found on the other replica
|
||||
*/
|
||||
other = (csync_file_stat_t *) node->data;
|
||||
|
||||
switch (cur->instruction) {
|
||||
case CSYNC_INSTRUCTION_UPDATE_METADATA:
|
||||
if (other->instruction == CSYNC_INSTRUCTION_UPDATE_METADATA && ctx->current == LOCAL_REPLICA) {
|
||||
// Remote wins, the SyncEngine will pick relevant local metadata since the remote tree is walked last.
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
}
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_EVAL_RENAME:
|
||||
/* If the file already exist on the other side, we have a conflict.
|
||||
Abort the rename and consider it is a new file. */
|
||||
cur->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
/* fall trough */
|
||||
/* file on current replica is changed or new */
|
||||
case CSYNC_INSTRUCTION_EVAL:
|
||||
case CSYNC_INSTRUCTION_NEW:
|
||||
// This operation is usually a no-op and will by default return false
|
||||
if (csync_file_locked_or_open(ctx->local.uri, cur->path)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "[Reconciler] IGNORING file %s/%s since it is locked / open", ctx->local.uri, cur->path);
|
||||
cur->instruction = CSYNC_INSTRUCTION_ERROR;
|
||||
if (cur->error_status == CSYNC_STATUS_OK) // don't overwrite error
|
||||
cur->error_status = CYSNC_STATUS_FILE_LOCKED_OR_OPEN;
|
||||
break;
|
||||
} else {
|
||||
//CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "[Reconciler] not ignoring file %s/%s", ctx->local.uri, cur->path);
|
||||
}
|
||||
switch (other->instruction) {
|
||||
/* file on other replica is changed or new */
|
||||
case CSYNC_INSTRUCTION_NEW:
|
||||
case CSYNC_INSTRUCTION_EVAL:
|
||||
if (other->type == CSYNC_FTW_TYPE_DIR &&
|
||||
cur->type == CSYNC_FTW_TYPE_DIR) {
|
||||
// Folders of the same path are always considered equals
|
||||
is_conflict = false;
|
||||
} else {
|
||||
is_conflict = ((other->size != cur->size) || (other->modtime != cur->modtime));
|
||||
// FIXME: do a binary comparision of the file here because of the following
|
||||
// edge case:
|
||||
// The files could still have different content, even though the mtime
|
||||
// and size are the same.
|
||||
}
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
// If the files are considered equal, only update the DB with the etag from remote
|
||||
cur->instruction = is_conflict ? CSYNC_INSTRUCTION_CONFLICT : CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else {
|
||||
cur->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
other->instruction = is_conflict ? CSYNC_INSTRUCTION_CONFLICT : CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
}
|
||||
|
||||
break;
|
||||
/* file on the other replica has not been modified */
|
||||
case CSYNC_INSTRUCTION_NONE:
|
||||
case CSYNC_INSTRUCTION_UPDATE_METADATA:
|
||||
if (cur->type != other->type) {
|
||||
// If the type of the entity changed, it's like NEW, but
|
||||
// needs to delete the other entity first.
|
||||
cur->instruction = CSYNC_INSTRUCTION_TYPE_CHANGE;
|
||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else if (cur->type == CSYNC_FTW_TYPE_DIR) {
|
||||
cur->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
} else {
|
||||
cur->instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
other->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
}
|
||||
break;
|
||||
case CSYNC_INSTRUCTION_IGNORE:
|
||||
cur->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//hide instruction NONE messages when log level is set to debug,
|
||||
//only show these messages on log level trace
|
||||
const char *repo = ctx->current == REMOTE_REPLICA ? "server" : "client";
|
||||
if(cur->instruction ==CSYNC_INSTRUCTION_NONE)
|
||||
{
|
||||
if(cur->type == CSYNC_FTW_TYPE_DIR)
|
||||
{
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
|
||||
"%-30s %s dir: %s",
|
||||
csync_instruction_str(cur->instruction),
|
||||
repo,
|
||||
cur->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE,
|
||||
"%-30s %s file: %s",
|
||||
csync_instruction_str(cur->instruction),
|
||||
repo,
|
||||
cur->path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cur->type == CSYNC_FTW_TYPE_DIR)
|
||||
{
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"%-30s %s dir: %s",
|
||||
csync_instruction_str(cur->instruction),
|
||||
repo,
|
||||
cur->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"%-30s %s file: %s",
|
||||
csync_instruction_str(cur->instruction),
|
||||
repo,
|
||||
cur->path);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_reconcile_updates(CSYNC *ctx) {
|
||||
int rc;
|
||||
c_rbtree_t *tree = NULL;
|
||||
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
tree = ctx->local.tree;
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
tree = ctx->remote.tree;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rc = c_rbtree_walk(tree, (void *) ctx, _csync_merge_algorithm_visitor);
|
||||
if( rc < 0 ) {
|
||||
ctx->status_code = CSYNC_STATUS_RECONCILE_ERROR;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* vim: set ts=8 sw=2 et cindent: */
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2012 by Olivier Goffart <ogoffart@woboq.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
#include "csync_private.h"
|
||||
#include "csync_rename.h"
|
||||
}
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
static std::string _parentDir(const std::string &path) {
|
||||
int len = path.length();
|
||||
while(len > 0 && path[len-1]!='/') len--;
|
||||
while(len > 0 && path[len-1]=='/') len--;
|
||||
return path.substr(0, len);
|
||||
}
|
||||
|
||||
struct csync_rename_s {
|
||||
static csync_rename_s *get(CSYNC *ctx) {
|
||||
if (!ctx->rename_info) {
|
||||
ctx->rename_info = new csync_rename_s;
|
||||
}
|
||||
return reinterpret_cast<csync_rename_s *>(ctx->rename_info);
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> folder_renamed_to; // map from->to
|
||||
std::map<std::string, std::string> folder_renamed_from; // map to->from
|
||||
|
||||
struct renameop {
|
||||
csync_file_stat_t *st;
|
||||
bool operator<(const renameop &other) const {
|
||||
return strlen(st->destpath) < strlen(other.st->destpath);
|
||||
}
|
||||
};
|
||||
std::vector<renameop> todo;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
void csync_rename_destroy(CSYNC* ctx)
|
||||
{
|
||||
delete reinterpret_cast<csync_rename_s *>(ctx->rename_info);
|
||||
ctx->rename_info = 0;
|
||||
}
|
||||
|
||||
void csync_rename_record(CSYNC* ctx, const char* from, const char* to)
|
||||
{
|
||||
csync_rename_s::get(ctx)->folder_renamed_to[from] = to;
|
||||
csync_rename_s::get(ctx)->folder_renamed_from[to] = from;
|
||||
}
|
||||
|
||||
char* csync_rename_adjust_path(CSYNC* ctx, const char* path)
|
||||
{
|
||||
csync_rename_s* d = csync_rename_s::get(ctx);
|
||||
for (std::string p = _parentDir(path); !p.empty(); p = _parentDir(p)) {
|
||||
std::map< std::string, std::string >::iterator it = d->folder_renamed_to.find(p);
|
||||
if (it != d->folder_renamed_to.end()) {
|
||||
std::string rep = it->second + (path + p.length());
|
||||
return c_strdup(rep.c_str());
|
||||
}
|
||||
}
|
||||
return c_strdup(path);
|
||||
}
|
||||
|
||||
char* csync_rename_adjust_path_source(CSYNC* ctx, const char* path)
|
||||
{
|
||||
csync_rename_s* d = csync_rename_s::get(ctx);
|
||||
for (std::string p = _parentDir(path); !p.empty(); p = _parentDir(p)) {
|
||||
std::map< std::string, std::string >::iterator it = d->folder_renamed_from.find(p);
|
||||
if (it != d->folder_renamed_from.end()) {
|
||||
std::string rep = it->second + (path + p.length());
|
||||
return c_strdup(rep.c_str());
|
||||
}
|
||||
}
|
||||
return c_strdup(path);
|
||||
}
|
||||
|
||||
bool csync_rename_count(CSYNC *ctx) {
|
||||
csync_rename_s* d = csync_rename_s::get(ctx);
|
||||
return d->folder_renamed_from.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,622 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync_private.h"
|
||||
#include "csync_statedb.h"
|
||||
#include "csync_util.h"
|
||||
#include "csync_misc.h"
|
||||
#include "csync_exclude.h"
|
||||
|
||||
#include "c_string.h"
|
||||
#include "c_jhash.h"
|
||||
#include "csync_time.h"
|
||||
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.statedb"
|
||||
#include "csync_log.h"
|
||||
#include "csync_rename.h"
|
||||
|
||||
#define BUF_SIZE 16
|
||||
|
||||
#define sqlite_open(A, B) sqlite3_open_v2(A,B, SQLITE_OPEN_READONLY+SQLITE_OPEN_NOMUTEX, NULL)
|
||||
|
||||
#define SQLTM_TIME 150
|
||||
#define SQLTM_COUNT 10
|
||||
|
||||
#define SQLITE_BUSY_HANDLED(F) if(1) { \
|
||||
int n = 0; \
|
||||
do { rc = F ; \
|
||||
if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) ) { \
|
||||
n++; \
|
||||
csync_sleep(SQLTM_TIME); \
|
||||
} \
|
||||
}while( (n < SQLTM_COUNT) && ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED))); \
|
||||
}
|
||||
|
||||
|
||||
void csync_set_statedb_exists(CSYNC *ctx, int val) {
|
||||
ctx->statedb.exists = val;
|
||||
}
|
||||
|
||||
int csync_get_statedb_exists(CSYNC *ctx) {
|
||||
return ctx->statedb.exists;
|
||||
}
|
||||
|
||||
static int _csync_check_db_integrity(sqlite3 *db) {
|
||||
c_strlist_t *result = NULL;
|
||||
int rc = -1;
|
||||
|
||||
result = csync_statedb_query(db, "PRAGMA quick_check;");
|
||||
if (result != NULL) {
|
||||
/* There is a result */
|
||||
if (result->count > 0) {
|
||||
if (c_streq(result->vector[0], "ok")) {
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
c_strlist_destroy(result);
|
||||
}
|
||||
|
||||
if( sqlite3_threadsafe() == 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "* WARNING: SQLite module is not threadsafe!");
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int _csync_statedb_is_empty(sqlite3 *db) {
|
||||
c_strlist_t *result = NULL;
|
||||
int rc = 0;
|
||||
|
||||
result = csync_statedb_query(db, "SELECT COUNT(phash) FROM metadata LIMIT 1 OFFSET 0;");
|
||||
if (result == NULL) {
|
||||
rc = 1;
|
||||
}
|
||||
c_strlist_destroy(result);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void sqlite_profile( void *x, const char* sql, sqlite3_uint64 time)
|
||||
{
|
||||
(void)x;
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG,
|
||||
"_SQL_ %s: %llu", sql, time);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb) {
|
||||
int rc = -1;
|
||||
c_strlist_t *result = NULL;
|
||||
sqlite3 *db = NULL;
|
||||
|
||||
if( !ctx ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->statedb.db) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: DB already open");
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->statedb.lastReturnValue = SQLITE_OK;
|
||||
|
||||
/* Openthe database */
|
||||
if (sqlite_open(statedb, &db) != SQLITE_OK) {
|
||||
const char *errmsg= sqlite3_errmsg(ctx->statedb.db);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: Failed to sqlite3 open statedb - bail out: %s.",
|
||||
errmsg ? errmsg : "<no sqlite3 errormsg>");
|
||||
|
||||
rc = -1;
|
||||
ctx->status_code = CSYNC_STATUS_STATEDB_LOAD_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_csync_check_db_integrity(db) != 0) {
|
||||
const char *errmsg= sqlite3_errmsg(db);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "ERR: sqlite3 integrity check failed - bail out: %s.",
|
||||
errmsg ? errmsg : "<no sqlite3 errormsg>");
|
||||
rc = -1;
|
||||
ctx->status_code = CSYNC_STATUS_STATEDB_CORRUPTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_csync_statedb_is_empty(db)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "statedb contents doesn't exist");
|
||||
csync_set_statedb_exists(ctx, 0);
|
||||
} else {
|
||||
csync_set_statedb_exists(ctx, 1);
|
||||
}
|
||||
|
||||
/* Print out the version */
|
||||
//
|
||||
result = csync_statedb_query(db, "SELECT sqlite_version();");
|
||||
if (result && result->count >= 1) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "sqlite3 version \"%s\"", *result->vector);
|
||||
}
|
||||
c_strlist_destroy(result);
|
||||
|
||||
/* optimization for speeding up SQLite */
|
||||
result = csync_statedb_query(db, "PRAGMA synchronous = NORMAL;");
|
||||
c_strlist_destroy(result);
|
||||
result = csync_statedb_query(db, "PRAGMA case_sensitive_like = ON;");
|
||||
c_strlist_destroy(result);
|
||||
|
||||
/* set a busy handler with 5 seconds timeout */
|
||||
sqlite3_busy_timeout(db, 5000);
|
||||
|
||||
#ifndef NDEBUG
|
||||
sqlite3_profile(db, sqlite_profile, 0 );
|
||||
#endif
|
||||
*pdb = db;
|
||||
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "Success");
|
||||
|
||||
return 0;
|
||||
out:
|
||||
sqlite3_close(db);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_statedb_close(CSYNC *ctx) {
|
||||
int rc = 0;
|
||||
|
||||
if (!ctx) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* deallocate query resources */
|
||||
if( ctx->statedb.by_fileid_stmt ) {
|
||||
sqlite3_finalize(ctx->statedb.by_fileid_stmt);
|
||||
ctx->statedb.by_fileid_stmt = NULL;
|
||||
}
|
||||
if( ctx->statedb.by_hash_stmt ) {
|
||||
sqlite3_finalize(ctx->statedb.by_hash_stmt);
|
||||
ctx->statedb.by_hash_stmt = NULL;
|
||||
}
|
||||
if( ctx->statedb.by_inode_stmt) {
|
||||
sqlite3_finalize(ctx->statedb.by_inode_stmt);
|
||||
ctx->statedb.by_inode_stmt = NULL;
|
||||
}
|
||||
|
||||
ctx->statedb.lastReturnValue = SQLITE_OK;
|
||||
|
||||
int sr = sqlite3_close(ctx->statedb.db);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "sqlite3_close=%d", sr);
|
||||
|
||||
ctx->statedb.db = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define METADATA_COLUMNS "phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, contentChecksum, contentChecksumTypeId"
|
||||
|
||||
// This funciton parses a line from the metadata table into the given csync_file_stat
|
||||
// structure which it is also allocating.
|
||||
// Note that this function calls laso sqlite3_step to actually get the info from db and
|
||||
// returns the sqlite return type.
|
||||
static int _csync_file_stat_from_metadata_table( csync_file_stat_t **st, sqlite3_stmt *stmt )
|
||||
{
|
||||
int rc = SQLITE_ERROR;
|
||||
int column_count;
|
||||
int len;
|
||||
|
||||
if( ! stmt ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Fatal: Statement is NULL.");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
column_count = sqlite3_column_count(stmt);
|
||||
|
||||
SQLITE_BUSY_HANDLED( sqlite3_step(stmt) );
|
||||
|
||||
if( rc == SQLITE_ROW ) {
|
||||
if(column_count > 7) {
|
||||
const char *name;
|
||||
|
||||
/* phash, pathlen, path, inode, uid, gid, mode, modtime */
|
||||
len = sqlite3_column_int(stmt, 1);
|
||||
*st = c_malloc(sizeof(csync_file_stat_t) + len + 1);
|
||||
/* clear the whole structure */
|
||||
ZERO_STRUCTP(*st);
|
||||
|
||||
/* The query suceeded so use the phash we pass to the function. */
|
||||
(*st)->phash = sqlite3_column_int64(stmt, 0);
|
||||
|
||||
(*st)->pathlen = sqlite3_column_int(stmt, 1);
|
||||
name = (const char*) sqlite3_column_text(stmt, 2);
|
||||
memcpy((*st)->path, (len ? name : ""), len + 1);
|
||||
(*st)->inode = sqlite3_column_int64(stmt,3);
|
||||
(*st)->mode = sqlite3_column_int(stmt, 6);
|
||||
(*st)->modtime = strtoul((char*)sqlite3_column_text(stmt, 7), NULL, 10);
|
||||
|
||||
if(*st && column_count > 8 ) {
|
||||
(*st)->type = sqlite3_column_int(stmt, 8);
|
||||
}
|
||||
|
||||
if(column_count > 9 && sqlite3_column_text(stmt, 9)) {
|
||||
(*st)->etag = c_strdup( (char*) sqlite3_column_text(stmt, 9) );
|
||||
}
|
||||
if(column_count > 10 && sqlite3_column_text(stmt,10)) {
|
||||
csync_vio_set_file_id((*st)->file_id, (char*) sqlite3_column_text(stmt, 10));
|
||||
}
|
||||
if(column_count > 11 && sqlite3_column_text(stmt,11)) {
|
||||
strncpy((*st)->remotePerm,
|
||||
(char*) sqlite3_column_text(stmt, 11),
|
||||
REMOTE_PERM_BUF_SIZE);
|
||||
}
|
||||
if(column_count > 12 && sqlite3_column_int64(stmt,12)) {
|
||||
(*st)->size = sqlite3_column_int64(stmt, 12);
|
||||
}
|
||||
if(column_count > 13) {
|
||||
(*st)->has_ignored_files = sqlite3_column_int(stmt, 13);
|
||||
}
|
||||
if(column_count > 15 && sqlite3_column_int(stmt, 15)) {
|
||||
(*st)->checksum = c_strdup( (char*) sqlite3_column_text(stmt, 14));
|
||||
(*st)->checksumTypeId = sqlite3_column_int(stmt, 15);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if( rc != SQLITE_DONE ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "WARN: Query results in %d", rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* caller must free the memory */
|
||||
csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx,
|
||||
uint64_t phash)
|
||||
{
|
||||
csync_file_stat_t *st = NULL;
|
||||
int rc;
|
||||
|
||||
if( !ctx || ctx->db_is_empty ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( ctx->statedb.by_hash_stmt == NULL ) {
|
||||
const char *hash_query = "SELECT " METADATA_COLUMNS " FROM metadata WHERE phash=?1";
|
||||
|
||||
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, hash_query, strlen(hash_query), &ctx->statedb.by_hash_stmt, NULL));
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_OK ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for hash query.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( ctx->statedb.by_hash_stmt == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sqlite3_bind_int64(ctx->statedb.by_hash_stmt, 1, (long long signed int)phash);
|
||||
|
||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_hash_stmt);
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
||||
}
|
||||
sqlite3_reset(ctx->statedb.by_hash_stmt);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx,
|
||||
const char *file_id ) {
|
||||
csync_file_stat_t *st = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (!file_id) {
|
||||
return 0;
|
||||
}
|
||||
if (c_streq(file_id, "")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !ctx || ctx->db_is_empty ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( ctx->statedb.by_fileid_stmt == NULL ) {
|
||||
const char *query = "SELECT " METADATA_COLUMNS " FROM metadata WHERE fileid=?1";
|
||||
|
||||
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, query, strlen(query), &ctx->statedb.by_fileid_stmt, NULL));
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_OK ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for file id query.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* bind the query value */
|
||||
sqlite3_bind_text(ctx->statedb.by_fileid_stmt, 1, file_id, -1, SQLITE_STATIC);
|
||||
|
||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_fileid_stmt);
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata: %d!", rc);
|
||||
}
|
||||
// clear the resources used by the statement.
|
||||
sqlite3_reset(ctx->statedb.by_fileid_stmt);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
/* caller must free the memory */
|
||||
csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx,
|
||||
uint64_t inode)
|
||||
{
|
||||
csync_file_stat_t *st = NULL;
|
||||
int rc;
|
||||
|
||||
if (!inode) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !ctx || ctx->db_is_empty ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( ctx->statedb.by_inode_stmt == NULL ) {
|
||||
const char *inode_query = "SELECT " METADATA_COLUMNS " FROM metadata WHERE inode=?1";
|
||||
|
||||
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, inode_query, strlen(inode_query), &ctx->statedb.by_inode_stmt, NULL));
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_OK ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for inode query.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( ctx->statedb.by_inode_stmt == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sqlite3_bind_int64(ctx->statedb.by_inode_stmt, 1, (long long signed int)inode);
|
||||
|
||||
rc = _csync_file_stat_from_metadata_table(&st, ctx->statedb.by_inode_stmt);
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( !(rc == SQLITE_ROW || rc == SQLITE_DONE) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Could not get line from metadata by inode: %d!", rc);
|
||||
}
|
||||
sqlite3_reset(ctx->statedb.by_inode_stmt);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
int csync_statedb_get_below_path( CSYNC *ctx, const char *path ) {
|
||||
int rc;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int64_t cnt = 0;
|
||||
|
||||
if( !path ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( !ctx || ctx->db_is_empty ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Select the entries for anything that starts with (path+'/')
|
||||
* In other words, anything that is between path+'/' and path+'0',
|
||||
* (because '0' follows '/' in ascii)
|
||||
*/
|
||||
const char *below_path_query = "SELECT " METADATA_COLUMNS " FROM metadata WHERE path > (?||'/') AND path < (?||'0')";
|
||||
SQLITE_BUSY_HANDLED(sqlite3_prepare_v2(ctx->statedb.db, below_path_query, -1, &stmt, NULL));
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_OK ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "WRN: Unable to create stmt for below path query.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (stmt == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, path, -1, SQLITE_STATIC);
|
||||
|
||||
cnt = 0;
|
||||
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
do {
|
||||
csync_file_stat_t *st = NULL;
|
||||
|
||||
rc = _csync_file_stat_from_metadata_table( &st, stmt);
|
||||
if( st ) {
|
||||
/* Check for exclusion from the tree.
|
||||
* Note that this is only a safety net in case the ignore list changes
|
||||
* without a full remote discovery being triggered. */
|
||||
CSYNC_EXCLUDE_TYPE excluded = csync_excluded_traversal(ctx->excludes, st->path, st->type);
|
||||
if (excluded != CSYNC_NOT_EXCLUDED) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", st->path, excluded);
|
||||
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE
|
||||
|| excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
|
||||
csync_file_stat_free(st);
|
||||
continue;
|
||||
}
|
||||
|
||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
}
|
||||
|
||||
/* store into result list. */
|
||||
if (c_rbtree_insert(ctx->remote.tree, (void *) st) < 0) {
|
||||
csync_file_stat_free(st);
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
break;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
} while( rc == SQLITE_ROW );
|
||||
|
||||
ctx->statedb.lastReturnValue = rc;
|
||||
if( rc != SQLITE_DONE ) {
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "%" PRId64 " entries read below path %s from db.", cnt, path);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* query the statedb, caller must free the memory */
|
||||
c_strlist_t *csync_statedb_query(sqlite3 *db,
|
||||
const char *statement) {
|
||||
int err = SQLITE_OK;
|
||||
int rc = SQLITE_OK;
|
||||
size_t i = 0;
|
||||
size_t busy_count = 0;
|
||||
size_t retry_count = 0;
|
||||
size_t column_count = 0;
|
||||
sqlite3_stmt *stmt;
|
||||
const char *tail = NULL;
|
||||
const char *field = NULL;
|
||||
c_strlist_t *result = NULL;
|
||||
int row = 0;
|
||||
|
||||
do {
|
||||
/* compile SQL program into a virtual machine, reattempteing if busy */
|
||||
do {
|
||||
if (busy_count) {
|
||||
csync_sleep(100);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "sqlite3_prepare: BUSY counter: %zu", busy_count);
|
||||
}
|
||||
err = sqlite3_prepare(db, statement, -1, &stmt, &tail);
|
||||
} while (err == SQLITE_BUSY && busy_count ++ < 120);
|
||||
|
||||
if (err != SQLITE_OK) {
|
||||
if (err == SQLITE_BUSY) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Gave up waiting for lock to clear");
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN,
|
||||
"sqlite3_compile error: %s - on query %s",
|
||||
sqlite3_errmsg(db), statement);
|
||||
break;
|
||||
} else {
|
||||
busy_count = 0;
|
||||
column_count = sqlite3_column_count(stmt);
|
||||
|
||||
/* execute virtual machine by iterating over rows */
|
||||
for(;;) {
|
||||
err = sqlite3_step(stmt);
|
||||
|
||||
if (err == SQLITE_BUSY) {
|
||||
if (busy_count++ > 120) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Busy counter has reached its maximum. Aborting this sql statement");
|
||||
break;
|
||||
}
|
||||
csync_sleep(100);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "sqlite3_step: BUSY counter: %zu", busy_count);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (err == SQLITE_MISUSE) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite3_step: MISUSE!!");
|
||||
}
|
||||
|
||||
if (err == SQLITE_DONE) {
|
||||
if (result == NULL) {
|
||||
result = c_strlist_new(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (err == SQLITE_ERROR) {
|
||||
break;
|
||||
}
|
||||
|
||||
row++;
|
||||
if( result ) {
|
||||
result = c_strlist_expand(result, row*column_count);
|
||||
} else {
|
||||
result = c_strlist_new(column_count);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* iterate over columns */
|
||||
for (i = 0; i < column_count; i++) {
|
||||
field = (const char *) sqlite3_column_text(stmt, i);
|
||||
if (!field)
|
||||
field = "";
|
||||
// CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "sqlite3_column_text: %s", field);
|
||||
if (c_strlist_add(result, field) < 0) {
|
||||
c_strlist_destroy(result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} /* end infinite for loop */
|
||||
|
||||
/* deallocate vm resources */
|
||||
rc = sqlite3_finalize(stmt);
|
||||
|
||||
if (err != SQLITE_DONE && rc != SQLITE_SCHEMA) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "sqlite_step error: %s - on query: %s", sqlite3_errmsg(db), statement);
|
||||
if (result != NULL) {
|
||||
c_strlist_destroy(result);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (rc == SQLITE_SCHEMA) {
|
||||
retry_count ++;
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "SQLITE_SCHEMA error occurred on query: %s", statement);
|
||||
if (retry_count < 10) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Retrying now.");
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "RETRY count has reached its maximum. Aborting statement: %s", statement);
|
||||
if (result != NULL) {
|
||||
c_strlist_destroy(result);
|
||||
}
|
||||
result = c_strlist_new(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (rc == SQLITE_SCHEMA && retry_count < 10);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* vim: set ts=8 sw=2 et cindent: */
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file csync_private.h
|
||||
*
|
||||
* @brief Private interface of csync
|
||||
*
|
||||
* @defgroup csyncstatedbInternals csync statedb internals
|
||||
* @ingroup csyncInternalAPI
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _CSYNC_STATEDB_H
|
||||
#define _CSYNC_STATEDB_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync_private.h"
|
||||
|
||||
void csync_set_statedb_exists(CSYNC *ctx, int val);
|
||||
|
||||
int csync_get_statedb_exists(CSYNC *ctx);
|
||||
|
||||
/**
|
||||
* @brief Load the statedb.
|
||||
*
|
||||
* This function tries to load the statedb. If it doesn't exists it creates
|
||||
* the sqlite3 database, but doesn't create the tables. This will be done when
|
||||
* csync gets destroyed.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
* @param statedb Path to the statedb file (sqlite3 db).
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred with errno set.
|
||||
*/
|
||||
OCSYNC_EXPORT int csync_statedb_load(CSYNC *ctx, const char *statedb, sqlite3 **pdb);
|
||||
|
||||
OCSYNC_EXPORT int csync_statedb_close(CSYNC *ctx);
|
||||
|
||||
OCSYNC_EXPORT csync_file_stat_t *csync_statedb_get_stat_by_hash(CSYNC *ctx, uint64_t phash);
|
||||
|
||||
OCSYNC_EXPORT csync_file_stat_t *csync_statedb_get_stat_by_inode(CSYNC *ctx, uint64_t inode);
|
||||
|
||||
OCSYNC_EXPORT csync_file_stat_t *csync_statedb_get_stat_by_file_id(CSYNC *ctx, const char *file_id);
|
||||
|
||||
/**
|
||||
* @brief Query all files metadata inside and below a path.
|
||||
* @param ctx The csync context.
|
||||
* @param path The path.
|
||||
*
|
||||
* This function queries all metadata of all files inside or below the
|
||||
* given path. The result is a linear string list with a multiple of 9
|
||||
* entries. For each result file there are 9 strings which are phash,
|
||||
* path, inode, uid, gid, mode, modtime, type and md5 (unique id).
|
||||
*
|
||||
* Note that not only the files in the given path are part of the result
|
||||
* but also the files in directories below the given path. Ie. if the
|
||||
* parameter path is /home/kf/test, we have /home/kf/test/file.txt in
|
||||
* the result but also /home/kf/test/homework/another_file.txt
|
||||
*
|
||||
* @return A stringlist containing a multiple of 9 entries.
|
||||
*/
|
||||
int csync_statedb_get_below_path(CSYNC *ctx, const char *path);
|
||||
|
||||
/**
|
||||
* @brief A generic statedb query.
|
||||
*
|
||||
* @param ctx The csync context.
|
||||
* @param statement The SQL statement to execute
|
||||
*
|
||||
* @return A stringlist of the entries of a column. An emtpy stringlist if
|
||||
* nothing has been found. NULL on error.
|
||||
*/
|
||||
c_strlist_t *csync_statedb_query(sqlite3 *db, const char *statement);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _CSYNC_STATEDB_H */
|
||||
/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */
|
||||
@@ -1,852 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
* Copyright (c) 2012-2013 by Klaas Freitag <freitag@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config_csync.h"
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "c_jhash.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
#include "csync_exclude.h"
|
||||
#include "csync_statedb.h"
|
||||
#include "csync_update.h"
|
||||
#include "csync_util.h"
|
||||
#include "csync_misc.h"
|
||||
|
||||
#include "vio/csync_vio.h"
|
||||
|
||||
#define CSYNC_LOG_CATEGORY_NAME "csync.updater"
|
||||
#include "csync_log.h"
|
||||
#include "csync_rename.h"
|
||||
|
||||
/* calculate the hash of a given uri */
|
||||
static uint64_t _hash_of_file(CSYNC *ctx, const char *file) {
|
||||
const char *path;
|
||||
int len;
|
||||
uint64_t h = 0;
|
||||
|
||||
if( ctx && file ) {
|
||||
path = file;
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (strlen(path) <= strlen(ctx->local.uri)) {
|
||||
return 0;
|
||||
}
|
||||
path += strlen(ctx->local.uri) + 1;
|
||||
}
|
||||
len = strlen(path);
|
||||
h = c_jhash64((uint8_t *) path, len, 0);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
#ifdef NO_RENAME_EXTENSION
|
||||
/* Return true if the two path have the same extension. false otherwise. */
|
||||
static bool _csync_sameextension(const char *p1, const char *p2) {
|
||||
/* Find pointer to the extensions */
|
||||
const char *e1 = strrchr(p1, '.');
|
||||
const char *e2 = strrchr(p2, '.');
|
||||
|
||||
/* If the found extension contains a '/', it is because the . was in the folder name
|
||||
* => no extensions */
|
||||
if (e1 && strchr(e1, '/')) e1 = NULL;
|
||||
if (e2 && strchr(e2, '/')) e2 = NULL;
|
||||
|
||||
/* If none have extension, it is the same extension */
|
||||
if (!e1 && !e2)
|
||||
return true;
|
||||
|
||||
/* c_streq takes care of the rest */
|
||||
return c_streq(e1, e2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool _last_db_return_error(CSYNC* ctx) {
|
||||
return ctx->statedb.lastReturnValue != SQLITE_OK && ctx->statedb.lastReturnValue != SQLITE_DONE && ctx->statedb.lastReturnValue != SQLITE_ROW;
|
||||
}
|
||||
|
||||
/*
|
||||
* This static method is needed because the type members of the two structs use
|
||||
* different enum values. A direct comparion is not neccessarily correct.
|
||||
*
|
||||
* tmp is csync_file_stat_t
|
||||
* fs is csync_vio_file_stat_t with this vio type:
|
||||
* enum csync_vio_file_type_e {
|
||||
* CSYNC_VIO_FILE_TYPE_UNKNOWN,
|
||||
* CSYNC_VIO_FILE_TYPE_REGULAR,
|
||||
* CSYNC_VIO_FILE_TYPE_DIRECTORY,
|
||||
* CSYNC_VIO_FILE_TYPE_FIFO,
|
||||
* CSYNC_VIO_FILE_TYPE_SOCKET,
|
||||
* CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE,
|
||||
* CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE,
|
||||
* CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK
|
||||
* };
|
||||
*
|
||||
* csync_file_stat_t can be:
|
||||
* CSYNC_FTW_TYPE_SKIP, CSYNC_FTW_TYPE_FILE
|
||||
* CSYNC_FTW_TYPE_DIR, CSYNC_FTW_TYPE_SLINK
|
||||
*/
|
||||
static bool _csync_filetype_different( const csync_file_stat_t *tmp, const csync_vio_file_stat_t *fs)
|
||||
{
|
||||
if( !(tmp && fs)) return false;
|
||||
|
||||
if( tmp->type == CSYNC_FTW_TYPE_SKIP ) return true;
|
||||
|
||||
if( tmp->type == CSYNC_FTW_TYPE_DIR && fs->type != CSYNC_VIO_FILE_TYPE_DIRECTORY )
|
||||
return true;
|
||||
if( tmp->type == CSYNC_FTW_TYPE_FILE && fs->type != CSYNC_VIO_FILE_TYPE_REGULAR )
|
||||
return true;
|
||||
if( tmp->type == CSYNC_FTW_TYPE_SLINK && fs->type != CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK )
|
||||
return true;
|
||||
|
||||
return false; // both are NOT different.
|
||||
}
|
||||
|
||||
/* Return true if two mtime are considered equal
|
||||
* We consider mtime that are one hour difference to be equal if they are one hour appart
|
||||
* because on some system (FAT) the date is changing when the daylight saving is changing */
|
||||
static bool _csync_mtime_equal(time_t a, time_t b)
|
||||
{
|
||||
if (a == b)
|
||||
return true;
|
||||
|
||||
/* 1h of difference +- 1 second because the accuracy of FAT is 2 seconds (#2438) */
|
||||
if (fabs(3600 - fabs(difftime(a, b))) < 2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function of the discovery/update pass.
|
||||
*
|
||||
* It's called (indirectly) by csync_update(), once for each entity in the
|
||||
* local filesystem and once for each entity in the server data.
|
||||
*
|
||||
* It has two main jobs:
|
||||
* - figure out whether anything happened compared to the sync journal
|
||||
* and set (primarily) the instruction flag accordingly
|
||||
* - build the ctx->local.tree / ctx->remote.tree
|
||||
*
|
||||
* See doc/dev/sync-algorithm.md for an overview.
|
||||
*/
|
||||
static int _csync_detect_update(CSYNC *ctx, const char *file,
|
||||
const csync_vio_file_stat_t *fs, const int type) {
|
||||
uint64_t h = 0;
|
||||
size_t len = 0;
|
||||
size_t size = 0;
|
||||
const char *path = NULL;
|
||||
csync_file_stat_t *st = NULL;
|
||||
csync_file_stat_t *tmp = NULL;
|
||||
CSYNC_EXCLUDE_TYPE excluded;
|
||||
|
||||
if ((file == NULL) || (fs == NULL)) {
|
||||
errno = EINVAL;
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = file;
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (strlen(path) <= strlen(ctx->local.uri)) {
|
||||
ctx->status_code = CSYNC_STATUS_PARAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
path += strlen(ctx->local.uri) + 1;
|
||||
}
|
||||
|
||||
len = strlen(path);
|
||||
|
||||
if (type == CSYNC_FTW_TYPE_SKIP) {
|
||||
excluded =CSYNC_FILE_EXCLUDE_STAT_FAILED;
|
||||
} else {
|
||||
/* Check if file is excluded */
|
||||
excluded = csync_excluded_traversal(ctx->excludes, path, type);
|
||||
}
|
||||
|
||||
if( excluded == CSYNC_NOT_EXCLUDED ) {
|
||||
/* Even if it is not excluded by a pattern, maybe it is to be ignored
|
||||
* because it's a hidden file that should not be synced.
|
||||
* This code should probably be in csync_exclude, but it does not have the fs parameter.
|
||||
* Keep it here for now */
|
||||
if (ctx->ignore_hidden_files && (fs->flags & CSYNC_VIO_FILE_FLAGS_HIDDEN)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file excluded because it is a hidden file: %s", path);
|
||||
excluded = CSYNC_FILE_EXCLUDE_HIDDEN;
|
||||
}
|
||||
} else {
|
||||
/* File is ignored because it's matched by a user- or system exclude pattern. */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "%s excluded (%d)", path, excluded);
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_AND_REMOVE) {
|
||||
return 1;
|
||||
}
|
||||
if (excluded == CSYNC_FILE_SILENTLY_EXCLUDED) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncBlackListHook) {
|
||||
if (ctx->callbacks.checkSelectiveSyncBlackListHook(ctx->callbacks.update_callback_userdata, path)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
h = _hash_of_file(ctx, file );
|
||||
if( h == 0 ) {
|
||||
return -1;
|
||||
}
|
||||
size = sizeof(csync_file_stat_t) + len + 1;
|
||||
|
||||
st = c_malloc(size);
|
||||
|
||||
/* Set instruction by default to none */
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
st->etag = NULL;
|
||||
st->child_modified = 0;
|
||||
st->has_ignored_files = 0;
|
||||
if (type == CSYNC_FTW_TYPE_FILE ) {
|
||||
if (fs->mtime == 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s - mtime is zero!", path);
|
||||
}
|
||||
}
|
||||
|
||||
if (excluded > CSYNC_NOT_EXCLUDED || type == CSYNC_FTW_TYPE_SLINK) {
|
||||
st->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
if (ctx->current_fs) {
|
||||
ctx->current_fs->has_ignored_files = true;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Update detection: Check if a database entry exists.
|
||||
* If not, the file is either new or has been renamed. To see if it is
|
||||
* renamed, the db gets queried by the inode of the file as that one
|
||||
* does not change on rename.
|
||||
*/
|
||||
if (csync_get_statedb_exists(ctx)) {
|
||||
tmp = csync_statedb_get_stat_by_hash(ctx, h);
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
csync_file_stat_free(st);
|
||||
csync_file_stat_free(tmp);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(tmp && tmp->phash == h ) { /* there is an entry in the database */
|
||||
/* we have an update! */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Database entry found, compare: %" PRId64 " <-> %" PRId64
|
||||
", etag: %s <-> %s, inode: %" PRId64 " <-> %" PRId64
|
||||
", size: %" PRId64 " <-> %" PRId64 ", perms: %s <-> %s, ignore: %d",
|
||||
((int64_t) fs->mtime), ((int64_t) tmp->modtime),
|
||||
fs->etag, tmp->etag, (uint64_t) fs->inode, (uint64_t) tmp->inode,
|
||||
(uint64_t) fs->size, (uint64_t) tmp->size, fs->remotePerm, tmp->remotePerm, tmp->has_ignored_files );
|
||||
if (ctx->current == REMOTE_REPLICA && !c_streq(fs->etag, tmp->etag)) {
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
|
||||
// Preserve the EVAL flag later on if the type has changed.
|
||||
if (_csync_filetype_different(tmp, fs)) {
|
||||
st->child_modified = 1;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
if (ctx->current == LOCAL_REPLICA &&
|
||||
(!_csync_mtime_equal(fs->mtime, tmp->modtime)
|
||||
// zero size in statedb can happen during migration
|
||||
|| (tmp->size != 0 && fs->size != tmp->size))) {
|
||||
|
||||
// Checksum comparison at this stage is only enabled for .eml files,
|
||||
// check #4754 #4755
|
||||
bool isEmlFile = csync_fnmatch("*.eml", file, FNM_CASEFOLD) == 0;
|
||||
if (isEmlFile && fs->size == tmp->size && tmp->checksumTypeId) {
|
||||
if (ctx->callbacks.checksum_hook) {
|
||||
st->checksum = ctx->callbacks.checksum_hook(
|
||||
file, tmp->checksumTypeId,
|
||||
ctx->callbacks.checksum_userdata);
|
||||
}
|
||||
bool checksumIdentical = false;
|
||||
if (st->checksum) {
|
||||
st->checksumTypeId = tmp->checksumTypeId;
|
||||
checksumIdentical = strncmp(st->checksum, tmp->checksum, 1000) == 0;
|
||||
}
|
||||
if (checksumIdentical) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "NOTE: Checksums are identical, file did not actually change: %s", path);
|
||||
st->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve the EVAL flag later on if the type has changed.
|
||||
if (_csync_filetype_different(tmp, fs)) {
|
||||
st->child_modified = 1;
|
||||
}
|
||||
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL;
|
||||
goto out;
|
||||
}
|
||||
bool metadata_differ = (ctx->current == REMOTE_REPLICA && (!c_streq(fs->file_id, tmp->file_id)
|
||||
|| !c_streq(fs->remotePerm, tmp->remotePerm)))
|
||||
|| (ctx->current == LOCAL_REPLICA && fs->inode != tmp->inode);
|
||||
if (type == CSYNC_FTW_TYPE_DIR && ctx->current == REMOTE_REPLICA
|
||||
&& !metadata_differ && ctx->read_remote_from_db) {
|
||||
/* If both etag and file id are equal for a directory, read all contents from
|
||||
* the database.
|
||||
* The metadata comparison ensure that we fetch all the file id or permission when
|
||||
* upgrading owncloud
|
||||
*/
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Reading from database: %s", path);
|
||||
ctx->remote.read_from_db = true;
|
||||
}
|
||||
/* If it was remembered in the db that the remote dir has ignored files, store
|
||||
* that so that the reconciler can make advantage of.
|
||||
*/
|
||||
if( ctx->current == REMOTE_REPLICA ) {
|
||||
st->has_ignored_files = tmp->has_ignored_files;
|
||||
}
|
||||
if (metadata_differ) {
|
||||
/* file id or permissions has changed. Which means we need to update them in the DB. */
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Need to update metadata for: %s", path);
|
||||
st->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
} else {
|
||||
st->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
}
|
||||
} else {
|
||||
enum csync_vio_file_type_e tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
|
||||
/* tmp might point to malloc mem, so free it here before reusing tmp */
|
||||
csync_file_stat_free(tmp);
|
||||
|
||||
/* check if it's a file and has been renamed */
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Checking for rename based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
|
||||
tmp = csync_statedb_get_stat_by_inode(ctx, fs->inode);
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
csync_file_stat_free(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* translate the file type between the two stat types csync has. */
|
||||
if( tmp && tmp->type == CSYNC_FTW_TYPE_FILE ) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_REGULAR;
|
||||
} else if( tmp && tmp->type == CSYNC_FTW_TYPE_DIR) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_DIRECTORY;
|
||||
} else if( tmp && tmp->type == CSYNC_FTW_TYPE_SLINK ) {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK;
|
||||
} else {
|
||||
tmp_vio_type = CSYNC_VIO_FILE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
// Default to NEW unless we're sure it's a rename.
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
|
||||
bool isRename =
|
||||
tmp && tmp->inode == fs->inode && tmp_vio_type == fs->type
|
||||
&& (tmp->modtime == fs->mtime || fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY)
|
||||
#ifdef NO_RENAME_EXTENSION
|
||||
&& _csync_sameextension(tmp->path, path)
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
// Verify the checksum where possible
|
||||
if (isRename && tmp->checksumTypeId && ctx->callbacks.checksum_hook
|
||||
&& fs->type == CSYNC_VIO_FILE_TYPE_REGULAR) {
|
||||
st->checksum = ctx->callbacks.checksum_hook(
|
||||
file, tmp->checksumTypeId,
|
||||
ctx->callbacks.checksum_userdata);
|
||||
if (st->checksum) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "checking checksum of potential rename %s %s <-> %s", path, st->checksum, tmp->checksum);
|
||||
st->checksumTypeId = tmp->checksumTypeId;
|
||||
isRename = strncmp(st->checksum, tmp->checksum, 1000) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRename) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "pot rename detected based on inode # %" PRId64 "", (uint64_t) fs->inode);
|
||||
/* inode found so the file has been renamed */
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
|
||||
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) {
|
||||
csync_rename_record(ctx, tmp->path, path);
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
|
||||
} else {
|
||||
/* Remote Replica Rename check */
|
||||
tmp = csync_statedb_get_stat_by_file_id(ctx, fs->file_id);
|
||||
|
||||
if(_last_db_return_error(ctx)) {
|
||||
csync_file_stat_free(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
if(tmp ) { /* tmp existing at all */
|
||||
if ( _csync_filetype_different(tmp, fs)) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "WARN: file types different is not!");
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
goto out;
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "remote rename detected based on fileid %s %s", tmp->path, file);
|
||||
st->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
|
||||
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) {
|
||||
csync_rename_record(ctx, tmp->path, path);
|
||||
} else {
|
||||
if( !c_streq(tmp->etag, fs->etag) ) {
|
||||
/* CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "ETags are different!"); */
|
||||
/* File with different etag, don't do a rename, but download the file again */
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
|
||||
} else {
|
||||
/* file not found in statedb */
|
||||
st->instruction = CSYNC_INSTRUCTION_NEW;
|
||||
|
||||
if (fs->type == CSYNC_VIO_FILE_TYPE_DIRECTORY && ctx->current == REMOTE_REPLICA && ctx->callbacks.checkSelectiveSyncNewFolderHook) {
|
||||
if (ctx->callbacks.checkSelectiveSyncNewFolderHook(ctx->callbacks.update_callback_userdata, path, fs->remotePerm)) {
|
||||
csync_file_stat_free(st);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Unable to open statedb" );
|
||||
csync_file_stat_free(st);
|
||||
ctx->status_code = CSYNC_STATUS_UNSUCCESSFUL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
/* Set the ignored error string. */
|
||||
if (st->instruction == CSYNC_INSTRUCTION_IGNORE) {
|
||||
if( type == CSYNC_FTW_TYPE_SLINK ) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK; /* Symbolic links are ignored. */
|
||||
} else {
|
||||
if (excluded == CSYNC_FILE_EXCLUDE_LIST) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST; /* File listed on ignore list. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_INVALID_CHAR) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS; /* File contains invalid characters. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_TRAILING_SPACE) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_TRAILING_SPACE; /* File ends with a trailing space. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_LONG_FILENAME) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_LONG_FILENAME; /* File name is too long. */
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_HIDDEN ) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_EXCLUDE_HIDDEN;
|
||||
} else if (excluded == CSYNC_FILE_EXCLUDE_STAT_FAILED) {
|
||||
st->error_status = CSYNC_STATUS_INDIVIDUAL_STAT_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st->instruction != CSYNC_INSTRUCTION_NONE
|
||||
&& st->instruction != CSYNC_INSTRUCTION_IGNORE
|
||||
&& st->instruction != CSYNC_INSTRUCTION_UPDATE_METADATA
|
||||
&& type != CSYNC_FTW_TYPE_DIR) {
|
||||
st->child_modified = 1;
|
||||
}
|
||||
ctx->current_fs = st;
|
||||
|
||||
csync_file_stat_free(tmp);
|
||||
st->inode = fs->inode;
|
||||
st->mode = fs->mode;
|
||||
st->size = fs->size;
|
||||
st->modtime = fs->mtime;
|
||||
st->type = type;
|
||||
st->etag = NULL;
|
||||
if( fs->etag ) {
|
||||
SAFE_FREE(st->etag);
|
||||
st->etag = c_strdup(fs->etag);
|
||||
}
|
||||
csync_vio_set_file_id(st->file_id, fs->file_id);
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADURL) {
|
||||
SAFE_FREE(st->directDownloadUrl);
|
||||
st->directDownloadUrl = c_strdup(fs->directDownloadUrl);
|
||||
}
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_DIRECTDOWNLOADCOOKIES) {
|
||||
SAFE_FREE(st->directDownloadCookies);
|
||||
st->directDownloadCookies = c_strdup(fs->directDownloadCookies);
|
||||
}
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_PERM) {
|
||||
strncpy(st->remotePerm, fs->remotePerm, REMOTE_PERM_BUF_SIZE);
|
||||
}
|
||||
|
||||
st->phash = h;
|
||||
st->pathlen = len;
|
||||
memcpy(st->path, (len ? path : ""), len + 1);
|
||||
|
||||
switch (ctx->current) {
|
||||
case LOCAL_REPLICA:
|
||||
if (c_rbtree_insert(ctx->local.tree, (void *) st) < 0) {
|
||||
csync_file_stat_free(st);
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case REMOTE_REPLICA:
|
||||
if (c_rbtree_insert(ctx->remote.tree, (void *) st) < 0) {
|
||||
csync_file_stat_free(st);
|
||||
ctx->status_code = CSYNC_STATUS_TREE_ERROR;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "file: %s, instruction: %s <<=", st->path,
|
||||
csync_instruction_str(st->instruction));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csync_walker(CSYNC *ctx, const char *file, const csync_vio_file_stat_t *fs,
|
||||
enum csync_ftw_flags_e flag) {
|
||||
int rc = -1;
|
||||
int type = CSYNC_FTW_TYPE_SKIP;
|
||||
csync_file_stat_t *st = NULL;
|
||||
uint64_t h;
|
||||
|
||||
if (ctx->abort) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Aborted!");
|
||||
ctx->status_code = CSYNC_STATUS_ABORTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case CSYNC_FTW_FLAG_FILE:
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
if (fs->fields & CSYNC_VIO_FILE_STAT_FIELDS_SIZE) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=%" PRIu64 "]", file, fs->file_id, fs->size);
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [file_id=%s size=UNKNOWN]", file, fs->file_id);
|
||||
}
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "file: %s [inode=%" PRIu64 " size=%" PRIu64 "]", file, fs->inode, fs->size);
|
||||
}
|
||||
type = CSYNC_FTW_TYPE_FILE;
|
||||
break;
|
||||
case CSYNC_FTW_FLAG_DIR: /* enter directory */
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [file_id=%s]", file, fs->file_id);
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "directory: %s [inode=%" PRIu64 "]", file, fs->inode);
|
||||
}
|
||||
type = CSYNC_FTW_TYPE_DIR;
|
||||
break;
|
||||
case CSYNC_FTW_FLAG_NSTAT: /* not statable file */
|
||||
/* if file was here before and now is not longer stat-able, still
|
||||
* add it to the db, otherwise not. */
|
||||
h = _hash_of_file( ctx, file );
|
||||
if( h == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
st = csync_statedb_get_stat_by_hash(ctx, h);
|
||||
if( !st ) {
|
||||
return 0;
|
||||
}
|
||||
csync_file_stat_free(st);
|
||||
st = NULL;
|
||||
|
||||
type = CSYNC_FTW_TYPE_SKIP;
|
||||
break;
|
||||
case CSYNC_FTW_FLAG_SLINK:
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "symlink: %s - not supported", file);
|
||||
type = CSYNC_FTW_TYPE_SLINK;
|
||||
break;
|
||||
case CSYNC_FTW_FLAG_DNR:
|
||||
case CSYNC_FTW_FLAG_DP:
|
||||
case CSYNC_FTW_FLAG_SLN:
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = _csync_detect_update(ctx, file, fs, type );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool fill_tree_from_db(CSYNC *ctx, const char *uri)
|
||||
{
|
||||
if( csync_statedb_get_below_path(ctx, uri) < 0 ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "StateDB could not be read!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* set the current item to an ignored state.
|
||||
* If the item is set to ignored, the update phase continues, ie. its not a hard error */
|
||||
static bool mark_current_item_ignored( CSYNC *ctx, csync_file_stat_t *previous_fs, CSYNC_STATUS status )
|
||||
{
|
||||
if(!ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctx->current_fs) {
|
||||
ctx->current_fs->instruction = CSYNC_INSTRUCTION_IGNORE;
|
||||
ctx->current_fs->error_status = status;
|
||||
/* If a directory has ignored files, put the flag on the parent directory as well */
|
||||
if( previous_fs ) {
|
||||
previous_fs->has_ignored_files = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* File tree walker */
|
||||
int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
unsigned int depth) {
|
||||
char *filename = NULL;
|
||||
char *d_name = NULL;
|
||||
csync_vio_handle_t *dh = NULL;
|
||||
csync_vio_file_stat_t *dirent = NULL;
|
||||
csync_file_stat_t *previous_fs = NULL;
|
||||
int read_from_db = 0;
|
||||
int rc = 0;
|
||||
int res = 0;
|
||||
|
||||
bool do_read_from_db = (ctx->current == REMOTE_REPLICA && ctx->remote.read_from_db);
|
||||
|
||||
read_from_db = ctx->remote.read_from_db;
|
||||
|
||||
// if the etag of this dir is still the same, its content is restored from the
|
||||
// database.
|
||||
if( do_read_from_db ) {
|
||||
if( ! fill_tree_from_db(ctx, uri) ) {
|
||||
errno = ENOENT;
|
||||
ctx->status_code = CSYNC_STATUS_OPENDIR_ERROR;
|
||||
goto error;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((dh = csync_vio_opendir(ctx, uri)) == NULL) {
|
||||
if (ctx->abort) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "Aborted!");
|
||||
ctx->status_code = CSYNC_STATUS_ABORTED;
|
||||
goto error;
|
||||
}
|
||||
int asp = 0;
|
||||
/* permission denied */
|
||||
ctx->status_code = csync_errno_to_status(errno, CSYNC_STATUS_OPENDIR_ERROR);
|
||||
if (errno == EACCES) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Permission denied.");
|
||||
if (mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_PERMISSION_DENIED)) {
|
||||
goto done;
|
||||
}
|
||||
} else if(errno == ENOENT) {
|
||||
asp = asprintf( &ctx->error_string, "%s", uri);
|
||||
if (asp < 0) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "asprintf failed!");
|
||||
}
|
||||
}
|
||||
// 403 Forbidden can be sent by the server if the file firewall is active.
|
||||
// A file or directory should be ignored and sync must continue. See #3490
|
||||
else if(errno == ERRNO_FORBIDDEN) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Directory access Forbidden (File Firewall?)");
|
||||
if( mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_FORBIDDEN) ) {
|
||||
goto done;
|
||||
}
|
||||
/* if current_fs is not defined here, better throw an error */
|
||||
}
|
||||
// The server usually replies with the custom "503 Storage not available"
|
||||
// if some path is temporarily unavailable. But in some cases a standard 503
|
||||
// is returned too. Thus we can't distinguish the two and will treat any
|
||||
// 503 as request to ignore the folder. See #3113 #2884.
|
||||
else if(errno == ERRNO_STORAGE_UNAVAILABLE || errno == ERRNO_SERVICE_UNAVAILABLE) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Storage was not available!");
|
||||
if( mark_current_item_ignored(ctx, previous_fs, CSYNC_STATUS_STORAGE_UNAVAILABLE ) ) {
|
||||
goto done;
|
||||
}
|
||||
/* if current_fs is not defined here, better throw an error */
|
||||
} else {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "opendir failed for %s - errno %d", uri, errno);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
while ((dirent = csync_vio_readdir(ctx, dh))) {
|
||||
int flen;
|
||||
int flag;
|
||||
|
||||
/* Conversion error */
|
||||
if (dirent->name == NULL && dirent->original_name) {
|
||||
ctx->status_code = CSYNC_STATUS_INVALID_CHARACTERS;
|
||||
ctx->error_string = dirent->original_name; // take ownership
|
||||
dirent->original_name = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
d_name = dirent->name;
|
||||
if (d_name == NULL) {
|
||||
ctx->status_code = CSYNC_STATUS_READDIR_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* skip "." and ".." */
|
||||
if ( (d_name[0] == '.' && d_name[1] == '\0')
|
||||
|| (d_name[0] == '.' && d_name[1] == '.' && d_name[2] == '\0')) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uri[0] == '\0') {
|
||||
filename = c_strdup(d_name);
|
||||
flen = strlen(d_name);
|
||||
} else {
|
||||
flen = asprintf(&filename, "%s/%s", uri, d_name);
|
||||
}
|
||||
if (flen < 0 || !filename) {
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
ctx->status_code = CSYNC_STATUS_MEMORY_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Only for the local replica we have to stat(), for the remote one we have all data already */
|
||||
if (ctx->replica == LOCAL_REPLICA) {
|
||||
res = csync_vio_stat(ctx, filename, dirent);
|
||||
} else {
|
||||
res = 0;
|
||||
}
|
||||
|
||||
/* if the filename starts with a . we consider it a hidden file
|
||||
* For windows, the hidden state is also discovered within the vio
|
||||
* local stat function.
|
||||
*/
|
||||
if( d_name[0] == '.' ) {
|
||||
if (strcmp(".sys.admin#recall#", d_name) != 0) { /* recall file shall not be ignored (#4420) */
|
||||
dirent->flags |= CSYNC_VIO_FILE_FLAGS_HIDDEN;
|
||||
}
|
||||
}
|
||||
|
||||
if( res == 0) {
|
||||
switch (dirent->type) {
|
||||
case CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK:
|
||||
flag = CSYNC_FTW_FLAG_SLINK;
|
||||
break;
|
||||
case CSYNC_VIO_FILE_TYPE_DIRECTORY:
|
||||
flag = CSYNC_FTW_FLAG_DIR;
|
||||
break;
|
||||
case CSYNC_VIO_FILE_TYPE_BLOCK_DEVICE:
|
||||
case CSYNC_VIO_FILE_TYPE_CHARACTER_DEVICE:
|
||||
case CSYNC_VIO_FILE_TYPE_SOCKET:
|
||||
flag = CSYNC_FTW_FLAG_SPEC;
|
||||
break;
|
||||
case CSYNC_VIO_FILE_TYPE_FIFO:
|
||||
flag = CSYNC_FTW_FLAG_SPEC;
|
||||
break;
|
||||
default:
|
||||
flag = CSYNC_FTW_FLAG_FILE;
|
||||
break;
|
||||
};
|
||||
} else {
|
||||
flag = CSYNC_FTW_FLAG_NSTAT;
|
||||
}
|
||||
|
||||
previous_fs = ctx->current_fs;
|
||||
|
||||
/* Call walker function for each file */
|
||||
rc = fn(ctx, filename, dirent, flag);
|
||||
/* this function may update ctx->current and ctx->read_from_db */
|
||||
|
||||
if (rc < 0) {
|
||||
if (CSYNC_STATUS_IS_OK(ctx->status_code)) {
|
||||
ctx->status_code = CSYNC_STATUS_UPDATE_ERROR;
|
||||
}
|
||||
|
||||
ctx->current_fs = previous_fs;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (flag == CSYNC_FTW_FLAG_DIR && depth && rc == 0
|
||||
&& (!ctx->current_fs || ctx->current_fs->instruction != CSYNC_INSTRUCTION_IGNORE)) {
|
||||
rc = csync_ftw(ctx, filename, fn, depth - 1);
|
||||
if (rc < 0) {
|
||||
ctx->current_fs = previous_fs;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ctx->current_fs && !ctx->current_fs->child_modified
|
||||
&& ctx->current_fs->instruction == CSYNC_INSTRUCTION_EVAL) {
|
||||
if (ctx->current == REMOTE_REPLICA) {
|
||||
ctx->current_fs->instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
} else {
|
||||
ctx->current_fs->instruction = CSYNC_INSTRUCTION_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->current_fs && previous_fs && ctx->current_fs->has_ignored_files) {
|
||||
/* If a directory has ignored files, put the flag on the parent directory as well */
|
||||
previous_fs->has_ignored_files = ctx->current_fs->has_ignored_files;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->current_fs && previous_fs && ctx->current_fs->child_modified) {
|
||||
/* If a directory has modified files, put the flag on the parent directory as well */
|
||||
previous_fs->child_modified = ctx->current_fs->child_modified;
|
||||
}
|
||||
|
||||
ctx->current_fs = previous_fs;
|
||||
ctx->remote.read_from_db = read_from_db;
|
||||
SAFE_FREE(filename);
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
dirent = NULL;
|
||||
}
|
||||
|
||||
csync_vio_closedir(ctx, dh);
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, " <= Closing walk for %s with read_from_db %d", uri, read_from_db);
|
||||
|
||||
done:
|
||||
csync_vio_file_stat_destroy(dirent);
|
||||
SAFE_FREE(filename);
|
||||
return rc;
|
||||
error:
|
||||
ctx->remote.read_from_db = read_from_db;
|
||||
if (dh != NULL) {
|
||||
csync_vio_closedir(ctx, dh);
|
||||
}
|
||||
SAFE_FREE(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* vim: set ts=8 sw=2 et cindent: */
|
||||
@@ -1,743 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2003-2004 by Andrew Suffield <asuffield@debian.org>
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code was originally released under GPL but Andrew Suffield agreed to
|
||||
* change it to LGPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* static function don't have NULL pointer checks, segfaults are intended.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "c_alloc.h"
|
||||
#include "c_rbtree.h"
|
||||
|
||||
#define NIL &_sentinel /* all leafs are sentinels */
|
||||
static c_rbnode_t _sentinel = {NULL, NIL, NIL, NULL, NULL, BLACK};
|
||||
|
||||
void c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare) {
|
||||
assert(rbtree);
|
||||
assert(key_compare);
|
||||
assert(data_compare);
|
||||
|
||||
c_rbtree_t *tree = NULL;
|
||||
|
||||
tree = c_malloc(sizeof(*tree));
|
||||
tree->root = NIL;
|
||||
tree->key_compare = key_compare;
|
||||
tree->data_compare = data_compare;
|
||||
tree->size = 0;
|
||||
|
||||
*rbtree = tree;
|
||||
}
|
||||
|
||||
static c_rbnode_t *_rbtree_subtree_dup(const c_rbnode_t *node, c_rbtree_t *new_tree, c_rbnode_t *new_parent) {
|
||||
c_rbnode_t *new_node = NULL;
|
||||
|
||||
new_node = (c_rbnode_t*) c_malloc(sizeof(c_rbnode_t));
|
||||
|
||||
new_node->tree = new_tree;
|
||||
new_node->data = node->data;
|
||||
new_node->color = node->color;
|
||||
new_node->parent = new_parent;
|
||||
|
||||
if (node->left == NIL) {
|
||||
new_node->left = NIL;
|
||||
} else {
|
||||
new_node->left = _rbtree_subtree_dup(node->left, new_tree, new_node);
|
||||
}
|
||||
|
||||
if (node->right == NIL) {
|
||||
new_node->right = NIL;
|
||||
} else {
|
||||
new_node->right = _rbtree_subtree_dup(node->right, new_tree, new_node);
|
||||
}
|
||||
|
||||
return new_node;
|
||||
}
|
||||
|
||||
c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree) {
|
||||
c_rbtree_t *new_tree = NULL;
|
||||
|
||||
new_tree = (c_rbtree_t*) c_malloc(sizeof(c_rbtree_t));
|
||||
|
||||
new_tree->key_compare = tree->key_compare;
|
||||
new_tree->data_compare = tree->data_compare;
|
||||
new_tree->size = tree->size;
|
||||
new_tree->root = _rbtree_subtree_dup(tree->root, new_tree, NULL);
|
||||
|
||||
return new_tree;
|
||||
}
|
||||
|
||||
static int _rbtree_subtree_free(c_rbnode_t *node) {
|
||||
assert(node);
|
||||
|
||||
if (node->left != NIL) {
|
||||
if (_rbtree_subtree_free(node->left) < 0) {
|
||||
/* TODO: set errno? ECANCELED? */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->right != NIL) {
|
||||
if (_rbtree_subtree_free(node->right) < 0) {
|
||||
/* TODO: set errno? ECANCELED? */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_FREE(node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_rbtree_free(c_rbtree_t *tree) {
|
||||
if (tree == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tree->root != NIL) {
|
||||
_rbtree_subtree_free(tree->root);
|
||||
}
|
||||
|
||||
SAFE_FREE(tree);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rbtree_subtree_walk(c_rbnode_t *node, void *data, c_rbtree_visit_func *visitor) {
|
||||
assert(node);
|
||||
assert(data);
|
||||
assert(visitor);
|
||||
|
||||
if (node == NIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_rbtree_subtree_walk(node->left, data, visitor) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*visitor)(node->data, data) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_rbtree_subtree_walk(node->right, data, visitor) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor) {
|
||||
if (tree == NULL || data == NULL || visitor == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_rbtree_subtree_walk(tree->root, data, visitor) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static c_rbnode_t *_rbtree_subtree_head(c_rbnode_t *node) {
|
||||
assert(node);
|
||||
|
||||
if (node == NIL) {
|
||||
return node;
|
||||
}
|
||||
|
||||
while (node->left != NIL) {
|
||||
node = node->left;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static c_rbnode_t *_rbtree_subtree_tail(c_rbnode_t *node) {
|
||||
assert(node);
|
||||
|
||||
if (node == NIL) {
|
||||
return node;
|
||||
}
|
||||
|
||||
while (node->right != NIL) {
|
||||
node = node->right;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
c_rbnode_t *c_rbtree_head(c_rbtree_t *tree) {
|
||||
c_rbnode_t *node = NULL;
|
||||
|
||||
if (tree == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = _rbtree_subtree_head(tree->root);
|
||||
|
||||
return node != NIL ? node : NULL;
|
||||
}
|
||||
|
||||
c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree) {
|
||||
c_rbnode_t *node = NULL;
|
||||
|
||||
if (tree == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = _rbtree_subtree_tail(tree->root);
|
||||
|
||||
return node != NIL ? node : NULL;
|
||||
}
|
||||
|
||||
c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node) {
|
||||
c_rbnode_t *parent = NULL;
|
||||
|
||||
if (node == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->right != NIL) {
|
||||
c_rbnode_t *next = NULL;
|
||||
next = _rbtree_subtree_head(node->right);
|
||||
|
||||
return next != NIL ? next : NULL;
|
||||
}
|
||||
|
||||
parent = node->parent;
|
||||
while (parent && node == parent->right) {
|
||||
node = parent;
|
||||
parent = node->parent;
|
||||
}
|
||||
|
||||
return parent != NULL ? parent : NULL;
|
||||
}
|
||||
|
||||
c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node) {
|
||||
c_rbnode_t *parent = NULL;
|
||||
|
||||
if (node == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->left != NIL) {
|
||||
c_rbnode_t *prev = NULL;
|
||||
prev = _rbtree_subtree_tail(node->left);
|
||||
return prev != NIL ? prev : NULL;
|
||||
}
|
||||
|
||||
parent = node->parent;
|
||||
while (parent && node == parent->left) {
|
||||
node = parent;
|
||||
parent = node->parent;
|
||||
}
|
||||
|
||||
return parent != NULL ? parent : NULL;
|
||||
}
|
||||
|
||||
c_rbnode_t *c_rbtree_find(c_rbtree_t *tree, const void *key) {
|
||||
int cmp = 0;
|
||||
c_rbnode_t *node = NULL;
|
||||
|
||||
if (tree == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
node = tree->root;
|
||||
|
||||
while (node != NIL) {
|
||||
cmp = tree->key_compare(key, node->data);
|
||||
if (cmp == 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (cmp < 0) {
|
||||
node = node->left;
|
||||
} else {
|
||||
node = node->right;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _rbtree_subtree_left_rotate(c_rbnode_t *x) {
|
||||
c_rbnode_t *y = NULL;
|
||||
|
||||
assert(x);
|
||||
|
||||
y = x->right;
|
||||
|
||||
/* establish x-right link */
|
||||
x->right = y->left;
|
||||
|
||||
if (y->left != NIL) {
|
||||
y->left->parent = x;
|
||||
}
|
||||
|
||||
/* establish y->parent link */
|
||||
if (y != NIL) {
|
||||
y->parent = x->parent;
|
||||
}
|
||||
|
||||
if (x->parent) {
|
||||
if (x == x->parent->left) {
|
||||
x->parent->left = y;
|
||||
} else {
|
||||
x->parent->right = y;
|
||||
}
|
||||
} else {
|
||||
x->tree->root = y;
|
||||
}
|
||||
|
||||
/* link x and y */
|
||||
y->left = x;
|
||||
if (x != NIL) {
|
||||
x->parent = y;
|
||||
}
|
||||
}
|
||||
|
||||
/* rotat node x to the right */
|
||||
static void _rbtree_subtree_right_rotate(c_rbnode_t *x) {
|
||||
c_rbnode_t *y = NULL;
|
||||
|
||||
assert(x);
|
||||
|
||||
y = x->left;
|
||||
|
||||
/* establish x->left link */
|
||||
x->left = y->right;
|
||||
|
||||
if (y->right != NIL) {
|
||||
y->right->parent = x;
|
||||
}
|
||||
|
||||
/* establish y->parent link */
|
||||
if (y != NIL) {
|
||||
y->parent = x->parent;
|
||||
}
|
||||
|
||||
if (x->parent) {
|
||||
if (x == x->parent->right) {
|
||||
x->parent->right = y;
|
||||
} else {
|
||||
x->parent->left = y;
|
||||
}
|
||||
} else {
|
||||
x->tree->root = y;
|
||||
}
|
||||
|
||||
/* link x and y */
|
||||
y->right = x;
|
||||
if (x != NIL) {
|
||||
x->parent = y;
|
||||
}
|
||||
}
|
||||
|
||||
int c_rbtree_insert(c_rbtree_t *tree, void *data) {
|
||||
int cmp = 0;
|
||||
c_rbnode_t *current = NULL;
|
||||
c_rbnode_t *parent = NULL;
|
||||
c_rbnode_t *x = NULL;
|
||||
|
||||
if (tree == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* First we do a classic binary tree insert */
|
||||
current = tree->root;
|
||||
parent = NULL;
|
||||
|
||||
while (current != NIL) {
|
||||
cmp = tree->data_compare(data, current->data);
|
||||
parent = current;
|
||||
if (cmp == 0) {
|
||||
return 1;
|
||||
} else if (cmp < 0) {
|
||||
current = current->left;
|
||||
} else {
|
||||
current = current->right;
|
||||
}
|
||||
}
|
||||
|
||||
x = (c_rbnode_t *) c_malloc(sizeof(c_rbnode_t));
|
||||
|
||||
x->tree = tree;
|
||||
x->data = data;
|
||||
x->parent = parent;
|
||||
x->left = NIL;
|
||||
x->right = NIL;
|
||||
x->color = RED;
|
||||
|
||||
if (parent) {
|
||||
/* Note that cmp still contains the comparison of data with
|
||||
* parent->data, from the last pass through the loop above
|
||||
*/
|
||||
if (cmp < 0) {
|
||||
parent->left = x;
|
||||
} else {
|
||||
parent->right = x;
|
||||
}
|
||||
} else {
|
||||
tree->root = x;
|
||||
}
|
||||
|
||||
/* Insert fixup - check red-black properties */
|
||||
while (x != tree->root && x->parent->color == RED) {
|
||||
/* we have a violation */
|
||||
if (x->parent == x->parent->parent->left) {
|
||||
c_rbnode_t *y = NULL;
|
||||
|
||||
y = x->parent->parent->right;
|
||||
if (y->color == RED) {
|
||||
x->parent->color = BLACK;
|
||||
y->color = BLACK;
|
||||
x->parent->parent->color = RED;
|
||||
x = x->parent->parent;
|
||||
} else {
|
||||
/* uncle is back */
|
||||
if (x == x->parent->right) {
|
||||
/* make x a left child */
|
||||
x = x->parent;
|
||||
_rbtree_subtree_left_rotate(x);
|
||||
}
|
||||
x->parent->color = BLACK;
|
||||
x->parent->parent->color = RED;
|
||||
_rbtree_subtree_right_rotate(x->parent->parent);
|
||||
}
|
||||
} else {
|
||||
c_rbnode_t *y = NULL;
|
||||
|
||||
y = x->parent->parent->left;
|
||||
if (y->color == RED) {
|
||||
x->parent->color = BLACK;
|
||||
y->color = BLACK;
|
||||
x->parent->parent->color = RED;
|
||||
x = x->parent->parent;
|
||||
} else {
|
||||
/* uncle is back */
|
||||
if (x == x->parent->left) {
|
||||
x = x->parent;
|
||||
_rbtree_subtree_right_rotate(x);
|
||||
}
|
||||
x->parent->color = BLACK;
|
||||
x->parent->parent->color = RED;
|
||||
_rbtree_subtree_left_rotate(x->parent->parent);
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
tree->root->color = BLACK;
|
||||
|
||||
tree->size++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int c_rbtree_node_delete(c_rbnode_t *node) {
|
||||
c_rbtree_t *tree;
|
||||
c_rbnode_t *y;
|
||||
c_rbnode_t *x;
|
||||
|
||||
if (node == NULL || node == NIL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tree = node->tree;
|
||||
|
||||
if (node->left == NIL || node->right == NIL) {
|
||||
/* y has a NIL node as a child */
|
||||
y = node;
|
||||
} else {
|
||||
/* find tree successor with a NIL node as a child */
|
||||
y = node;
|
||||
while(y->left != NIL) {
|
||||
y = y->left;
|
||||
}
|
||||
}
|
||||
|
||||
/* x is y's only child */
|
||||
if (y->left != NIL) {
|
||||
x = y->left;
|
||||
} else {
|
||||
x = y->right;
|
||||
}
|
||||
|
||||
/* remove y from the parent chain */
|
||||
x->parent = y->parent;
|
||||
|
||||
if (y->parent) {
|
||||
if (y == y->parent->left) {
|
||||
y->parent->left = x;
|
||||
} else {
|
||||
y->parent->right = x;
|
||||
}
|
||||
} else {
|
||||
y->tree->root = x;
|
||||
}
|
||||
|
||||
/* If y is not the node we're deleting, splice it in place of that
|
||||
* node
|
||||
*
|
||||
* The traditional code would call for us to simply copy y->data, but
|
||||
* that would invalidate the wrong pointer - there might be external
|
||||
* references to this node, and we must preserve its address.
|
||||
*/
|
||||
if (y != node) {
|
||||
/* Update y */
|
||||
y->parent = node->parent;
|
||||
y->left = node->left;
|
||||
y->right = node->right;
|
||||
|
||||
/* Update the children and the parent */
|
||||
if (y->left != NIL) {
|
||||
y->left->parent = y;
|
||||
}
|
||||
if (y->right != NIL) {
|
||||
y->right->parent = y;
|
||||
}
|
||||
if (y->parent != NULL) {
|
||||
if (node == y->parent->left) {
|
||||
y->parent->left = y;
|
||||
} else {
|
||||
y->parent->right = y;
|
||||
}
|
||||
} else {
|
||||
y->tree->root = y;
|
||||
}
|
||||
}
|
||||
|
||||
if (y->color == BLACK) {
|
||||
while (x != y->tree->root && x->color == BLACK) {
|
||||
if (x == x->parent->left) {
|
||||
c_rbnode_t *w = NULL;
|
||||
|
||||
w = x->parent->right;
|
||||
|
||||
if (w->color == RED) {
|
||||
w->color = BLACK;
|
||||
x->parent->color = RED;
|
||||
_rbtree_subtree_left_rotate(x->parent);
|
||||
w = x->parent->right;
|
||||
}
|
||||
|
||||
if (w->left->color == BLACK && w->right->color == BLACK) {
|
||||
w->color = RED;
|
||||
x = x->parent;
|
||||
} else {
|
||||
if (w->right->color == BLACK) {
|
||||
w->left->color = BLACK;
|
||||
w->color = RED;
|
||||
_rbtree_subtree_right_rotate(w);
|
||||
w = x->parent->right;
|
||||
}
|
||||
w->color = x->parent->color;
|
||||
x->parent->color = BLACK;
|
||||
w->right->color = BLACK;
|
||||
_rbtree_subtree_left_rotate(x->parent);
|
||||
x = y->tree->root;
|
||||
}
|
||||
} else {
|
||||
c_rbnode_t *w = NULL;
|
||||
|
||||
w = x->parent->left;
|
||||
if (w->color == RED) {
|
||||
w->color = BLACK;
|
||||
x->parent->color = RED;
|
||||
_rbtree_subtree_right_rotate(x->parent);
|
||||
w = x->parent->left;
|
||||
}
|
||||
|
||||
if (w->right->color == BLACK && w->left->color == BLACK) {
|
||||
w->color = RED;
|
||||
x = x->parent;
|
||||
} else {
|
||||
if (w->left->color == BLACK) {
|
||||
w->right->color = BLACK;
|
||||
w->color = RED;
|
||||
_rbtree_subtree_left_rotate(w);
|
||||
w = x->parent->left;
|
||||
}
|
||||
w->color = x->parent->color;
|
||||
x->parent->color = BLACK;
|
||||
w->left->color = BLACK;
|
||||
_rbtree_subtree_right_rotate(x->parent);
|
||||
x = y->tree->root;
|
||||
}
|
||||
}
|
||||
}
|
||||
x->color = BLACK;
|
||||
} /* end if: y->color == BLACK */
|
||||
|
||||
/* node has now been spliced out of the tree */
|
||||
SAFE_FREE(y);
|
||||
tree->size--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _rbtree_subtree_check_black_height(c_rbnode_t *node) {
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
|
||||
assert(node);
|
||||
|
||||
if (node == NIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
left = _rbtree_subtree_check_black_height(node->left);
|
||||
right = _rbtree_subtree_check_black_height(node->right);
|
||||
if (left != right) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return left + (node->color == BLACK);
|
||||
}
|
||||
|
||||
int c_rbtree_check_sanity(c_rbtree_t *tree) {
|
||||
c_rbnode_t *node = NULL;
|
||||
c_rbnode_t *prev = NULL;
|
||||
c_rbnode_t *next = NULL;
|
||||
c_rbnode_t *tail = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
if (tree == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! tree->key_compare || ! tree->data_compare) {
|
||||
errno = EINVAL;
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Iterate the tree */
|
||||
tail = c_rbtree_tail(tree);
|
||||
for (node = c_rbtree_head(tree); node; node = next) {
|
||||
if (node->tree != tree) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
/* We should never see a nil while iterating */
|
||||
if (node == NIL) {
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* node == tree-root iff node->parent == NIL */
|
||||
if (node == tree->root) {
|
||||
if (node->parent != NULL) {
|
||||
return -6;
|
||||
}
|
||||
} else {
|
||||
if (node->parent == NULL) {
|
||||
return -7;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invertability of the iterate functions */
|
||||
if (prev != c_rbtree_node_prev(node)) {
|
||||
return -8;
|
||||
}
|
||||
|
||||
/* Check the iteration sequence */
|
||||
if (prev) {
|
||||
if (tree->data_compare(prev->data, node->data) > 0) {
|
||||
return -9;
|
||||
}
|
||||
|
||||
/* And the other way around, to make sure data_compare is stable */
|
||||
if (tree->data_compare(node->data, prev->data) < 0) {
|
||||
return -10;
|
||||
}
|
||||
}
|
||||
|
||||
/* The binary tree property */
|
||||
if (node->left != NIL) {
|
||||
if (tree->data_compare(node->left->data, node->data) > 0) {
|
||||
return -11;
|
||||
}
|
||||
|
||||
if (tree->data_compare(node->data, node->left->data) < 0) {
|
||||
return -11;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->right != NIL) {
|
||||
if (tree->data_compare(node->data, node->right->data) > 0) {
|
||||
return -12;
|
||||
}
|
||||
|
||||
if (tree->data_compare(node->right->data, node->data) < 0) {
|
||||
return -13;
|
||||
}
|
||||
}
|
||||
|
||||
/* Red-black tree property 3: red nodes have black children */
|
||||
if (node->color == RED) {
|
||||
if (node->left->color == RED) {
|
||||
return -14;
|
||||
}
|
||||
if (node->right->color == RED) {
|
||||
return -15;
|
||||
}
|
||||
}
|
||||
|
||||
/* next == NULL if node == tail */
|
||||
next = c_rbtree_node_next(node);
|
||||
if (next) {
|
||||
if (node == tail) {
|
||||
return -16;
|
||||
}
|
||||
} else {
|
||||
if (node != tail) {
|
||||
return -17;
|
||||
}
|
||||
}
|
||||
|
||||
prev = node;
|
||||
size++;
|
||||
} /* end for loop */
|
||||
|
||||
if (size != tree->size) {
|
||||
return -18;
|
||||
}
|
||||
|
||||
if (_rbtree_subtree_check_black_height(tree->root) < 0) {
|
||||
return -19;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* cynapses libc functions
|
||||
*
|
||||
* Copyright (c) 2003-2004 by Andrew Suffield <asuffield@debian.org>
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c_rbtree.h
|
||||
*
|
||||
* @brief Interface of the cynapses libc red-black tree implementation
|
||||
*
|
||||
* A red-black tree is a type of self-balancing binary search tree. It is
|
||||
* complex, but has good worst-case running time for its operations and is
|
||||
* efficient in practice: it can search, insert, and delete in O(log n)
|
||||
* time, where n is the number of elements in the tree.
|
||||
*
|
||||
* In red-black trees, the leaf nodes are not relevant and do not contain
|
||||
* data. Therefore we use a sentinal node to save memory. All references
|
||||
* from internal nodes to leaf nodes instead point to the sentinel node.
|
||||
*
|
||||
* In a red-black tree each node has a color attribute, the value of which
|
||||
* is either red or black. In addition to the ordinary requirements imposed
|
||||
* on binary search trees, the following additional requirements of any
|
||||
* valid red-black tree apply:
|
||||
*
|
||||
* 1. A node is either red or black.
|
||||
* 2. The root is black.
|
||||
* 3. All leaves are black, even when the parent is black
|
||||
* (The leaves are the null children.)
|
||||
* 4. Both children of every red node are black.
|
||||
* 5. Every simple path from a node to a descendant leaf contains the same
|
||||
* number of black nodes, either counting or not counting the null black
|
||||
* nodes. (Counting or not counting the null black nodes does not affect
|
||||
* the structure as long as the choice is used consistently.).
|
||||
*
|
||||
* These constraints enforce a critical property of red-black trees: that the
|
||||
* longest path from the root to a leaf is no more than twice as long as the
|
||||
* shortest path from the root to a leaf in that tree. The result is that the
|
||||
* tree is roughly balanced. Since operations such as inserting, deleting, and
|
||||
* finding values requires worst-case time proportional to the height of the
|
||||
* tree, this theoretical upper bound on the height allows red-black trees to
|
||||
* be efficient in the worst-case, unlike ordinary binary search trees.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Red-black_tree
|
||||
*
|
||||
* @defgroup cynRBTreeInternals cynapses libc red-black tree functions
|
||||
* @ingroup cynLibraryAPI
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef _C_RBTREE_H
|
||||
#define _C_RBTREE_H
|
||||
|
||||
/* Forward declarations */
|
||||
struct c_rbtree_s; typedef struct c_rbtree_s c_rbtree_t;
|
||||
struct c_rbnode_s; typedef struct c_rbnode_s c_rbnode_t;
|
||||
|
||||
/**
|
||||
* Define the two colors for the red-black tree
|
||||
*/
|
||||
enum xrbcolor_e { BLACK = 0, RED }; typedef enum xrbcolor_e xrbcolor_t;
|
||||
|
||||
/**
|
||||
* @brief Callback function to compare a key with the data from a
|
||||
* red-black tree node.
|
||||
*
|
||||
* @param key key as a generic pointer
|
||||
* @param data data as a generic pointer
|
||||
*
|
||||
* @return It returns an integer less than, equal to, or greater than zero
|
||||
* depending on the key or data you use. The function is similar
|
||||
* to strcmp().
|
||||
*/
|
||||
typedef int c_rbtree_compare_func(const void *key, const void *data);
|
||||
|
||||
/**
|
||||
* @brief Visit function for the c_rbtree_walk() function.
|
||||
*
|
||||
* This function will be called by c_rbtree_walk() for every node. It is up to
|
||||
* the developer what the function does. The fist parameter is a node object
|
||||
* the second can be of any kind.
|
||||
*
|
||||
* @param obj The node data that will be passed by c_rbtree_walk().
|
||||
* @param data Generic data pointer.
|
||||
*
|
||||
* @return 0 on success, < 0 on error. You should set errno.
|
||||
*
|
||||
*/
|
||||
typedef int c_rbtree_visit_func(void *, void *);
|
||||
|
||||
/**
|
||||
* Structure that represents a red-black tree
|
||||
*/
|
||||
struct c_rbtree_s {
|
||||
c_rbnode_t *root;
|
||||
c_rbtree_compare_func *key_compare;
|
||||
c_rbtree_compare_func *data_compare;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure that represents a node of a red-black tree
|
||||
*/
|
||||
struct c_rbnode_s {
|
||||
c_rbtree_t *tree;
|
||||
c_rbnode_t *left;
|
||||
c_rbnode_t *right;
|
||||
c_rbnode_t *parent;
|
||||
void *data;
|
||||
xrbcolor_t color;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create the red-black tree
|
||||
*
|
||||
* @param rbtree The pointer to assign the allocated memory.
|
||||
*
|
||||
* @param key_compare Callback function to compare a key with the data
|
||||
* inside a reb-black tree node.
|
||||
*
|
||||
* @param data_compare Callback function to compare a key as data with thee
|
||||
* data inside a red-black tree node.
|
||||
*/
|
||||
void c_rbtree_create(c_rbtree_t **rbtree, c_rbtree_compare_func *key_compare, c_rbtree_compare_func *data_compare);
|
||||
|
||||
/**
|
||||
* @brief Duplicate a red-black tree.
|
||||
*
|
||||
* @param tree Tree to duplicate.
|
||||
*
|
||||
* @return Pointer to a new allocated duplicated rbtree. NULL if an error
|
||||
* occurred.
|
||||
*/
|
||||
c_rbtree_t *c_rbtree_dup(const c_rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Free the structure of a red-black tree.
|
||||
*
|
||||
* You should call c_rbtree_destroy() before you call this function.
|
||||
*
|
||||
* @param tree The tree to free.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_free(c_rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Destroy the content and the nodes of an red-black tree.
|
||||
*
|
||||
* This is far from the most efficient way to walk a tree, but it is
|
||||
* the *safest* way to destroy a tree - the destructor can do almost
|
||||
* anything (as long as it does not create an infinite loop) to the
|
||||
* tree structure without risk.
|
||||
*
|
||||
* If for some strange reason you need a faster destructor (think
|
||||
* twice - speed and memory deallocation don't mix well) then consider
|
||||
* stashing an llist of dataects and destroying that instead, and just
|
||||
* using c_rbtree_free() on your tree.
|
||||
*
|
||||
* @param T The tree to destroy.
|
||||
* @param DESTRUCTOR The destructor to call on a node to destroy.
|
||||
*/
|
||||
#define c_rbtree_destroy(T, DESTRUCTOR) \
|
||||
do { \
|
||||
if (T) { \
|
||||
c_rbnode_t *_c_rbtree_temp; \
|
||||
while ((_c_rbtree_temp = c_rbtree_head(T))) { \
|
||||
(DESTRUCTOR)(_c_rbtree_temp->data); \
|
||||
if (_c_rbtree_temp == c_rbtree_head(T)) { \
|
||||
c_rbtree_node_delete(_c_rbtree_temp); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
SAFE_FREE(T); \
|
||||
} while (0);
|
||||
|
||||
/**
|
||||
* @brief Inserts a node into a red black tree.
|
||||
*
|
||||
* @param tree The red black tree to insert the node.
|
||||
* @param data The data to insert into the tree.
|
||||
*
|
||||
* @return 0 on success, 1 if a duplicate has been found and < 0 if an error
|
||||
* occurred with errno set.
|
||||
* EINVAL if a null pointer has been passed as the tree.
|
||||
* ENOMEM if there is no memory left.
|
||||
*/
|
||||
int c_rbtree_insert(c_rbtree_t *tree, void *data);
|
||||
|
||||
/**
|
||||
* @brief Find a node in a red-black tree.
|
||||
*
|
||||
* c_rbtree_find() is searching for the given key in a red-black tree and
|
||||
* returns the node if the key has been found.
|
||||
*
|
||||
* @param tree The tree to search.
|
||||
* @param key The key to search for.
|
||||
*
|
||||
* @return If the key was found the node will be returned. On error NULL
|
||||
* will be returned.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_find(c_rbtree_t *tree, const void *key);
|
||||
|
||||
/**
|
||||
* @brief Get the head of the red-black tree.
|
||||
*
|
||||
* @param tree The tree to get the head for.
|
||||
*
|
||||
* @return The head node. NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_head(c_rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Get the tail of the red-black tree.
|
||||
*
|
||||
* @param tree The tree to get the tail for.
|
||||
*
|
||||
* @return The tail node. NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_tail(c_rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* @brief Get the size of the red-black tree.
|
||||
*
|
||||
* @param T The tree to get the size from.
|
||||
*
|
||||
* @return The size of the red-black tree.
|
||||
*/
|
||||
#define c_rbtree_size(T) (T) == NULL ? 0 : ((T)->size)
|
||||
|
||||
/**
|
||||
* @brief Walk over a red-black tree.
|
||||
*
|
||||
* Walk over a red-black tree calling a visitor function for each node found.
|
||||
*
|
||||
* @param tree Tree to walk.
|
||||
* @param data Data which should be passed to the visitor function.
|
||||
* @param visitor Visitor function. This will be called for each node passed.
|
||||
*
|
||||
* @return 0 on sucess, less than 0 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_walk(c_rbtree_t *tree, void *data, c_rbtree_visit_func *visitor);
|
||||
|
||||
/**
|
||||
* @brief Delete a node in a red-black tree.
|
||||
*
|
||||
* @param node Node which should be deleted.
|
||||
*
|
||||
* @return 0 on success, -1 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_node_delete(c_rbnode_t *node);
|
||||
|
||||
/**
|
||||
* @brief Get the next node.
|
||||
*
|
||||
* @param node The node of which you want the next node.
|
||||
*
|
||||
* @return The next node, NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_node_next(c_rbnode_t *node);
|
||||
|
||||
/**
|
||||
* @brief Get the previous node.
|
||||
*
|
||||
* @param node The node of which you want the previous node.
|
||||
*
|
||||
* @return The previous node, NULL if an error occurred.
|
||||
*/
|
||||
c_rbnode_t *c_rbtree_node_prev(c_rbnode_t *node);
|
||||
|
||||
/**
|
||||
* @brief Get the data of a node.
|
||||
*
|
||||
* @param N The node to get the data from.
|
||||
*
|
||||
* @return The data, NULL if an error occurred.
|
||||
*/
|
||||
#define c_rbtree_node_data(N) ((N) ? ((N)->data) : NULL)
|
||||
|
||||
/**
|
||||
* @brief Perform a sanity check for a red-black tree.
|
||||
*
|
||||
* This is mostly for testing purposes.
|
||||
*
|
||||
* @param tree The tree to check.
|
||||
*
|
||||
* @return 0 on success, less than 0 if an error occurred.
|
||||
*/
|
||||
int c_rbtree_check_sanity(c_rbtree_t *tree);
|
||||
|
||||
/**
|
||||
* }@
|
||||
*/
|
||||
#endif /* _C_RBTREE_H */
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "c_lib.h"
|
||||
#include "csync.h"
|
||||
#include "csync_log.h"
|
||||
|
||||
csync_vio_file_stat_t *csync_vio_file_stat_new(void) {
|
||||
csync_vio_file_stat_t *file_stat = (csync_vio_file_stat_t *) c_malloc(sizeof(csync_vio_file_stat_t));
|
||||
ZERO_STRUCTP(file_stat);
|
||||
return file_stat;
|
||||
}
|
||||
|
||||
csync_vio_file_stat_t* csync_vio_file_stat_copy(csync_vio_file_stat_t *file_stat) {
|
||||
csync_vio_file_stat_t *file_stat_cpy = csync_vio_file_stat_new();
|
||||
memcpy(file_stat_cpy, file_stat, sizeof(csync_vio_file_stat_t));
|
||||
if (file_stat_cpy->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) {
|
||||
file_stat_cpy->etag = c_strdup(file_stat_cpy->etag);
|
||||
}
|
||||
if (file_stat_cpy->directDownloadCookies) {
|
||||
file_stat_cpy->directDownloadCookies = c_strdup(file_stat_cpy->directDownloadCookies);
|
||||
}
|
||||
if (file_stat_cpy->directDownloadUrl) {
|
||||
file_stat_cpy->directDownloadUrl = c_strdup(file_stat_cpy->directDownloadUrl);
|
||||
}
|
||||
file_stat_cpy->name = c_strdup(file_stat_cpy->name);
|
||||
return file_stat_cpy;
|
||||
}
|
||||
|
||||
void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) {
|
||||
/* FIXME: free rest */
|
||||
if (file_stat == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_stat->fields & CSYNC_VIO_FILE_STAT_FIELDS_ETAG) {
|
||||
SAFE_FREE(file_stat->etag);
|
||||
}
|
||||
SAFE_FREE(file_stat->directDownloadUrl);
|
||||
SAFE_FREE(file_stat->directDownloadCookies);
|
||||
SAFE_FREE(file_stat->name);
|
||||
SAFE_FREE(file_stat->original_name);
|
||||
SAFE_FREE(file_stat);
|
||||
}
|
||||
|
||||
void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t *dst, const char* src ) {
|
||||
|
||||
csync_vio_set_file_id( dst->file_id, src );
|
||||
if( c_streq( dst->file_id, "" )) {
|
||||
return;
|
||||
}
|
||||
dst->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID;
|
||||
}
|
||||
|
||||
void csync_vio_set_file_id( char* dst, const char *src ) {
|
||||
if( src && dst ) {
|
||||
if( strlen(src) > FILE_ID_BUF_SIZE ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Ignoring file_id because it is too long: %s", src);
|
||||
strcpy(dst, "");
|
||||
} else {
|
||||
strcpy(dst, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
project(tests C)
|
||||
|
||||
set(TORTURE_LIBRARY torture)
|
||||
|
||||
include_directories(
|
||||
${CSYNC_PUBLIC_INCLUDE_DIRS}
|
||||
${CSTDLIB_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMOCKA_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
include_directories(${CHECK_INCLUDE_DIRS})
|
||||
# create test library
|
||||
add_library(${TORTURE_LIBRARY} STATIC torture.c cmdline.c)
|
||||
target_link_libraries(${TORTURE_LIBRARY} ${CMOCKA_LIBRARIES} ${CSYNC_LIBRARY} ${CSTDLIB_LIBRARY})
|
||||
|
||||
set(TEST_TARGET_LIBRARIES ${TORTURE_LIBRARY})
|
||||
|
||||
# create tests
|
||||
|
||||
# std
|
||||
add_cmocka_test(check_std_c_alloc std_tests/check_std_c_alloc.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_jhash std_tests/check_std_c_jhash.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_path std_tests/check_std_c_path.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_rbtree std_tests/check_std_c_rbtree.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_str std_tests/check_std_c_str.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_std_c_time std_tests/check_std_c_time.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
# csync tests
|
||||
# This will be rewritten soon anyway.
|
||||
#add_cmocka_test(check_logger log_tests/check_log.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
add_cmocka_test(check_csync_create csync_tests/check_csync_create.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_log csync_tests/check_csync_log.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_exclude csync_tests/check_csync_exclude.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_statedb_load csync_tests/check_csync_statedb_load.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_util csync_tests/check_csync_util.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_misc csync_tests/check_csync_misc.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
# csync tests which require init
|
||||
add_cmocka_test(check_csync_init csync_tests/check_csync_init.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_statedb_query csync_tests/check_csync_statedb_query.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_csync_commit csync_tests/check_csync_commit.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
# vio
|
||||
add_cmocka_test(check_vio_file_stat vio_tests/check_vio_file_stat.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_vio vio_tests/check_vio.c ${TEST_TARGET_LIBRARIES})
|
||||
add_cmocka_test(check_vio_ext vio_tests/check_vio_ext.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
# sync
|
||||
add_cmocka_test(check_csync_update csync_tests/check_csync_update.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
# encoding
|
||||
add_cmocka_test(check_encoding_functions encoding_tests/check_encoding.c ${TEST_TARGET_LIBRARIES})
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_module(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
csync_init(csync, "foo");
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_commit(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_commit(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1);
|
||||
}
|
||||
|
||||
static void check_csync_commit_dummy(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_commit(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1);
|
||||
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_commit, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
|
||||
static void check_csync_destroy_null(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = csync_destroy(NULL);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_csync_create(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
csync_create(&csync, "/tmp/csync1");
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(check_csync_destroy_null),
|
||||
cmocka_unit_test(check_csync_create),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_module(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
*state = csync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_init(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
|
||||
csync_init(csync, "");
|
||||
|
||||
assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1);
|
||||
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_init, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_init, setup_module, teardown),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#define CSYNC_TEST 1
|
||||
#include "csync_statedb.c"
|
||||
|
||||
#define TESTDB "/tmp/check_csync1/test.db"
|
||||
|
||||
static int setup(void **state) {
|
||||
CSYNC *csync;
|
||||
int rc;
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
|
||||
csync->statedb.file = c_strdup( TESTDB );
|
||||
*state = csync;
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
rc = sqlite3_close(db);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_csync_statedb_load(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
int rc;
|
||||
|
||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
sqlite3_close(csync->statedb.db);
|
||||
}
|
||||
|
||||
static void check_csync_statedb_close(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_stat_t sb;
|
||||
time_t modtime;
|
||||
mbchar_t *testdb = c_utf8_path_to_locale(TESTDB);
|
||||
int rc;
|
||||
|
||||
/* statedb not written */
|
||||
csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
|
||||
rc = _tstat(testdb, &sb);
|
||||
assert_int_equal(rc, 0);
|
||||
modtime = sb.st_mtime;
|
||||
|
||||
rc = csync_statedb_close(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = _tstat(testdb, &sb);
|
||||
assert_int_equal(rc, 0);
|
||||
assert_int_equal(modtime, sb.st_mtime);
|
||||
|
||||
csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
|
||||
rc = _tstat(testdb, &sb);
|
||||
assert_int_equal(rc, 0);
|
||||
modtime = sb.st_mtime;
|
||||
|
||||
/* wait a sec or the modtime will be the same */
|
||||
sleep(1);
|
||||
|
||||
/* statedb written */
|
||||
rc = csync_statedb_close(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = _tstat(testdb, &sb);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
c_free_locale_string(testdb);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_load, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_close, setup, teardown),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "torture.h"
|
||||
|
||||
#define CSYNC_TEST 1
|
||||
#include "csync_statedb.c"
|
||||
|
||||
#define TESTDB "/tmp/check_csync1/test.db"
|
||||
#define TESTDBTMP "/tmp/check_csync1/test.db.ctmp"
|
||||
|
||||
|
||||
|
||||
static int setup(void **state)
|
||||
{
|
||||
CSYNC *csync;
|
||||
int rc = 0;
|
||||
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("mkdir -p /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
csync_create(&csync, "/tmp/check_csync1");
|
||||
csync_init(csync, TESTDB);
|
||||
|
||||
sqlite3 *db = NULL;
|
||||
rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
rc = sqlite3_close(db);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = csync;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_db(void **state)
|
||||
{
|
||||
char *errmsg;
|
||||
int rc = 0;
|
||||
sqlite3 *db = NULL;
|
||||
|
||||
const char *sql = "CREATE TABLE IF NOT EXISTS metadata ("
|
||||
"phash INTEGER(8),"
|
||||
"pathlen INTEGER,"
|
||||
"path VARCHAR(4096),"
|
||||
"inode INTEGER,"
|
||||
"uid INTEGER,"
|
||||
"gid INTEGER,"
|
||||
"mode INTEGER,"
|
||||
"modtime INTEGER(8),"
|
||||
"type INTEGER,"
|
||||
"md5 VARCHAR(32),"
|
||||
"PRIMARY KEY(phash)"
|
||||
");";
|
||||
|
||||
const char *sql2 = "INSERT INTO metadata"
|
||||
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES"
|
||||
"(42, 42, 'Its funny stuff', 23, 42, 43, 55, 66, 2, 54);";
|
||||
|
||||
|
||||
setup(state);
|
||||
rc = sqlite3_open( TESTDB, &db);
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
rc = sqlite3_exec( db, sql, NULL, NULL, &errmsg );
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
rc = sqlite3_exec( db, sql2, NULL, NULL, &errmsg );
|
||||
assert_int_equal(rc, SQLITE_OK);
|
||||
|
||||
sqlite3_close(db);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int teardown(void **state) {
|
||||
CSYNC *csync = *state;
|
||||
int rc = 0;
|
||||
|
||||
rc = csync_destroy(csync);
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync");
|
||||
assert_int_equal(rc, 0);
|
||||
rc = system("rm -rf /tmp/check_csync1");
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
*state = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void check_csync_statedb_query_statement(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
c_strlist_t *result;
|
||||
|
||||
result = csync_statedb_query(csync->statedb.db, "");
|
||||
assert_null(result);
|
||||
if (result != NULL) {
|
||||
c_strlist_destroy(result);
|
||||
}
|
||||
|
||||
result = csync_statedb_query(csync->statedb.db, "SELECT;");
|
||||
assert_null(result);
|
||||
if (result != NULL) {
|
||||
c_strlist_destroy(result);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_csync_statedb_drop_tables(void **state)
|
||||
{
|
||||
// CSYNC *csync = *state;
|
||||
int rc = 0;
|
||||
(void) state;
|
||||
|
||||
// rc = csync_statedb_drop_tables(csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
// rc = csync_statedb_create_tables(csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
// rc = csync_statedb_drop_tables(csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_csync_statedb_insert_metadata(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_file_stat_t *st;
|
||||
int i, rc = 0;
|
||||
|
||||
// rc = csync_statedb_create_tables(csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
st = c_malloc(sizeof(csync_file_stat_t) + 30 );
|
||||
snprintf(st->path, 29, "file_%d" , i );
|
||||
st->phash = i;
|
||||
|
||||
rc = c_rbtree_insert(csync->local.tree, (void *) st);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
// rc = csync_statedb_insert_metadata(csync, csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_csync_statedb_write(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_file_stat_t *st;
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
st = c_malloc(sizeof(csync_file_stat_t) + 30);
|
||||
snprintf(st->path, 29, "file_%d" , i );
|
||||
st->phash = i;
|
||||
|
||||
rc = c_rbtree_insert(csync->local.tree, (void *) st);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
// rc = csync_statedb_write(csync, csync->statedb.db);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
|
||||
static void check_csync_statedb_get_stat_by_hash_not_found(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_file_stat_t *tmp;
|
||||
|
||||
tmp = csync_statedb_get_stat_by_hash(csync, (uint64_t) 666);
|
||||
assert_null(tmp);
|
||||
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
|
||||
static void check_csync_statedb_get_stat_by_inode_not_found(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
csync_file_stat_t *tmp;
|
||||
|
||||
tmp = csync_statedb_get_stat_by_inode(csync, (ino_t) 666);
|
||||
assert_null(tmp);
|
||||
}
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_write, setup, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_hash_not_found, setup_db, teardown),
|
||||
cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "torture.h"
|
||||
#include "csync_update.cpp"
|
||||
|
||||
#include "csync_update.c"
|
||||
extern "C" {
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#define TESTDB "/tmp/check_csync/journal.db"
|
||||
|
||||
@@ -52,6 +54,13 @@ static void statedb_create_metadata_table(sqlite3 *db)
|
||||
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
|
||||
//const char *msg = sqlite3_errmsg(db);
|
||||
assert_int_equal( rc, SQLITE_OK );
|
||||
|
||||
sql = "CREATE TABLE IF NOT EXISTS checksumtype("
|
||||
"id INTEGER PRIMARY KEY,"
|
||||
"name TEXT UNIQUE"
|
||||
");";
|
||||
rc = sqlite3_exec(db, sql, NULL, NULL, NULL);
|
||||
assert_int_equal( rc, SQLITE_OK );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +152,7 @@ static int setup_ftw(void **state)
|
||||
|
||||
static int teardown(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
unlink( csync->statedb.file);
|
||||
@@ -226,7 +235,7 @@ static csync_vio_file_stat_t* create_fstat(const char *name,
|
||||
static int failing_fn(CSYNC *ctx,
|
||||
const char *file,
|
||||
const csync_vio_file_stat_t *fs,
|
||||
enum csync_ftw_flags_e flag)
|
||||
int flag)
|
||||
{
|
||||
(void) ctx;
|
||||
(void) file;
|
||||
@@ -239,7 +248,7 @@ static int failing_fn(CSYNC *ctx,
|
||||
/* detect a new file */
|
||||
static void check_csync_detect_update(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
@@ -254,7 +263,7 @@ static void check_csync_detect_update(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = c_rbtree_node_data(csync->local.tree->root);
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
/* create a statedb */
|
||||
@@ -268,7 +277,7 @@ static void check_csync_detect_update(void **state)
|
||||
*/
|
||||
static void check_csync_detect_update_db_none(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
@@ -283,7 +292,7 @@ static void check_csync_detect_update_db_none(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = c_rbtree_node_data(csync->local.tree->root);
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
|
||||
@@ -295,7 +304,7 @@ static void check_csync_detect_update_db_none(void **state)
|
||||
|
||||
static void check_csync_detect_update_db_eval(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
@@ -310,7 +319,7 @@ static void check_csync_detect_update_db_eval(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = c_rbtree_node_data(csync->local.tree->root);
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
/* create a statedb */
|
||||
@@ -322,7 +331,7 @@ static void check_csync_detect_update_db_eval(void **state)
|
||||
|
||||
static void check_csync_detect_update_db_rename(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
// csync_file_stat_t *st;
|
||||
|
||||
csync_vio_file_stat_t *fs;
|
||||
@@ -341,7 +350,7 @@ static void check_csync_detect_update_db_rename(void **state)
|
||||
/* the instruction should be set to rename */
|
||||
/*
|
||||
* temporarily broken.
|
||||
st = c_rbtree_node_data(csync->local.tree->root);
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_RENAME);
|
||||
|
||||
st->instruction = CSYNC_INSTRUCTION_UPDATED;
|
||||
@@ -354,7 +363,7 @@ static void check_csync_detect_update_db_rename(void **state)
|
||||
|
||||
static void check_csync_detect_update_db_new(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_file_stat_t *st;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
@@ -369,7 +378,7 @@ static void check_csync_detect_update_db_new(void **state)
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* the instruction should be set to new */
|
||||
st = c_rbtree_node_data(csync->local.tree->root);
|
||||
st = (csync_file_stat_t*)c_rbtree_node_data(csync->local.tree->root);
|
||||
assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW);
|
||||
|
||||
|
||||
@@ -381,7 +390,7 @@ static void check_csync_detect_update_db_new(void **state)
|
||||
|
||||
static void check_csync_detect_update_null(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
csync_vio_file_stat_t *fs;
|
||||
int rc;
|
||||
|
||||
@@ -405,7 +414,7 @@ static void check_csync_detect_update_null(void **state)
|
||||
|
||||
static void check_csync_ftw(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
rc = csync_ftw(csync, "/tmp", csync_walker, MAX_DEPTH);
|
||||
@@ -414,7 +423,7 @@ static void check_csync_ftw(void **state)
|
||||
|
||||
static void check_csync_ftw_empty_uri(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
rc = csync_ftw(csync, "", csync_walker, MAX_DEPTH);
|
||||
@@ -423,7 +432,7 @@ static void check_csync_ftw_empty_uri(void **state)
|
||||
|
||||
static void check_csync_ftw_failing_fn(void **state)
|
||||
{
|
||||
CSYNC *csync = *state;
|
||||
CSYNC *csync = (CSYNC*)*state;
|
||||
int rc;
|
||||
|
||||
rc = csync_ftw(csync, "/tmp", failing_fn, MAX_DEPTH);
|
||||
@@ -448,3 +457,4 @@ int torture_run_tests(void)
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,363 +0,0 @@
|
||||
/*
|
||||
* libcsync -- a library to sync a directory with another
|
||||
*
|
||||
* Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "torture.h"
|
||||
|
||||
#include "std/c_alloc.h"
|
||||
#include "std/c_rbtree.h"
|
||||
|
||||
typedef struct test_s {
|
||||
int key;
|
||||
int number;
|
||||
} test_t;
|
||||
|
||||
static int data_cmp(const void *key, const void *data) {
|
||||
test_t *a, *b;
|
||||
|
||||
a = (test_t *) key;
|
||||
b = (test_t *) data;
|
||||
|
||||
if (a->key < b->key) {
|
||||
return -1;
|
||||
} else if (a->key > b->key) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int key_cmp(const void *key, const void *data) {
|
||||
int a;
|
||||
test_t *b;
|
||||
|
||||
a = POINTER_TO_INT(key);
|
||||
b = (test_t *) data;
|
||||
|
||||
if (a < b->key) {
|
||||
return -1;
|
||||
} else if (a > b->key) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visitor(void *obj, void *data) {
|
||||
test_t *a;
|
||||
test_t *b;
|
||||
|
||||
a = (test_t *) obj;
|
||||
b = (test_t *) data;
|
||||
|
||||
if (a->key == b->key) {
|
||||
a->number = 42;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destructor(void *data) {
|
||||
test_t *freedata = NULL;
|
||||
|
||||
freedata = (test_t *) data;
|
||||
SAFE_FREE(freedata);
|
||||
}
|
||||
|
||||
static void setup(void **state) {
|
||||
c_rbtree_t *tree = NULL;
|
||||
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
|
||||
*state = tree;
|
||||
}
|
||||
|
||||
static void setup_complete_tree(void **state) {
|
||||
c_rbtree_t *tree = NULL;
|
||||
int i = 0;
|
||||
int rc;
|
||||
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
test_t *testdata = NULL;
|
||||
|
||||
testdata = c_malloc(sizeof(test_t));
|
||||
assert_non_null(testdata);
|
||||
|
||||
testdata->key = i;
|
||||
|
||||
rc = c_rbtree_insert(tree, (void *) testdata);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
*state = tree;
|
||||
}
|
||||
|
||||
static void teardown(void **state) {
|
||||
c_rbtree_t *tree = *state;
|
||||
|
||||
c_rbtree_destroy(tree, destructor);
|
||||
c_rbtree_free(tree);
|
||||
|
||||
*state = NULL;
|
||||
}
|
||||
|
||||
static void check_c_rbtree_create_free(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = NULL;
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
assert_int_equal(tree->size, 0);
|
||||
|
||||
rc = c_rbtree_free(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_free_null(void **state)
|
||||
{
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
rc = c_rbtree_free(NULL);
|
||||
assert_int_equal(rc, -1);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_insert_delete(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = NULL;
|
||||
c_rbnode_t *node = NULL;
|
||||
test_t *testdata = NULL;
|
||||
int rc;
|
||||
|
||||
(void) state; /* unused */
|
||||
|
||||
c_rbtree_create(&tree, key_cmp, data_cmp);
|
||||
|
||||
testdata = malloc(sizeof(test_t));
|
||||
testdata->key = 42;
|
||||
|
||||
rc = c_rbtree_insert(tree, (void *) testdata);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
node = c_rbtree_head(tree);
|
||||
assert_non_null(node);
|
||||
|
||||
testdata = c_rbtree_node_data(node);
|
||||
SAFE_FREE(testdata);
|
||||
rc = c_rbtree_node_delete(node);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
c_rbtree_free(tree);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_insert_random(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
int i = 0, rc;
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
test_t *testdata = NULL;
|
||||
|
||||
testdata = malloc(sizeof(test_t));
|
||||
assert_non_null(testdata);
|
||||
|
||||
testdata->key = i;
|
||||
|
||||
rc = c_rbtree_insert(tree, testdata);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
}
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_insert_duplicate(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
test_t *testdata;
|
||||
int rc;
|
||||
|
||||
testdata = malloc(sizeof(test_t));
|
||||
assert_non_null(testdata);
|
||||
|
||||
testdata->key = 42;
|
||||
|
||||
rc = c_rbtree_insert(tree, (void *) testdata);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* add again */
|
||||
testdata = malloc(sizeof(test_t));
|
||||
assert_non_null(testdata);
|
||||
|
||||
testdata->key = 42;
|
||||
|
||||
/* check for duplicate */
|
||||
rc = c_rbtree_insert(tree, (void *) testdata);
|
||||
assert_int_equal(rc, 1);
|
||||
|
||||
free(testdata);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_find(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
int rc, i = 42;
|
||||
c_rbnode_t *node;
|
||||
test_t *testdata;
|
||||
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* find the node with the key 42 */
|
||||
node = c_rbtree_find(tree, (void *) &i);
|
||||
assert_non_null(node);
|
||||
|
||||
testdata = (test_t *) c_rbtree_node_data(node);
|
||||
assert_int_equal(testdata->key, 42);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_delete(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
int rc, i = 42;
|
||||
c_rbnode_t *node = NULL;
|
||||
test_t *freedata = NULL;
|
||||
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
node = c_rbtree_find(tree, (void *) &i);
|
||||
assert_non_null(node);
|
||||
|
||||
freedata = (test_t *) c_rbtree_node_data(node);
|
||||
free(freedata);
|
||||
rc = c_rbtree_node_delete(node);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_walk(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
int rc, i = 42;
|
||||
test_t *testdata;
|
||||
c_rbnode_t *node;
|
||||
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
testdata = (test_t *) c_malloc(sizeof(test_t));
|
||||
testdata->key = 42;
|
||||
|
||||
rc = c_rbtree_walk(tree, testdata, visitor);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
/* find the node with the key 42 */
|
||||
node = c_rbtree_find(tree, (void *) &i);
|
||||
assert_non_null(node);
|
||||
free(testdata);
|
||||
|
||||
testdata = (test_t *) c_rbtree_node_data(node);
|
||||
assert_int_equal(testdata->number, 42);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_walk_null(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
int rc, i = 42;
|
||||
test_t *testdata;
|
||||
c_rbnode_t *node;
|
||||
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
testdata = (test_t *) malloc(sizeof(test_t));
|
||||
testdata->key = 42;
|
||||
|
||||
rc = c_rbtree_walk(NULL, testdata, visitor);
|
||||
assert_int_equal(rc, -1);
|
||||
assert_int_equal(errno, EINVAL);
|
||||
|
||||
rc = c_rbtree_walk(tree, NULL, visitor);
|
||||
assert_int_equal(rc, -1);
|
||||
assert_int_equal(errno, EINVAL);
|
||||
|
||||
rc = c_rbtree_walk(tree, testdata, NULL);
|
||||
assert_int_equal(rc, -1);
|
||||
assert_int_equal(errno, EINVAL);
|
||||
|
||||
/* find the node with the key 42 */
|
||||
node = c_rbtree_find(tree, (void *) &i);
|
||||
assert_non_null(node);
|
||||
|
||||
free(testdata);
|
||||
}
|
||||
|
||||
static void check_c_rbtree_dup(void **state)
|
||||
{
|
||||
c_rbtree_t *tree = *state;
|
||||
c_rbtree_t *duptree = NULL;
|
||||
int rc = -1;
|
||||
|
||||
duptree = c_rbtree_dup(tree);
|
||||
assert_non_null(duptree);
|
||||
|
||||
rc = c_rbtree_check_sanity(duptree);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
c_rbtree_free(duptree);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void check_c_rbtree_x)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
rc = c_rbtree_check_sanity(tree);
|
||||
fail_unless(rc == 0, "c_rbtree_check_sanity failed with return code %d", rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
int torture_run_tests(void)
|
||||
{
|
||||
const UnitTest tests[] = {
|
||||
unit_test(check_c_rbtree_create_free),
|
||||
unit_test(check_c_rbtree_free_null),
|
||||
unit_test(check_c_rbtree_insert_delete),
|
||||
unit_test_setup_teardown(check_c_rbtree_insert_random, setup, teardown),
|
||||
unit_test_setup_teardown(check_c_rbtree_insert_duplicate, setup, teardown),
|
||||
unit_test_setup_teardown(check_c_rbtree_find, setup_complete_tree, teardown),
|
||||
unit_test_setup_teardown(check_c_rbtree_delete, setup_complete_tree, teardown),
|
||||
unit_test_setup_teardown(check_c_rbtree_walk, setup_complete_tree, teardown),
|
||||
unit_test_setup_teardown(check_c_rbtree_walk_null, setup_complete_tree, teardown),
|
||||
unit_test_setup_teardown(check_c_rbtree_dup, setup_complete_tree, teardown),
|
||||
};
|
||||
|
||||
return run_tests(tests);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ if(SPHINX_FOUND)
|
||||
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
|
||||
# HTML output directory
|
||||
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man1")
|
||||
set(SPHINX_PDF_DIR "${CMAKE_CURRENT_BINARY_DIR}/latex")
|
||||
set(SPHINX_QCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/qthelp")
|
||||
set(SPHINX_HTMLHELP_DIR "${CMAKE_CURRENT_BINARY_DIR}/htmlhelp")
|
||||
@@ -12,17 +11,17 @@ if(SPHINX_FOUND)
|
||||
# assets
|
||||
set(LATEX_LOGO "${CMAKE_CURRENT_SOURCE_DIR}/logo-blue.pdf")
|
||||
|
||||
install(DIRECTORY ${SPHINX_HTML_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR} OPTIONAL)
|
||||
install(DIRECTORY ${SPHINX_MAN_DIR} DESTINATION ${CMAKE_INSTALL_MANDIR} OPTIONAL)
|
||||
install(DIRECTORY ${SPHINX_PDF_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR} OPTIONAL)
|
||||
install(DIRECTORY ${SPHINX_QCH_DIR} DESTINATION ${CMAKE_INSTALL_DOCDIR} OPTIONAL)
|
||||
set(APPLICATION_DOC_DIR "${CMAKE_INSTALL_DOCDIR}/${PACKAGE}")
|
||||
install(DIRECTORY ${SPHINX_HTML_DIR} DESTINATION ${APPLICATION_DOC_DIR} OPTIONAL)
|
||||
install(DIRECTORY ${SPHINX_PDF_DIR} DESTINATION ${APPLICATION_DOC_DIR} OPTIONAL)
|
||||
install(DIRECTORY ${SPHINX_QCH_DIR} DESTINATION ${APPLICATION_DOC_DIR} OPTIONAL)
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in" conf.py @ONLY)
|
||||
|
||||
if(WITH_DOC)
|
||||
add_custom_target(doc ALL DEPENDS doc-html doc-man COMMENT "Building documentation...")
|
||||
add_custom_target(doc ALL DEPENDS doc-html COMMENT "Building documentation...")
|
||||
else(WITH_DOC)
|
||||
add_custom_target(doc DEPENDS doc-html doc-man COMMENT "Building documentation...")
|
||||
add_custom_target(doc DEPENDS doc-html COMMENT "Building documentation...")
|
||||
endif(WITH_DOC)
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ocdoc/_shared_assets")
|
||||
@@ -71,11 +70,6 @@ if(SPHINX_FOUND)
|
||||
-D html_theme=owncloud_com
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_HTML_DIR}/com )
|
||||
add_custom_target( doc-man ${SPHINX_EXECUTABLE}
|
||||
-q -c . -b man
|
||||
-d ${SPHINX_CACHE_DIR}/man
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_MAN_DIR} )
|
||||
|
||||
## Building CHM files requires HTML Help Workshop. Since it requires wine
|
||||
## with special dependencies, it's impossible to write a cmake check for it.
|
||||
@@ -90,4 +84,4 @@ if(SPHINX_FOUND)
|
||||
${SPHINX_HTMLHELP_DIR} )
|
||||
add_custom_target( doc-chm pushd ${SPHINX_HTMLHELP_DIR}; ${MSHTML_COMPILER} *.hhp; popd
|
||||
DEPENDS doc-chm-sphinx )
|
||||
endif(SPHINX_FOUND)
|
||||
endif(SPHINX_FOUND)
|
||||
174
doc/Makefile
Normal file
@@ -0,0 +1,174 @@
|
||||
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " pdf to make PDF files"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html: html-org
|
||||
|
||||
html-all: html-release html-org html-com
|
||||
|
||||
html-release:
|
||||
$(SPHINXBUILD) -b html -D html_theme='owncloud_release' $(ALLSPHINXOPTS) $(BUILDDIR)/html/release
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/release."
|
||||
|
||||
html-org:
|
||||
$(SPHINXBUILD) -b html -D html_theme='owncloud_org' $(ALLSPHINXOPTS) $(BUILDDIR)/html/org
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/org."
|
||||
|
||||
html-com:
|
||||
$(SPHINXBUILD) -b html -D html_theme='owncloud_com' $(ALLSPHINXOPTS) $(BUILDDIR)/html/com
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/com."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OwncloudDocumentation.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OwncloudDocumentation.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/OwncloudDocumentation"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OwncloudDocumentation"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
pdf:
|
||||
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) $(BUILDDIR)/pdf
|
||||
@echo
|
||||
@echo "build finished. the text files are in $(BUILDDIR)/pdf."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "build finished. the text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
@@ -14,6 +14,11 @@ Configuration File
|
||||
.. index:: config file
|
||||
.. include:: conffile.rst
|
||||
|
||||
Environment Variables
|
||||
---------------------
|
||||
.. index:: env vars
|
||||
.. include:: envvars.rst
|
||||
|
||||
ownCloud Command Line Client
|
||||
----------------------------
|
||||
.. index:: owncloudcmd
|
||||
|
||||
@@ -143,39 +143,159 @@ the remote file will be downloaded and saved as message.txt.
|
||||
|
||||
Conflict files are always created on the client and never on the server.
|
||||
|
||||
Checksum Algorithm Negotiation
|
||||
------------------------------
|
||||
|
||||
In ownCloud 10.0 we implemented a checksum feature which checks the file integrity on upload and download by computing a checksum after the file transfer finishes.
|
||||
The client queries the server capabilities after login to decide which checksum algorithm to use.
|
||||
Currently, SHA1 is hard-coded in the official server release and can't be changed by the end-user.
|
||||
Note that the server additionally also supports MD5 and Adler-32, but the desktop client will always use the checksum algorithm announced in the capabilities:
|
||||
|
||||
::
|
||||
|
||||
GET http://localhost:8000/ocs/v1.php/cloud/capabilities?format=json
|
||||
|
||||
::
|
||||
|
||||
json
|
||||
{
|
||||
"ocs":{
|
||||
"meta":{
|
||||
"status":"ok",
|
||||
"statuscode":100,
|
||||
"message":"OK",
|
||||
"totalitems":"",
|
||||
"itemsperpage":""
|
||||
},
|
||||
"data":{
|
||||
"version":{
|
||||
"major":10,
|
||||
"minor":0,
|
||||
"micro":0,
|
||||
"string":"10.0.0 beta",
|
||||
"edition":"Community"
|
||||
},
|
||||
"capabilities":{
|
||||
"core":{
|
||||
"pollinterval":60,
|
||||
"webdav-root":"remote.php/webdav"
|
||||
},
|
||||
"dav":{
|
||||
"chunking":"1.0"
|
||||
},
|
||||
"files_sharing":{
|
||||
"api_enabled":true,
|
||||
"public":{
|
||||
"enabled":true,
|
||||
"password":{
|
||||
"enforced":false
|
||||
},
|
||||
"expire_date":{
|
||||
"enabled":false
|
||||
},
|
||||
"send_mail":false,
|
||||
"upload":true
|
||||
},
|
||||
"user":{
|
||||
"send_mail":false
|
||||
},
|
||||
"resharing":true,
|
||||
"group_sharing":true,
|
||||
"federation":{
|
||||
"outgoing":true,
|
||||
"incoming":true
|
||||
}
|
||||
},
|
||||
"checksums":{
|
||||
"supportedTypes":[
|
||||
"SHA1"
|
||||
],
|
||||
"preferredUploadType":"SHA1"
|
||||
},
|
||||
"files":{
|
||||
"bigfilechunking":true,
|
||||
"blacklisted_files":[
|
||||
".htaccess"
|
||||
],
|
||||
"undelete":true,
|
||||
"versioning":true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Upload
|
||||
~~~~~~
|
||||
|
||||
A checksum is calculated with the previously negotiated algorithm by the client and sent along with the file in an HTTP Header.
|
||||
```OC-Checksum: [algorithm]:[checksum]```
|
||||
|
||||
.. image:: ./images/checksums/client-activity.png
|
||||
|
||||
During file upload, the server computes SHA1, MD5, and Adler-32 checksums and compares one of them to the checksum supplied by the client.
|
||||
|
||||
On mismatch, the server returns HTTP Status code 400 (Bad Request) thus signaling the client that the upload failed.
|
||||
The server then discards the upload, and the client blacklists the file:
|
||||
|
||||
.. image:: ./images/checksums/testing-checksums.png
|
||||
|
||||
::
|
||||
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
|
||||
<s:exception>Sabre\DAV\Exception\BadRequest</s:exception>
|
||||
<s:message>The computed checksum does not match the one received from the
|
||||
client.</s:message>
|
||||
</d:error>
|
||||
|
||||
The client retries the upload using exponential back-off.
|
||||
On success (matching checksum) the computed checksums are stored by the server in ``oc_filecache`` alongside the file.
|
||||
|
||||
Chunked Upload
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Mostly same as above.
|
||||
The checksum of the full file is sent with every chunk of the file.
|
||||
But the server only compares the checksum after receiving the checksum sent with the last chunk.
|
||||
|
||||
Download
|
||||
~~~~~~~~
|
||||
|
||||
The server sends the checksum in an HTTP header with the file. (same format as above).
|
||||
If no checksum is found in ``oc_filecache`` (freshly mounted external storage) it is computed and stored in ``oc_filecache`` on the first download.
|
||||
The checksum is then provided on all subsequent downloads but not on the first.
|
||||
|
||||
.. _ignored-files-label:
|
||||
|
||||
Ignored Files
|
||||
-------------
|
||||
|
||||
The ownCloud Client supports the ability to exclude or ignore certain files
|
||||
from the synchronization process. Some system wide file patterns that are used
|
||||
to exclude or ignore files are included with the client by default and the
|
||||
ownCloud Client provides the ability to add custom patterns.
|
||||
The ownCloud Client supports the ability to exclude or ignore certain files from the synchronization process.
|
||||
Some system wide file patterns that are used to exclude or ignore files are included with the client by default and the ownCloud Client provides the ability to add custom patterns.
|
||||
|
||||
By default, the ownCloud Client ignores the following files:
|
||||
|
||||
* Files matched by one of the patterns defined in the Ignored Files Editor
|
||||
* Files containing characters that do not work on certain file systems ``(`\, /, :, ?, *, ", >, <, |`)``.
|
||||
* Files starting with ``._sync_xxxxxxx.db`` and the old format ``.csync_journal.db``,
|
||||
as these files are reserved for journalling.
|
||||
* Files starting with ``._sync_xxxxxxx.db`` and the old format ``.csync_journal.db``, as these files are reserved for journalling.
|
||||
|
||||
If a pattern selected using a checkbox in the `ignoredFilesEditor-label` (or if
|
||||
a line in the exclude file starts with the character ``]`` directly followed by
|
||||
the file pattern), files matching the pattern are considered *fleeting meta
|
||||
data*. These files are ignored and *removed* by the client if found in the
|
||||
synchronized folder. This is suitable for meta files created by some
|
||||
applications that have no sustainable meaning.
|
||||
data*.
|
||||
|
||||
If a pattern ends with the forwardslash (``/``) character, only directories are
|
||||
matched. The pattern is only applied for directory components of filenames
|
||||
selected using the checkbox.
|
||||
These files are ignored and *removed* by the client if found in the
|
||||
synchronized folder.
|
||||
This is suitable for meta files created by some applications that have no sustainable meaning.
|
||||
|
||||
To match filenames against the exclude patterns, the unix standard C library
|
||||
function fnmatch is used. This process checks the filename against the
|
||||
specified pattern using standard shell wildcard pattern matching. For more
|
||||
information, please refer to `The opengroup website
|
||||
If a pattern ends with the forward slash (``/``) character, only directories are matched.
|
||||
The pattern is only applied for directory components of filenames selected using the checkbox.
|
||||
|
||||
To match filenames against the exclude patterns, the UNIX standard C library
|
||||
function ``fnmatch`` is used.
|
||||
This process checks the filename against the specified pattern using standard shell wildcard pattern matching.
|
||||
For more information, please refer to `The opengroup website
|
||||
<http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_13_01>`_.
|
||||
|
||||
The path that is checked is the relative path under the sync root directory.
|
||||
@@ -212,9 +332,9 @@ In the communication between client and server a couple of custom WebDAV propert
|
||||
were introduced. They are either needed for sync functionality or help have a positive
|
||||
effect on synchronization performance.
|
||||
|
||||
This chapter describes additional xml elements which the server returns in response
|
||||
This chapter describes additional XML elements which the server returns in response
|
||||
to a successful PROPFIND request on a file or directory. The elements are returned in
|
||||
the namespace oc.
|
||||
the namespace ``oc``.
|
||||
|
||||
Server Side Permissions
|
||||
------------------------
|
||||
@@ -223,27 +343,27 @@ The XML element ``<oc:permissions>`` represents the permission- and sharing stat
|
||||
item. It is a list of characters, and each of the chars has a meaning as outlined
|
||||
in the table below:
|
||||
|
||||
+----+----------------+-------------------------------------------+
|
||||
|Code| Resource | Description |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| S | File or Folder | is shared |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| R | File or Folder | can share (includes reshare) |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| M | File or Folder | is mounted (like on DropBox, Samba, etc.) |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| W | File | can write file |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| C | Folder |can create file in folder |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| K | Folder | can create folder (mkdir) |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| D | File or Folder |can delete file or folder |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| N | File or Folder | can rename file or folder |
|
||||
+----+----------------+-------------------------------------------+
|
||||
| V | File or Folder | can move file or folder |
|
||||
+----+----------------+-------------------------------------------+
|
||||
+------+----------------+-------------------------------------------+
|
||||
| Code | Resource | Description |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| S | File or Folder | is shared |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| R | File or Folder | can share (includes re-share) |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| M | File or Folder | is mounted (like on Dropbox, Samba, etc.) |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| W | File | can write file |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| C | Folder | can create file in folder |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| K | Folder | can create folder (mkdir) |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| D | File or Folder | can delete file or folder |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| N | File or Folder | can rename file or folder |
|
||||
+------+----------------+-------------------------------------------+
|
||||
| V | File or Folder | can move file or folder |
|
||||
+------+----------------+-------------------------------------------+
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
@@ -59,7 +59,7 @@ the auto-updater entirely. The following sections describe how to disable the
|
||||
auto-update mechanism for different operating systems.
|
||||
|
||||
Preventing Automatic Updates in Windows Environments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Users may disable automatic updates by adding this line to the [General]
|
||||
section of their ``owncloud.cfg`` files::
|
||||
|
||||
@@ -11,7 +11,7 @@ desktop client.
|
||||
.. note:: Build instructions are subject to change as development proceeds.
|
||||
Please check the version for which you want to build.
|
||||
|
||||
These instructions are updated to work with version 2.2 of the ownCloud Client.
|
||||
These instructions are updated to work with version |version| of the ownCloud Client.
|
||||
|
||||
Getting Source Code
|
||||
-------------------
|
||||
@@ -30,10 +30,10 @@ you the exact sources from which the binary packages are built. These are
|
||||
hosted on the `ownCloud repository from OBS`_. Go to the `Index of
|
||||
repositories`_ to see all the Linux client repos.
|
||||
|
||||
1. At the `bottom of the page for each distribution
|
||||
1. The source RPMs for CentOS, RHEL, Fedora, SLES, and openSUSE are at the `bottom of the page for each distribution
|
||||
<https://software.opensuse.org/download/package?project=isv:ownCloud:desktop&
|
||||
package=owncloud-client>`_ is a "Grab binary packages directly" section.
|
||||
These contain source RPMs for CentOS, RHEL, Fedora, SLES, and openSUSE.
|
||||
package=owncloud-client>`
|
||||
the sources for DEB and Ubuntu based distributions are at e.g. http://download.opensuse.org/repositories/isv:/ownCloud:/desktop/Ubuntu_16.04/
|
||||
|
||||
To get the .deb source packages add the source
|
||||
repo for your Debian or Ubuntu version, like this example for Debian 8
|
||||
@@ -99,18 +99,18 @@ To set up your build environment for development using HomeBrew_:
|
||||
|
||||
10. Install the Packages_ package creation tool.
|
||||
|
||||
11. In the build directory, run ``admin/osx/create_mac.sh <build_dir>
|
||||
<install_dir>``. If you have a developer signing certificate, you can specify
|
||||
its Common Name as a third parameter (use quotes) to have the package
|
||||
signed automatically.
|
||||
11. In the build directory, run ``admin/osx/create_mac.sh <build_dir> <install_dir>``.
|
||||
If you have a developer signing certificate, you can specify
|
||||
its Common Name as a third parameter (use quotes) to have the package
|
||||
signed automatically.
|
||||
|
||||
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||
.. note:: Contrary to earlier versions, ownCloud 1.7 and later are packaged
|
||||
as a ``pkg`` installer. Do not call "make package" at any time when
|
||||
compiling for OS X, as this will build a disk image, and will not
|
||||
work correctly.
|
||||
|
||||
Windows Development Build
|
||||
-----------------------
|
||||
-------------------------
|
||||
|
||||
If you want to test some changes and deploy them locally, you can build natively
|
||||
on Windows using MinGW. If you want to generate an installer for deployment, please
|
||||
@@ -210,7 +210,7 @@ In order to make setup simple, you can use the provided Dockerfile to build your
|
||||
-in ${unsigned_file} \
|
||||
-out ${installer_file}
|
||||
|
||||
for ``-in``, use the URL to the time stamping server provided by your CA along with the Authenticode certificate. Alternatively,
|
||||
For ``-in``, use the URL to the time stamping server provided by your CA along with the Authenticode certificate. Alternatively,
|
||||
you may use the official Microsoft ``signtool`` utility on Microsoft Windows.
|
||||
|
||||
If you're familiar with docker, you can use the version of ``osslsigncode`` that is part of the docker image.
|
||||
@@ -240,8 +240,8 @@ To build the most up-to-date version of the client:
|
||||
|
||||
3. Configure the client build::
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE="Debug" ..
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE="Debug" ..
|
||||
|
||||
.. note:: You must use absolute paths for the ``include`` and ``library``
|
||||
directories.
|
||||
|
||||
@@ -249,14 +249,10 @@ To build the most up-to-date version of the client:
|
||||
where ``target`` is a private location, i.e. in parallel to your build
|
||||
dir by specifying ``../install``.
|
||||
|
||||
..note:: qtkeychain must be compiled with the same prefix e.g CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/
|
||||
|
||||
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
|
||||
|
||||
.. note:: Example:: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -D_OPENSSL_LIBDIR=/usr/local/opt/openssl/lib/ -D_OPENSSL_INCLUDEDIR=/usr/local/opt/openssl/include/ -D_OPENSSL_VERSION=1.0.2a -DOPENSSL_INCLUDE_DIR=/usr/local/opt/openssl/include/ -DNO_SHIBBOLETH=1
|
||||
|
||||
qtkeychain must be compiled with the same prefix e.g CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ .
|
||||
|
||||
.. note:: qtkeychain must be compiled with the same prefix e.g ``CMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ .``
|
||||
|
||||
.. note:: Example:: ``cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/install/ -DNO_SHIBBOLETH=1``
|
||||
|
||||
4. Call ``make``.
|
||||
|
||||
The owncloud binary will appear in the ``bin`` directory.
|
||||
|
||||
292
doc/conf.py
Normal file
@@ -0,0 +1,292 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# ownCloud Documentation documentation build configuration file, created by
|
||||
# sphinx-quickstart on Mon Oct 22 23:16:40 2012.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.todo']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'ownCloud Client Manual'
|
||||
copyright = u'2013-2016, The ownCloud developers'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '2.4.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '2.4.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build','scripts/*']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
2
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/themes']
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#html_theme = 'bootstrap'
|
||||
html_theme = 'default'
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
html_short_title = "Client Manual"
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/ocdoc/_shared_assets/static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
html_show_sphinx = False
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'ownCloudClientManual'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'ownCloudClientManual.tex', u'ownCloud Client Manual',
|
||||
u'The ownCloud developers', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
latex_logo = 'logo-blue.pdf'
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('owncloud.1', 'owncloud', u'File synchronisation desktop utility.',
|
||||
[u'The ownCloud developers'], 1),
|
||||
('owncloudcmd.1', 'owncloudcmd', u'Command line ownCloud client tool.',
|
||||
[u'The ownCloud developers'], 1),
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
man_show_urls = True
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'ownCloudClientManual', u'ownCloud Client Manual',
|
||||
u'The ownCloud developers', 'ownCloud', 'The ownCloud Client Manual.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
|
||||
# -- Options for Epub output ---------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'ownCloud Client Manual'
|
||||
epub_author = u'The ownCloud developers'
|
||||
epub_publisher = u'The ownCloud developers'
|
||||
epub_copyright = u'2013-2016, The ownCloud developers'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
#epub_exclude_files = []
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
# Include todos?
|
||||
todo_include_todos = True
|
||||
|
||||
rst_epilog = '.. |version| replace:: %s' % version
|
||||
@@ -16,20 +16,50 @@ format. You can overwrite changes using the ownCloud configuration dialog.
|
||||
.. note:: Use caution when making changes to the ownCloud Client configuration
|
||||
file. Incorrect settings can produce unintended results.
|
||||
|
||||
You can change the following configuration settings in the ``[ownCloud]`` section:
|
||||
Some interesting values that can be set on the configuration file are:
|
||||
|
||||
- ``remotePollInterval`` (default: ``30000``) -- Specifies the poll time for the remote repository in milliseconds.
|
||||
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``[ownCloud]`` section |
|
||||
+=================================+===============+========================================================================================================+
|
||||
| Variable | Default | Meaning |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``remotePollInterval`` | ``30000`` | Specifies the poll time for the remote repository in milliseconds. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``forceSyncInterval`` | ``7200000`` | The duration of no activity after which a synchronization run shall be triggered automatically. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``notificationRefreshInterval`` | ``300000`` | Specifies the default interval of checking for new server notifications in milliseconds. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
- ``forceSyncInterval`` (default: ``7200000``) -- The duration of no activity after which a synchronization run shall be triggered automatically.
|
||||
|
||||
- ``notificationRefreshInterval`` (default: ``300000``) -- Specifies the default interval of checking for new server notifications in milliseconds.
|
||||
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``[General]`` section |
|
||||
+=================================+===============+========================================================================================================+
|
||||
| Variable | Default | Meaning |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``chunkSize`` | ``5242880`` | Specifies the chunk size of uploaded files in bytes. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``promptDeleteAllFiles`` | ``true`` | If a UI prompt should ask for confirmation if it was detected that all files and folders were deleted. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``maxLogLines`` | ``20000`` | Specifies the maximum number of log lines displayed in the log window. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``timeout`` | ``300`` | The timeout for network connections in seconds. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
You can change the following configuration settings in the ``[General]`` section:
|
||||
|
||||
- ``chunkSize`` (default: ``5242880``) -- Specifies the chunk size of uploaded files in bytes.
|
||||
|
||||
- ``promptDeleteAllFiles`` (default: ``true``) -- If a UI prompt should ask for confirmation if it was detected that all files and folders were deleted.
|
||||
|
||||
- ``maxLogLines`` (default: ``20000``) -- Specifies the maximum number of log lines displayed in the log window.
|
||||
|
||||
- ``timeout`` (default: ``300``) -- The timeout for network connections in seconds.
|
||||
+----------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| ``[Proxy]`` section |
|
||||
+=================================+===============+========================================================================================================+
|
||||
| Variable | Default | Meaning |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``host`` | ``127.0.0.1`` | The address of the proxy server. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``port`` | ``8080`` | The port were the proxy is listening. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
| ``type`` | ``2`` | ``0`` for System Proxy. |
|
||||
+ + +--------------------------------------------------------------------------------------------------------+
|
||||
| | | ``1`` for SOCKS5 Proxy. |
|
||||
+ + +--------------------------------------------------------------------------------------------------------+
|
||||
| | | ``2`` for No Proxy. |
|
||||
+ + +--------------------------------------------------------------------------------------------------------+
|
||||
| | | ``3`` for HTTP(S) Proxy. |
|
||||
+---------------------------------+---------------+--------------------------------------------------------------------------------------------------------+
|
||||
|
||||
@@ -34,7 +34,7 @@ The discovery phase collects file and directory metadata from the local and remo
|
||||
Afterwards, we have two trees that tell us what happened relative to the journal. But there may still be conflicts if something happened to an entity both locally and on the remote.
|
||||
|
||||
- Input: file system, server data, journal
|
||||
- Output: two c_rbtree_t*, representing the local and remote trees
|
||||
- Output: two FileMap (std::map<QByteArray, std::unique_ptr<csync_file_stat_t>>), representing the local and remote trees
|
||||
|
||||
- Note on remote discovery: Since a change to a file on the server causes the etags of all parent folders to change, folders with an unchanged etag can be read from the journal directly and don't need to be walked into.
|
||||
|
||||
@@ -52,12 +52,12 @@ The reconcile phase compares and adjusts the local and remote trees (in both dir
|
||||
|
||||
Afterwards, there are still two trees, but conflicts are marked in them.
|
||||
|
||||
- Input: c_rbtree_t* for the local and remote trees, journal (for some rename-related queries)
|
||||
- Output: changes c_rbtree_t* in-place
|
||||
- Input: FileMap for the local and remote trees, journal (for some rename-related queries)
|
||||
- Output: changes FileMap in-place
|
||||
|
||||
- Details
|
||||
- csync_reconcile() runs csync_reconcile_updates() for the local and remote trees, one after the other.
|
||||
- csync_reconcile_updates() uses c_rbtree_walk() to iterate through the entries, calling _csync_merge_algorithm_visitor() for each.
|
||||
- csync_reconcile_updates() iterates through the entries, calling _csync_merge_algorithm_visitor() for each.
|
||||
- _csync_merge_algorithm_visitor() checks whether the other tree also has an entry for that node and merges the actions, detecting conflicts. This is the main function of this pass.
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ The post-reconcile phase merges the two trees into one set of SyncFileItems.
|
||||
|
||||
Afterwards, there is a list of items that can tell the propagator what needs to be done.
|
||||
|
||||
- Input: c_rbtree_t* for the local and remote trees
|
||||
- Input: FileMap for the local and remote trees
|
||||
- Output: QMap<QString, SyncFileItemPtr>
|
||||
|
||||
- Note that some "propagations", specifically cheap metadata-only updates, are already done at this stage.
|
||||
|
||||
11
doc/envvars.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
The behavior of the client can also be controlled using environment variables. The value of the environment variables overrides the values in the configuration file.
|
||||
|
||||
The environment variables are:
|
||||
|
||||
- `OWNCLOUD_CHUNK_SIZE` (default: 5242880; 5 MiB) – Specifies the chunk size of uploaded files in bytes. Increasing this value may help with synchronization problems in certain configurations.
|
||||
- `OWNCLOUD_TIMEOUT` (default: 300 s) – The timeout for network connections in seconds.
|
||||
- `OWNCLOUD_CRITICAL_FREE_SPACE_BYTES` (default: 50\*1000\*1000 bytes) - The minimum disk space needed for operation. A fatal error is raised if less free space is available.
|
||||
- `OWNCLOUD_FREE_SPACE_BYTES` (default: 250\*1000\*1000 bytes) - Downloads that would reduce the free space below this value are skipped. More information available under the "Low Disk Space" section.
|
||||
- `OWNCLOUD_MAX_PARALLEL` (default: 6) - Maximum number of parallel jobs.
|
||||
- `OWNCLOUD_BLACKLIST_TIME_MIN` (default: 25 s) - Minimum timeout for blacklisted files.
|
||||
- `OWNCLOUD_BLACKLIST_TIME_MAX` (default: 24\*60\*60 s; one day) - Maximum timeout for blacklisted files.
|
||||
52
doc/faq.rst
@@ -1,7 +1,7 @@
|
||||
FAQ
|
||||
===
|
||||
|
||||
Some files are continuously uploaded to the server, even when they are not modified.
|
||||
Some Files Are Continuously Uploaded to the Server, Even When They Are Not Modified.
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
It is possible that another program is changing the modification date of the file.
|
||||
@@ -11,10 +11,48 @@ continually changes all files, unless you remove
|
||||
from the windows registry.
|
||||
See http://petersteier.wordpress.com/2011/10/22/windows-indexer-changes-modification-dates-of-eml-files/ for more information.
|
||||
|
||||
Syncing breaks when attempting to sync deeper than 50 sub-directories, but the sync client does not report an error (RC=0)
|
||||
--------------------------------------------------------------------------------------------------------------------------
|
||||
Syncing Stops When Attempting To Sync Deeper Than 100 Sub-directories.
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The sync client has been intentionally limited to sync no deeper than
|
||||
fifty sub-directories, to help prevent memory problems.
|
||||
Unfortunately, it, *currently*, does not report an error when this occurs.
|
||||
However, a UI notification is planned for a future release of ownCloud.
|
||||
The sync client has been intentionally limited to sync no deeper than 100
|
||||
sub-directories. The hard limit exists to guard against bugs with cycles
|
||||
like symbolic link loops.
|
||||
When a deeply nested directory is excluded from synchronization it will be
|
||||
listed with other ignored files and directories in the "Not synced" tab of
|
||||
the "Activity" pane.
|
||||
|
||||
I Want To Move My Local Sync Folder
|
||||
-----------------------------------
|
||||
|
||||
The ownCloud desktop client does not provide a way to change the local sync directory.
|
||||
However, it can be done, though it is a bit unorthodox.
|
||||
Specifically, you have to:
|
||||
|
||||
1. Remove the existing connection which syncs to the wrong directory
|
||||
2. Add a new connection which syncs to the desired directory
|
||||
|
||||
.. figure:: images/setup/ownCloud-remove_existing_connection.png
|
||||
:alt: Remove an existing connection
|
||||
|
||||
To do so, in the client UI, which you can see above, click the "**Account**" drop-down menu and then click "Remove".
|
||||
This will display a "**Confirm Account Removal**" dialog window.
|
||||
|
||||
.. figure:: images/setup/ownCloud-remove_existing_connection_confirmation_dialog.png
|
||||
:alt: Remove existing connection confirmation dialog
|
||||
|
||||
If you're sure, click "**Remove connection**".
|
||||
|
||||
Then, click the Account drop-down menu again, and this time click "**Add new**".
|
||||
|
||||
.. figure:: images/setup/ownCloud-replacement_connection_wizard.png
|
||||
:alt: Replacement connection wizard
|
||||
|
||||
This opens the ownCloud Connection Wizard, which you can see above, *but* with an extra option.
|
||||
This option provides the ability to either: keep the existing data (synced by the previous connection) or to start a clean sync (erasing the existing data).
|
||||
|
||||
.. important::
|
||||
|
||||
Be careful before choosing the "Start a clean sync" option. The old sync folder *may* contain a considerable amount of data, ranging into the gigabytes or terabytes. If it does, after the client creates the new connection, it will have to download **all** of that information again. Instead, first move or copy the old local sync folder, containing a copy of the existing files, to the new location. Then, when creating the new connection choose "*keep existing data*" instead. The ownCloud client will check the files in the newly-added sync folder and find that they match what is on the server and not need to download anything.
|
||||
|
||||
Make your choice and click "**Connect...**".
|
||||
This will then step you through the Connection Wizard, just as you did when you setup the previous sync connection, but giving you the opportunity to choose a new sync directory.
|
||||
|
||||
BIN
doc/images/checksums/client-activity.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
doc/images/checksums/testing-checksums.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
doc/images/setup/ownCloud-remove_existing_connection.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 19 KiB |
BIN
doc/images/setup/ownCloud-replacement_connection_wizard.png
Executable file
|
After Width: | Height: | Size: 49 KiB |
@@ -3,8 +3,7 @@ Installing the Desktop Synchronization Client
|
||||
=============================================
|
||||
|
||||
You can download the latest version of the ownCloud Desktop Synchronization
|
||||
Client from the `ownCloud download page
|
||||
<https://owncloud.org/install/#desktop>`_.
|
||||
Client from the `ownCloud download page`_.
|
||||
There are clients for Linux, Mac OS X, and Microsoft Windows.
|
||||
|
||||
Installation on Mac OS X and Windows is the same as for any software
|
||||
@@ -59,3 +58,7 @@ synchronizing your files.
|
||||
Web GUI, and one to open your local ownCloud folder
|
||||
|
||||
Click the Finish button, and you're all done.
|
||||
|
||||
.. Links
|
||||
|
||||
.. _ownCloud download page: https://owncloud.com/download/#desktop-clients
|
||||
|
||||
@@ -19,7 +19,7 @@ recommended to keep your client updated.
|
||||
Improvements and New Features
|
||||
-----------------------------
|
||||
|
||||
The 2.2 release of the ownCloud desktop sync client has many new features and
|
||||
The |version| release of the ownCloud desktop sync client has many new features and
|
||||
improvements. (See the `complete changelog
|
||||
<https://owncloud.org/changelog/desktop/>`_.)
|
||||
|
||||
@@ -29,5 +29,5 @@ improvements. (See the `complete changelog
|
||||
* Improved user notifications about ignored files and conflicts
|
||||
* Add warnings for old server versions
|
||||
* Update of QtKeyChain to support Windows credential store
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distros
|
||||
|
||||
* Packaging of dolphin overlay icon module for bleeding edge distributions
|
||||
|
||||
|
||||
@@ -87,8 +87,7 @@ have the following features:
|
||||
**Log Out**, and **Remove**.
|
||||
* Used and available space on the server.
|
||||
* Current synchronization status.
|
||||
* **Add Folder Sync Connection** button, which is active only when you have
|
||||
removed synchronization on an account (see **Remove Sync** below).
|
||||
* **Add Folder Sync Connection** button.
|
||||
|
||||
The little button with three dots (the overflow menu) that sits to the right of
|
||||
the sync status bar offers four additional options:
|
||||
@@ -190,7 +189,9 @@ The Activity window contains the log of your recent activities, organized over
|
||||
three tabs: **Server Activities**, which includes new shares and files
|
||||
downloaded and deleted, **Sync Protocol**, which displays local activities such
|
||||
as which local folders your files went into, and **Not Synced** shows errors
|
||||
such as files not synced.
|
||||
such as files not synced. Double clicking an entry pointing to an existing
|
||||
file in **Server Activities** or **Sync Protocol** will open the folder containing
|
||||
the file and highlight it.
|
||||
|
||||
.. figure:: images/client-8.png
|
||||
:alt: Activity windows logs all server and client activities.
|
||||
@@ -236,7 +237,7 @@ also to limit download and upload bandwidth.
|
||||
|
||||
.. figure:: images/settings_network.png
|
||||
|
||||
.. _ignoredFilesEditor-label:
|
||||
.. _usingIgnoredFilesEditor-label:
|
||||
|
||||
Using the Ignored Files Editor
|
||||
------------------------------
|
||||
|
||||
@@ -25,4 +25,6 @@ The other options are:
|
||||
Clears (flushes) the log file after each write action.
|
||||
|
||||
``--confdir`` `<dirname>`
|
||||
Uses the specified configuration directory.
|
||||
Uses the specified configuration directory.
|
||||
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ Other command line switches supported by ``owncloudcmd`` include the following:
|
||||
Exclude list file
|
||||
|
||||
``--unsyncedfolders [file]``
|
||||
File containing the list of unsynced remote folders (selective sync)
|
||||
File containing the list of un-synced remote folders (selective sync)
|
||||
|
||||
``--max-sync-retries [n]``
|
||||
Retries maximum n times (defaults to 3)
|
||||
@@ -60,10 +60,9 @@ Other command line switches supported by ``owncloudcmd`` include the following:
|
||||
Credential Handling
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``owncloudcmd`` uses the credentials of the GUI synchronization client.
|
||||
If no client is configured, or if you choose to use a different user to synchronize,
|
||||
you can specify the user
|
||||
password setting with the usual URL pattern. For example::
|
||||
``owncloudcmd`` requires the user to specify the username and password using the standard URL pattern, e.g.,
|
||||
|
||||
::
|
||||
|
||||
$ owncloudcmd /home/user/my_sync_folder https://carla:secret@server/owncloud/remote.php/webdav/
|
||||
|
||||
@@ -77,3 +76,11 @@ machine using IP address ``192.168.178.1``, the command line would be::
|
||||
|
||||
``owncloudcmd`` will prompt for the user name and password, unless they have
|
||||
been specified on the command line or ``-n`` has been passed.
|
||||
|
||||
Exclude List
|
||||
~~~~~~~~~~~~
|
||||
|
||||
``owncloudcmd`` requires access to an exclude list file. It must either be
|
||||
installed along with ``owncloudcmd`` and thus be available in a system location,
|
||||
be placed next to the binary as ``sync-exclude.lst`` or be explicitly specified
|
||||
with the ``--exclude`` switch.
|
||||
|
||||
@@ -27,7 +27,7 @@ Identifying Basic Functionality Problems
|
||||
misconfiguration of the WebDAV API.
|
||||
|
||||
The ownCloud Client uses the built-in WebDAV access of the server content.
|
||||
Verify that you can log on to ownClouds WebDAV server. To verify connectivity
|
||||
Verify that you can log on to ownCloud's WebDAV server. To verify connectivity
|
||||
with the ownCloud WebDAV server:
|
||||
|
||||
- Open a browser window and enter the address to the ownCloud WebDAV server.
|
||||
@@ -55,8 +55,8 @@ Identifying Basic Functionality Problems
|
||||
---------------------
|
||||
|
||||
If you see this error message stop your client, delete the
|
||||
``.csync_journal.db`` file, and then restart your client.
|
||||
There is a ``.csync_journal.db`` file inside the folder of every account
|
||||
``._sync_xxxxxxx.db`` file, and then restart your client.
|
||||
There is a hidden ``._sync_xxxxxxx.db`` file inside the folder of every account
|
||||
configured on your client.
|
||||
|
||||
.. NOTE::
|
||||
@@ -78,17 +78,17 @@ Other issues can affect synchronization of your ownCloud files:
|
||||
|
||||
- Synchronizing the same directory with ownCloud and other synchronization
|
||||
software such as Unison, rsync, Microsoft Windows Offline Folders, or other
|
||||
cloud services such as DropBox or Microsoft SkyDrive is not supported and
|
||||
cloud services such as Dropbox or Microsoft SkyDrive is not supported and
|
||||
should not be attempted. In the worst case, it is possible that synchronizing
|
||||
folders or files using ownCloud and other synchronization software or
|
||||
services can result in data loss.
|
||||
|
||||
- If you find that only specific files are not synrchronized, the
|
||||
- If you find that only specific files are not synchronized, the
|
||||
synchronization protocol might be having an effect. Some files are
|
||||
automatically ignored because they are system files, other files might be
|
||||
ignored because their filename contains characters that are not supported on
|
||||
certain file systems. For more information about ignored files, see
|
||||
:ref:`_ignored-files-label`.
|
||||
:ref:`ignored-files-label`.
|
||||
|
||||
- If you are operating your own server, and use the local storage backend (the
|
||||
default), make sure that ownCloud has exclusive access to the directory.
|
||||
@@ -134,7 +134,7 @@ To obtain the client log file:
|
||||
|
||||
5. Name the log file and click the 'Save' button.
|
||||
|
||||
The log file is saved in the location specifed.
|
||||
The log file is saved in the location specified.
|
||||
|
||||
Alternatively, you can launch the ownCloud Log Output window using the
|
||||
``--logwindow`` command. After issuing this command, the Log Output window
|
||||
@@ -197,7 +197,7 @@ directly from the file system in the ownCloud server data directory.
|
||||
Webserver Log Files
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It can be helpful to view your webservers error log file to isolate any
|
||||
It can be helpful to view your webserver's error log file to isolate any
|
||||
ownCloud-related problems. For Apache on Linux, the error logs are typically
|
||||
located in the ``/var/log/apache2`` directory. Some helpful files include the
|
||||
following:
|
||||
|
||||
@@ -61,7 +61,7 @@ Where:
|
||||
desired.
|
||||
* ``Storage Usage``: Provides further details on the storage utilization on the
|
||||
ownCloud server.
|
||||
* ``Edit Ignored Files``: Provides a list of files which will be ignored, i.e.
|
||||
* ``Edit Ignored Files``: Provides a list of files which will be ignored, i.e.,
|
||||
will not sync between the client and server. The ignored files editor allows
|
||||
adding patterns for files or directories that should be excluded from the
|
||||
sync process. Besides normal characters, wild cards may be used, an asterisk
|
||||
@@ -80,11 +80,6 @@ Adding a Folder Sync Connection
|
||||
Adding a new sync is initiated by clicking ``Add Folder Sync Connection`` in
|
||||
the ``Account`` settings.
|
||||
|
||||
..note:: To add a folder, you must not already sync a folder that contains this
|
||||
folder. By default, the wizard sets up the root folder of the ownCloud
|
||||
server to sync all of your ownCloud account. In consequence, you will
|
||||
first need to remove this folder prior to specifying new syncs.
|
||||
|
||||
.. image:: images/folderwizard_local.png
|
||||
:scale: 50 %
|
||||
|
||||
@@ -124,7 +119,7 @@ The tab provides several useful options:
|
||||
:scale: 50 %
|
||||
|
||||
* ``Launch on System Startup``: This option is automatically activated
|
||||
once a user has conimaged his account. Unchecking the box will cause
|
||||
once a user has conimaged his account. Un-checking the box will cause
|
||||
ownCloud client to not launch on startup for a particular user.
|
||||
* ``Show Desktop Nofications``: When checked, bubble notifications when
|
||||
a set of sync operations has been performed are provided.
|
||||
|
||||
14
man/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
if(SPHINX_FOUND)
|
||||
|
||||
# Sphinx cache with pickled ReST documents
|
||||
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
|
||||
|
||||
# HTML output directory
|
||||
set(SPHINX_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/man1")
|
||||
install(DIRECTORY ${SPHINX_MAN_DIR} DESTINATION ${CMAKE_INSTALL_MANDIR} OPTIONAL)
|
||||
add_custom_target( doc-man ${SPHINX_EXECUTABLE}
|
||||
-c ${CMAKE_SOURCE_DIR}/doc -b man
|
||||
-d ${SPHINX_CACHE_DIR}/man
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SPHINX_MAN_DIR} )
|
||||
endif(SPHINX_FOUND)
|
||||
1
man/index.rst
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
:orphan:
|
||||
|
||||
owncloud(1)
|
||||
-----------
|
||||
————
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
@@ -16,11 +16,11 @@ Normally, you start the client by clicking on the desktop icon or by starting it
|
||||
|
||||
Options
|
||||
=======
|
||||
.. include:: options.rst
|
||||
.. include:: ../doc/options.rst
|
||||
|
||||
Config File
|
||||
===========
|
||||
.. include:: conffile.rst
|
||||
.. include:: ../doc/conffile.rst
|
||||
|
||||
BUGS
|
||||
====
|
||||
@@ -31,4 +31,3 @@ Please report bugs at https://github.com/owncloud/client/issues.
|
||||
SEE ALSO
|
||||
========
|
||||
:manpage:`owncloudcmd(1)`
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
:orphan:
|
||||
|
||||
owncloudcmd(1)
|
||||
--------------
|
||||
—————
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
@@ -29,40 +29,40 @@ the server URL.
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
``--user``, ``-u`` ``[user]``
|
||||
``—user``, ``-u`` ``[user]``
|
||||
Use ``user`` as the login name.
|
||||
|
||||
``--password``, ``-p`` ``[password]``
|
||||
``—password``, ``-p`` ``[password]``
|
||||
Use ``password`` as the password.
|
||||
|
||||
``-n``
|
||||
Use ``netrc (5)`` for login.
|
||||
|
||||
``--non-interactive``
|
||||
``—non-interactive``
|
||||
Do not prompt for questions.
|
||||
|
||||
``--silent``, ``--s``
|
||||
``—silent``, ``—s``
|
||||
Inhibits verbose log output.
|
||||
|
||||
``--trust``
|
||||
``—trust``
|
||||
Trust any SSL certificate, including invalid ones.
|
||||
|
||||
``--httpproxy http://[user@pass:]<server>:<port>``
|
||||
``—httpproxy http://[user@pass:]<server>:<port>``
|
||||
Uses ``server`` as HTTP proxy.
|
||||
|
||||
``--nonshib``
|
||||
``—nonshib``
|
||||
Uses Non Shibboleth WebDAV Authentication
|
||||
|
||||
``--davpath [path]``
|
||||
``—davpath [path]``
|
||||
Overrides the WebDAV Path with ``path``
|
||||
|
||||
``--exclude [file]``
|
||||
``—exclude [file]``
|
||||
Exclude list file
|
||||
|
||||
``--unsyncedfolders [file]``
|
||||
``—unsyncedfolders [file]``
|
||||
File containing the list of unsynced folders (selective sync)
|
||||
|
||||
``--max-sync-retries [n]``
|
||||
``—max-sync-retries [n]``
|
||||
Retries maximum n times (defaults to 3)
|
||||
|
||||
``-h``
|
||||
@@ -74,7 +74,7 @@ To synchronize the ownCloud directory ``Music`` to the local directory ``media/m
|
||||
through a proxy listening on port ``8080`` on the gateway machine ``192.168.178.1``,
|
||||
the command line would be::
|
||||
|
||||
$ owncloudcmd --httpproxy http://192.168.178.1:8080 \
|
||||
$ owncloudcmd —httpproxy http://192.168.178.1:8080 \
|
||||
$HOME/media/music \
|
||||
https://server/owncloud/remote.php/webdav/Music
|
||||
|
||||
@@ -83,7 +83,7 @@ been specified on the command line or ``-n`` (see `netrc(5)`) has been passed.
|
||||
|
||||
Using the legacy scheme, it would be::
|
||||
|
||||
$ owncloudcmd --httpproxy http://192.168.178.1:8080 \
|
||||
$ owncloudcmd —httpproxy http://192.168.178.1:8080 \
|
||||
$HOME/media/music \
|
||||
ownclouds://server/owncloud/remote.php/webdav/Music
|
||||
|
||||
@@ -94,5 +94,4 @@ Please report bugs at https://github.com/owncloud/client/issues.
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
:manpage:`owncloud(1)`
|
||||
|
||||
:manpage:`owncloud(1)`
|
||||
@@ -8,398 +8,6 @@ GenericName=Folder Sync
|
||||
Icon=@APPLICATION_EXECUTABLE@
|
||||
Keywords=@APPLICATION_NAME@;syncing;file;sharing;
|
||||
X-GNOME-Autostart-Delay=3
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
# Translations
|
||||
|
||||
|
||||
@@ -763,6 +371,10 @@ Comment[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
|
||||
GenericName[ar]=مزامنة المجلد
|
||||
Name[ar]=@APPLICATION_NAME@ زبون مزامنة مكتبي
|
||||
Icon[ar]=@APPLICATION_EXECUTABLE@
|
||||
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
|
||||
GenericName[bg_BG]=Синхронизиране на папката
|
||||
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
|
||||
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
GenericName[ca]=Sincronització de carpetes
|
||||
Name[ca]=Client de sincronització d'escriptori @APPLICATION_NAME@
|
||||
@@ -795,17 +407,21 @@ Comment[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
GenericName[de_DE]=Ordner-Synchronisation
|
||||
Name[de_DE]=@APPLICATION_NAME@ Desktop-Synchronisationsclient
|
||||
Icon[de_DE]=@APPLICATION_EXECUTABLE@
|
||||
Comment[bg_BG]=@APPLICATION_NAME@ клиент за десктоп синхронизация
|
||||
GenericName[bg_BG]=Синхронизиране на папката
|
||||
Name[bg_BG]=@APPLICATION_NAME@ клиент десктоп синхронизация
|
||||
Icon[bg_BG]=@APPLICATION_EXECUTABLE@
|
||||
Comment[eu]=@APPLICATION_NAME@ mahaigaineko sinkronizazio bezeroa
|
||||
GenericName[eu]=Karpetaren sinkronizazioa
|
||||
Name[eu]=@APPLICATION_NAME@ mahaigaineko sinkronizazio bezeroa
|
||||
Icon[eu]=@APPLICATION_EXECUTABLE@
|
||||
GenericName[fa]=همسان سازی پوشهها
|
||||
Name[fa]=@APPLICATION_EXECUTABLE@ نسخهی همسان سازی مشتری
|
||||
Icon[fa]=@APPLICATION_EXECUTABLE@
|
||||
Comment[fr]=@APPLICATION_NAME@ synchronisation du client
|
||||
GenericName[fr]=Dossier de Synchronisation
|
||||
Name[fr]=@APPLICATION_NAME@ synchronisation du client
|
||||
Comment[fr]=Synchronisez vos dossiers avec un serveur @APPLICATION_NAME@
|
||||
GenericName[fr]=Synchronisation de dossier
|
||||
Name[fr]=Client de synchronisation @APPLICATION_NAME@
|
||||
Icon[fr]=@APPLICATION_EXECUTABLE@
|
||||
Comment[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
|
||||
GenericName[gl]=Sincronizar Cartafol
|
||||
Name[gl]=@APPLICATION_NAME@ cliente de sincronización para escritorio
|
||||
Icon[gl]=@APPLICATION_EXECUTABLE@
|
||||
Comment[he]=@APPLICATION_NAME@ לקוח סנכון שולחן עבודה
|
||||
GenericName[he]=סנכון תיקייה
|
||||
Name[he]=@APPLICATION_NAME@ לקוח סנכרון שולחן עבודה
|
||||
@@ -829,10 +445,19 @@ Icon[it]=@APPLICATION_EXECUTABLE@
|
||||
Comment[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
GenericName[ko]=폴더 동기화
|
||||
Name[ko]=@APPLICATION_NAME@ 데스크톱 동기화 클라이언트
|
||||
Icon[ko]=@APPLICATION_EXECUTABLE@
|
||||
Comment[lo]=@APPLICATION_NAME@ ການປະສານຂໍ້ມູນຄອມພິວເຕີລູກຂ່າຍ
|
||||
GenericName[lo]=ໂຟນເດີຊິງ
|
||||
Name[lo]=@APPLICATION_NAME@ ຊິງຄອມພິວເຕີລູກຂ່າຍ
|
||||
Icon[lo]=@APPLICATION_EXECUTABLE@
|
||||
Comment[hu_HU]=@APPLICATION_NAME@ asztali szinkronizációs kliens
|
||||
GenericName[hu_HU]=Könyvtár szinkronizálás
|
||||
Name[hu_HU]=@APPLICATION_NAME@ asztali szinkr. kliens
|
||||
Icon[hu_HU]=@APPLICATION_EXECUTABLE@
|
||||
Comment[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
|
||||
GenericName[af_ZA]=Vouersinchronisering
|
||||
Name[af_ZA]=@APPLICATION_NAME@ werkskermsinchroniseerkliënt
|
||||
Icon[af_ZA]=@APPLICATION_EXECUTABLE@
|
||||
Comment[nl]=@APPLICATION_NAME@ desktop synchronisatie client
|
||||
GenericName[nl]=Mappen sync
|
||||
Name[nl]=@APPLICATION_NAME@ desktop sync client
|
||||
@@ -889,7 +514,15 @@ Comment[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
GenericName[zh_CN]=文件夹同步
|
||||
Name[zh_CN]=@APPLICATION_NAME@ 桌面同步客户端
|
||||
Icon[zh_CN]=@APPLICATION_EXECUTABLE@
|
||||
Comment[zh_HK]=桌面版同步客户端
|
||||
Comment[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
|
||||
GenericName[zh_TW]=資料夾同步
|
||||
Name[zh_TW]=@APPLICATION_NAME@ 桌面同步客戶端
|
||||
Icon[zh_TW]=@APPLICATION_EXECUTABLE@
|
||||
Comment[es_AR]=Cliente de sincronización para escritorio @APPLICATION_NAME@
|
||||
GenericName[es_AR]=Sincronización de directorio
|
||||
Name[es_AR]=Cliente de sincronización para escritorio @APPLICATION_NAME@
|
||||
Icon[es_AR]=@APPLICATION_EXECUTABLE@
|
||||
Comment[lt_LT]=@APPLICATION_NAME@ darbalaukio sinchronizavimo programa
|
||||
GenericName[lt_LT]=Katalogo sinchnorizacija
|
||||
Name[lt_LT]=@APPLICATION_NAME@ darbalaukio programa
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
if (APPLE)
|
||||
add_subdirectory(MacOSX)
|
||||
endif()
|
||||
add_subdirectory(icons)
|
||||
if(BUILD_SHELL_INTEGRATION_ICONS)
|
||||
add_subdirectory(icons)
|
||||
endif()
|
||||
|
||||
if( UNIX AND NOT APPLE )
|
||||
add_subdirectory(nautilus)
|
||||
if(BUILD_SHELL_INTEGRATION_NAUTILUS)
|
||||
add_subdirectory(nautilus)
|
||||
endif()
|
||||
|
||||
find_package(ECM 1.2.0 NO_MODULE QUIET)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
find_package(KF5 "5.16" COMPONENTS KIO)
|
||||
if(KF5_FOUND)
|
||||
add_subdirectory(dolphin)
|
||||
else()
|
||||
message("Dolphin plugin disabled: KDE Frameworks 5.16 not found")
|
||||
if(BUILD_SHELL_INTEGRATION_DOLPHIN)
|
||||
find_package(ECM 1.2.0 NO_MODULE QUIET)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
find_package(KF5 "5.16" COMPONENTS KIO)
|
||||
if(KF5_FOUND)
|
||||
add_subdirectory(dolphin)
|
||||
else()
|
||||
message("Dolphin plugin disabled: KDE Frameworks 5.16 not found")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
|
||||
if(APPLE)
|
||||
add_custom_target( legacy_mac_overlayplugin ALL
|
||||
xcodebuild -workspace ${CMAKE_SOURCE_DIR}/shell_integration/MacOSX/OwnCloud.xcworkspace
|
||||
-scheme SyncStateFinder.osax -configuration Release SYMROOT=${CMAKE_CURRENT_BINARY_DIR}
|
||||
OC_APPLICATION_REV_DOMAIN=${APPLICATION_REV_DOMAIN}
|
||||
OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX=${SOCKETAPI_TEAM_IDENTIFIER_PREFIX}
|
||||
COMMENT building Legacy Mac Overlay icons)
|
||||
|
||||
# Contrary to popular belief, this is called like this no matter what theme/OEM.
|
||||
set(OC_OEM_SHARE_ICNS "${CMAKE_BINARY_DIR}/src/gui/ownCloud.icns")
|
||||
|
||||
@@ -25,12 +17,6 @@ add_custom_target( mac_overlayplugin ALL
|
||||
VERBATIM)
|
||||
add_dependencies(mac_overlayplugin ${APPLICATION_EXECUTABLE}) # for the ownCloud.icns to be generated
|
||||
|
||||
|
||||
# legacy
|
||||
INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/SyncStateFinder.osax/Contents
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/Library/ScriptingAdditions/SyncStateFinder.osax/ )
|
||||
|
||||
# >= 10.10.x
|
||||
INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Release/FinderSyncExt.appex
|
||||
DESTINATION ${OWNCLOUD_OSX_BUNDLE}/Contents/PlugIns
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
|
||||
@@ -4,10 +4,4 @@
|
||||
<FileRef
|
||||
location = "group:OwnCloudFinderSync/OwnCloudFinderSync.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:OwnCloudFinder/OwnCloudFinder.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:OwnCloudInjector/OwnCloudInjector.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface OwnCloudFinderContentManager : NSObject
|
||||
{
|
||||
NSMutableDictionary* _fileNamesCache;
|
||||
NSMutableDictionary* _oldFileNamesCache;
|
||||
BOOL _fileIconsEnabled;
|
||||
BOOL _hasChangedContent;
|
||||
|
||||
NSNumber *_icnOk;
|
||||
NSNumber *_icnSync;
|
||||
NSNumber *_icnWarn;
|
||||
NSNumber *_icnErr;
|
||||
NSNumber *_icnOkSwm;
|
||||
NSNumber *_icnSyncSwm;
|
||||
NSNumber *_icnWarnSwm;
|
||||
NSNumber *_icnErrSwm;
|
||||
}
|
||||
|
||||
+ (OwnCloudFinderContentManager*)sharedInstance;
|
||||
|
||||
- (void)enableFileIcons:(BOOL)enable;
|
||||
- (NSNumber*)iconByPath:(NSString*)path isDirectory:(BOOL)isDir;
|
||||
- (void)removeAllIcons;
|
||||
- (void)setIcons:(NSDictionary*)iconDictionary filterByFolder:(NSString*)filterFolder;
|
||||
- (void)setResultForPath:(NSString*)path result:(NSString*)result;
|
||||
- (void)clearFileNameCache;
|
||||
- (void)reFetchFileNameCacheForPath:(NSString*)path;
|
||||
- (void)repaintAllWindows;
|
||||
|
||||
- (void)loadIconResources;
|
||||
|
||||
@end
|
||||
@@ -1,358 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#import <AppKit/NSApplication.h>
|
||||
#import <AppKit/NSWindow.h>
|
||||
#import <objc/runtime.h>
|
||||
#import "ContentManager.h"
|
||||
#import "MenuManager.h"
|
||||
#import "RequestManager.h"
|
||||
#import "IconCache.h"
|
||||
|
||||
static OwnCloudFinderContentManager* sharedInstance = nil;
|
||||
|
||||
@implementation OwnCloudFinderContentManager
|
||||
- init
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_fileNamesCache = [[NSMutableDictionary alloc] init];
|
||||
_oldFileNamesCache = [[NSMutableDictionary alloc] init];
|
||||
_fileIconsEnabled = TRUE;
|
||||
_hasChangedContent = TRUE;
|
||||
[self loadIconResources];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self removeAllIcons];
|
||||
[_fileNamesCache release];
|
||||
[_oldFileNamesCache release];
|
||||
sharedInstance = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
+ (OwnCloudFinderContentManager*)sharedInstance
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
if (sharedInstance == nil)
|
||||
{
|
||||
sharedInstance = [[self alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (void)loadIconResources
|
||||
{
|
||||
NSBundle *extBundle = [NSBundle bundleForClass:[self class]];
|
||||
|
||||
_icnOk = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"ok.icns"]];
|
||||
_icnSync = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"sync.icns"]];
|
||||
_icnWarn = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"warning.icns"]];
|
||||
_icnErr = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"error.icns"]];
|
||||
_icnOkSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"ok_swm.icns"]];
|
||||
_icnSyncSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"sync_swm.icns"]];
|
||||
_icnWarnSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"warning_swm.icns"]];
|
||||
_icnErrSwm = [[IconCache sharedInstance] registerIcon:[extBundle imageForResource:@"error_swm.icns"]];
|
||||
|
||||
// NSLog(@"Icon ok: %@ identifier: %d from bundle %@", [extBundle imageForResource:@"ok.icns"], [_icnOk intValue], extBundle);
|
||||
}
|
||||
|
||||
- (void)enableFileIcons:(BOOL)enable
|
||||
{
|
||||
_fileIconsEnabled = enable;
|
||||
|
||||
[self repaintAllWindows];
|
||||
}
|
||||
|
||||
- (void)setResultForPath:(NSString*)path result:(NSString*)result
|
||||
{
|
||||
if (_icnOk == nil) {
|
||||
// no icon resource path registered yet
|
||||
return;
|
||||
}
|
||||
|
||||
NSNumber *res;
|
||||
res = [NSNumber numberWithInt:0];
|
||||
|
||||
if( [result isEqualToString:@"OK"] ) {
|
||||
res = _icnOk;
|
||||
} else if( [result isEqualToString:@"SYNC"] || [result isEqualToString:@"NEW"] ) {
|
||||
res = _icnSync;
|
||||
} else if( [result isEqualToString:@"IGNORE"]) {
|
||||
res = _icnWarn;
|
||||
} else if( [result isEqualToString:@"ERROR"]) {
|
||||
res = _icnErr;
|
||||
} else if( [result isEqualToString:@"OK+SWM"] ) {
|
||||
res = _icnOkSwm;
|
||||
} else if( [result isEqualToString:@"SYNC+SWM"] || [result isEqualToString:@"NEW+SWM"] ) {
|
||||
res = _icnSyncSwm;
|
||||
} else if( [result isEqualToString:@"IGNORE+SWM"]) {
|
||||
res = _icnWarnSwm;
|
||||
} else if( [result isEqualToString:@"ERROR+SWM"]) {
|
||||
res = _icnErrSwm;
|
||||
}else if( [result isEqualToString:@"NOP"]) {
|
||||
// Nothing.
|
||||
} else {
|
||||
NSLog(@"SyncState: Unknown status code %@", result);
|
||||
}
|
||||
|
||||
NSString* normalizedPath = [path decomposedStringWithCanonicalMapping];
|
||||
|
||||
if (![_fileNamesCache objectForKey:normalizedPath] || ![[_fileNamesCache objectForKey:normalizedPath] isEqualTo:res]) {
|
||||
[_fileNamesCache setObject:res forKey:normalizedPath];
|
||||
//NSLog(@"SET value %d %@", [res intValue], normalizedPath);
|
||||
_hasChangedContent = YES;
|
||||
[self performSelector:@selector(repaintAllWindowsIfNeeded) withObject:0 afterDelay:1.0]; // 1 sec
|
||||
}
|
||||
}
|
||||
|
||||
- (NSNumber*)iconByPath:(NSString*)path isDirectory:(BOOL)isDir
|
||||
{
|
||||
//NSLog(@"%@ %@", NSStringFromSelector(_cmd), path);
|
||||
if (!_fileIconsEnabled)
|
||||
{
|
||||
NSLog(@"SyncState: Icons are NOT ENABLED!");
|
||||
// return nil;
|
||||
}
|
||||
|
||||
if( path == nil ) {
|
||||
NSNumber *res = [NSNumber numberWithInt:0];
|
||||
return res;
|
||||
}
|
||||
NSString* normalizedPath = [path decomposedStringWithCanonicalMapping];
|
||||
|
||||
if (![[OwnCloudFinderRequestManager sharedInstance] isRegisteredPath:normalizedPath isDirectory:isDir]) {
|
||||
return [NSNumber numberWithInt:0];
|
||||
}
|
||||
|
||||
NSNumber* result = [_fileNamesCache objectForKey:normalizedPath];
|
||||
// NSLog(@"XXXXXXX Asking for icon for path %@ = %d",normalizedPath, [result intValue]);
|
||||
|
||||
if( result == nil ) {
|
||||
result = [NSNumber numberWithInt:0];
|
||||
// Set 0 into the cache, meaning "don't have an icon, but already requested it"
|
||||
[_fileNamesCache setObject:result forKey:normalizedPath];
|
||||
// start the async call
|
||||
[[OwnCloudFinderRequestManager sharedInstance] askForIcon:normalizedPath isDirectory:isDir];
|
||||
}
|
||||
if ([result intValue] == 0) {
|
||||
// Show the old state while we wait for the new one
|
||||
NSNumber* oldResult = [_oldFileNamesCache objectForKey:normalizedPath];
|
||||
if (oldResult)
|
||||
result = oldResult;
|
||||
}
|
||||
// NSLog(@"iconByPath return value %d", [result intValue]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Clears the entries from the hash to make it call again home to the desktop client.
|
||||
- (void)clearFileNameCache
|
||||
{
|
||||
[_fileNamesCache release];
|
||||
_fileNamesCache = [[NSMutableDictionary alloc] init];
|
||||
[_oldFileNamesCache removeAllObjects];
|
||||
}
|
||||
|
||||
- (void)reFetchFileNameCacheForPath:(NSString*)path
|
||||
{
|
||||
//NSLog(@"%@", NSStringFromSelector(_cmd));
|
||||
|
||||
// We won't request the new state if it finds the path in _fileNamesCache
|
||||
// Move all entries to _oldFileNamesCache so that they get re-requested, but
|
||||
// still available while we refill the cache
|
||||
[_oldFileNamesCache addEntriesFromDictionary:_fileNamesCache];
|
||||
[_fileNamesCache removeAllObjects];
|
||||
|
||||
[self repaintAllWindows];
|
||||
}
|
||||
|
||||
|
||||
- (void)removeAllIcons
|
||||
{
|
||||
[_fileNamesCache removeAllObjects];
|
||||
[_oldFileNamesCache removeAllObjects];
|
||||
|
||||
[self repaintAllWindows];
|
||||
}
|
||||
|
||||
- (void)repaintAllWindowsIfNeeded
|
||||
{
|
||||
if (!_hasChangedContent) {
|
||||
//NSLog(@"%@ Repaint scheduled but not needed", NSStringFromSelector(_cmd));
|
||||
return;
|
||||
}
|
||||
|
||||
_hasChangedContent = NO;
|
||||
[self repaintAllWindows];
|
||||
}
|
||||
|
||||
- (void)repaintAllWindows
|
||||
{
|
||||
//NSLog(@"%@", NSStringFromSelector(_cmd));
|
||||
NSArray* windows = [[NSApplication sharedApplication] windows];
|
||||
|
||||
for (int i = 0; i < [windows count]; i++)
|
||||
{
|
||||
NSWindow* window = [windows objectAtIndex:i];
|
||||
|
||||
if (![window isVisible])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
OwnCloudFinderRequestManager* requestManager = [OwnCloudFinderRequestManager sharedInstance];
|
||||
|
||||
if ([[window className] isEqualToString:@"TBrowserWindow"])
|
||||
{
|
||||
NSObject* browserWindowController = [window browserWindowController];
|
||||
|
||||
BOOL repaintWindow = YES;
|
||||
|
||||
NSString* filterFolder = [requestManager filterFolder];
|
||||
|
||||
if (filterFolder)
|
||||
{
|
||||
repaintWindow = NO;
|
||||
|
||||
struct TFENodeVector* targetPath;
|
||||
|
||||
if ([browserWindowController respondsToSelector:@selector(targetPath)])
|
||||
{
|
||||
// 10.7 & 10.8
|
||||
targetPath = [browserWindowController targetPath];
|
||||
}
|
||||
else if ([browserWindowController respondsToSelector:@selector(activeContainer)])
|
||||
{
|
||||
// 10.9
|
||||
targetPath = [[browserWindowController activeContainer] targetPath];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"SyncState: refreshing icon badges failed");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray* folderPaths = [menuManager pathsForNodes:targetPath];
|
||||
|
||||
for (NSString* folderPath in folderPaths)
|
||||
{
|
||||
if ([folderPath hasPrefix:filterFolder] || [filterFolder hasPrefix:folderPath])
|
||||
{
|
||||
repaintWindow = YES;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (repaintWindow)
|
||||
{
|
||||
if ([browserWindowController respondsToSelector:@selector(browserViewController)])
|
||||
{
|
||||
// 10.7 & 10.8
|
||||
NSObject* browserViewController = [browserWindowController browserViewController];
|
||||
|
||||
NSObject* browserView = [browserViewController browserView];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{[browserView setNeedsDisplay:YES];});
|
||||
}
|
||||
else if ([browserWindowController respondsToSelector:@selector(activeBrowserViewController)])
|
||||
{
|
||||
// 10.9
|
||||
NSObject* browserViewController = [browserWindowController activeBrowserViewController];
|
||||
|
||||
NSObject* browserView = [browserViewController browserView];
|
||||
|
||||
if ([browserView isKindOfClass:(id)objc_getClass("TListView")])
|
||||
{
|
||||
// List or Coverflow View
|
||||
[self setNeedsDisplayForListView:browserView];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Icon or Column View
|
||||
dispatch_async(dispatch_get_main_queue(), ^{[browserView setNeedsDisplay:YES];});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"SyncState: refreshing icon badges failed");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setIcons:(NSDictionary*)iconDictionary filterByFolder:(NSString*)filterFolder
|
||||
{
|
||||
NSLog(@"%@", NSStringFromSelector(_cmd));
|
||||
for (NSString* path in iconDictionary)
|
||||
{
|
||||
if (filterFolder && ![path hasPrefix:filterFolder])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString* normalizedPath = [path decomposedStringWithCanonicalMapping];
|
||||
NSNumber* iconId = [iconDictionary objectForKey:path];
|
||||
|
||||
if ([iconId intValue] == -1)
|
||||
{
|
||||
[_fileNamesCache removeObjectForKey:normalizedPath];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_oldFileNamesCache removeObjectForKey:normalizedPath];
|
||||
[_fileNamesCache setObject:iconId forKey:normalizedPath];
|
||||
}
|
||||
}
|
||||
|
||||
[self repaintAllWindows];
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplayForListView:(NSView*)view
|
||||
{
|
||||
NSArray* subviews = [view subviews];
|
||||
|
||||
for (int i = 0; i < [subviews count]; i++)
|
||||
{
|
||||
NSView* subview = [subviews objectAtIndex:i];
|
||||
|
||||
if ([subview isKindOfClass:(id)objc_getClass("TListRowView")])
|
||||
{
|
||||
[self setNeedsDisplayForListView:subview];
|
||||
}
|
||||
else if ([subview isKindOfClass:(id)objc_getClass("TListNameCellView")])
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{[subview setNeedsDisplay:YES];});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSObject (ContextMenuHandlers)
|
||||
|
||||
struct TFENodeVector;
|
||||
|
||||
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 browserController:(id)arg5 addPlugIns:(BOOL)arg6;
|
||||
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 windowController:(id)arg5 addPlugIns:(BOOL)arg6;
|
||||
+ (void)OCContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3;
|
||||
|
||||
- (void)OCContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 browserController:(id)arg2 container:(BOOL)arg3;
|
||||
- (void)OCContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 windowController:(id)arg2 container:(BOOL)arg3;
|
||||
|
||||
@end
|
||||
@@ -1,101 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#import "ContextMenuHandlers.h"
|
||||
#import "MenuManager.h"
|
||||
|
||||
@class TIconViewController;
|
||||
|
||||
@implementation NSObject (ContextMenuHandlers)
|
||||
|
||||
+ (void)OCContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3 // 10.7 & 10.8
|
||||
{
|
||||
[self OCContextMenuHandlers_addViewSpecificStuffToMenu:arg1 browserViewController:arg2 context:arg3];
|
||||
NSLog(@"OCContextMenuHandlers_addViewSpecificStuffToMenu 10.7/10.8 %@ %@ %d", arg1, arg2, arg3);
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
if (menuManager.menuItems.count > 0)
|
||||
{
|
||||
[menuManager addItemsToMenu:arg1 forFiles:menuManager.menuItems];
|
||||
[menuManager.menuItems removeAllObjects];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)OCContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 clickedView:(id)arg2 browserViewController:(id)arg3 context:(unsigned int)arg4 // 10.9
|
||||
{
|
||||
[self OCContextMenuHandlers_addViewSpecificStuffToMenu:arg1 clickedView:arg2 browserViewController:arg3 context:arg4];
|
||||
NSLog(@"OCContextMenuHandlers_addViewSpecificStuffToMenu 10.9 %@ %@ %@ %d", arg1, arg2, arg3, arg4);
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
if (menuManager.menuItems.count > 0)
|
||||
{
|
||||
[menuManager addItemsToMenu:arg1 forFiles:menuManager.menuItems];
|
||||
[menuManager.menuItems removeAllObjects];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 windowController:(id)arg5 addPlugIns:(BOOL)arg6 // 10.7
|
||||
{
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
NSLog(@"ContextMenuHandlers_handleContextMenuCommon");
|
||||
menuManager.menuItems = (NSMutableArray*)[menuManager pathsForNodes:arg2];
|
||||
[self OCContextMenuHandlers_handleContextMenuCommon:arg1 nodes:arg2 event:arg3 view:arg4 windowController:arg5 addPlugIns:arg6];
|
||||
}
|
||||
|
||||
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 browserController:(id)arg5 addPlugIns:(BOOL)arg6 // 10.8
|
||||
{
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
NSLog(@"ContextMenuHandlers_handleContextMenuCommon");
|
||||
menuManager.menuItems = (NSMutableArray*)[menuManager pathsForNodes:arg2];
|
||||
[self OCContextMenuHandlers_handleContextMenuCommon:arg1 nodes:arg2 event:arg3 view:arg4 browserController:arg5 addPlugIns:arg6];
|
||||
}
|
||||
|
||||
+ (void)OCContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 clickedView:(id)arg4 browserViewController:(id)arg5 addPlugIns:(BOOL)arg6 // 10.9
|
||||
{
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
NSLog(@"ContextMenuHandlers_handleContextMenuCommon");
|
||||
menuManager.menuItems = (NSMutableArray*)[menuManager pathsForNodes:arg2];
|
||||
[self OCContextMenuHandlers_handleContextMenuCommon:arg1 nodes:arg2 event:arg3 clickedView:arg4 browserViewController:arg5 addPlugIns:arg6];
|
||||
}
|
||||
|
||||
- (void)OCContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 windowController:(id)arg2 container:(BOOL)arg3 // 10.7
|
||||
{
|
||||
[self OCContextMenuHandlers_configureWithNodes:arg1 windowController:arg2 container:arg3];
|
||||
NSLog(@"ContextMenuHandlers_configureWithNodes");
|
||||
TContextMenu* realSelf = (TContextMenu*)self;
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
NSArray* selectedItems = [menuManager pathsForNodes:arg1];
|
||||
[menuManager addItemsToMenu:realSelf forFiles:selectedItems];
|
||||
}
|
||||
|
||||
- (void)OCContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 browserController:(id)arg2 container:(BOOL)arg3 // 10.8
|
||||
{
|
||||
[self OCContextMenuHandlers_configureWithNodes:arg1 browserController:arg2 container:arg3];
|
||||
NSLog(@"ContextMenuHandlers_configureWithNodes");
|
||||
TContextMenu* realSelf = (TContextMenu*)self;
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
|
||||
NSArray* selectedItems = [menuManager pathsForNodes:arg1];
|
||||
[menuManager addItemsToMenu:realSelf forFiles:selectedItems];
|
||||
}
|
||||
|
||||
- (void)OCContextMenuHandlers_configureFromMenuNeedsUpdate:(id)arg1 clickedView:(id)arg2 container:(BOOL)arg3 event:(id)arg4 selectedNodes:(const struct TFENodeVector *)arg5 // 10.9
|
||||
{
|
||||
[self OCContextMenuHandlers_configureFromMenuNeedsUpdate:arg1 clickedView:arg2 container:arg3 event:arg4 selectedNodes:arg5]; // 10.8
|
||||
NSLog(@"ContextMenuHandlers_configureFromMenuNeedsUpdate");
|
||||
TContextMenu* realSelf = (TContextMenu*)self;
|
||||
MenuManager* menuManager = [MenuManager sharedInstance];
|
||||
NSArray* selectedItems = [menuManager pathsForNodes:arg5];
|
||||
[menuManager addItemsToMenu:realSelf forFiles:selectedItems];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#import "ContextMenuHandlers.h"
|
||||
#import "Finder/Finder.h"
|
||||
#import "MenuManager.h"
|
||||
|
||||
@implementation NSObject (ContextMenuHandlers)
|
||||
|
||||
+ (void) ContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 windowController:(id)arg5 addPlugIns:(BOOL)arg6 // Lion
|
||||
{
|
||||
MenuManager* contextMenuUtils = [MenuManager sharedInstance];
|
||||
|
||||
contextMenuUtils.menuItems = (NSMutableArray*)[contextMenuUtils pathsForNodes:arg2];
|
||||
|
||||
[self ContextMenuHandlers_handleContextMenuCommon:arg1 nodes:arg2 event:arg3 view:arg4 windowController:arg5 addPlugIns:arg6];
|
||||
}
|
||||
|
||||
+ (void) ContextMenuHandlers_handleContextMenuCommon:(unsigned int)arg1 nodes:(const struct TFENodeVector*)arg2 event:(id)arg3 view:(id)arg4 browserController:(id)arg5 addPlugIns:(BOOL)arg6 // Mountain Lion
|
||||
{
|
||||
MenuManager* contextMenuUtils = [MenuManager sharedInstance];
|
||||
|
||||
contextMenuUtils.menuItems = (NSMutableArray*)[contextMenuUtils pathsForNodes:arg2];
|
||||
|
||||
[self ContextMenuHandlers_handleContextMenuCommon:arg1 nodes:arg2 event:arg3 view:arg4 browserController:arg5 addPlugIns:arg6];
|
||||
}
|
||||
|
||||
+ (void) ContextMenuHandlers_addViewSpecificStuffToMenu:(id)arg1 browserViewController:(id)arg2 context:(unsigned int)arg3
|
||||
{
|
||||
[self ContextMenuHandlers_addViewSpecificStuffToMenu:arg1 browserViewController:arg2 context:arg3];
|
||||
|
||||
if ([MenuManager sharedInstance].menuItems.count > 0)
|
||||
{
|
||||
MenuManager* contextMenuUtils = [MenuManager sharedInstance];
|
||||
[contextMenuUtils addItemsToMenu:arg1 forPaths:contextMenuUtils.menuItems];
|
||||
[contextMenuUtils.menuItems removeAllObjects];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) ContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 windowController:(id)arg2 container:(BOOL)arg3 // Lion
|
||||
{
|
||||
[self ContextMenuHandlers_configureWithNodes:arg1 windowController:arg2 container:arg3];
|
||||
|
||||
TContextMenu* realSelf = (TContextMenu*)self;
|
||||
MenuManager* contextMenuUtils = [MenuManager sharedInstance];
|
||||
|
||||
NSArray* selectedItems = [contextMenuUtils pathsForNodes:arg1];
|
||||
[contextMenuUtils addItemsToMenu:realSelf forPaths:selectedItems];
|
||||
}
|
||||
|
||||
- (void) ContextMenuHandlers_configureWithNodes:(const struct TFENodeVector*)arg1 browserController:(id)arg2 container:(BOOL)arg3 // Mountain Lion
|
||||
{
|
||||
[self ContextMenuHandlers_configureWithNodes:arg1 browserController:arg2 container:arg3];
|
||||
|
||||
TContextMenu* realSelf = (TContextMenu*)self;
|
||||
MenuManager* contextMenuUtils = [MenuManager sharedInstance];
|
||||
|
||||
NSArray* selectedItems = [contextMenuUtils pathsForNodes:arg1];
|
||||
[contextMenuUtils addItemsToMenu:realSelf forPaths:selectedItems];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@@ -1,2 +0,0 @@
|
||||
/* Localized versions of Info.plist keys */
|
||||
|
||||