Compare commits
784
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
621aada0d1 | ||
|
|
e5a3fed155 | ||
|
|
67b133a206 | ||
|
|
5b1df6fa61 | ||
|
|
f50b49c56e | ||
|
|
e05888e557 | ||
|
|
c36ec0cbc5 | ||
|
|
b968dba9ce | ||
|
|
7a85b1763f | ||
|
|
599b4124f2 | ||
|
|
037e9e179f | ||
|
|
b9d6084973 | ||
|
|
c52f08bc6e | ||
|
|
85d5b1d74e | ||
|
|
63fc93ab38 | ||
|
|
790f9c06fa | ||
|
|
12407d4c03 | ||
|
|
090ecf1af6 | ||
|
|
105f6e16ff | ||
|
|
499a3ad575 | ||
|
|
f0107b476a | ||
|
|
b7cac4cd51 | ||
|
|
b55ba094b6 | ||
|
|
fecb2bf25a | ||
|
|
877b1c811f | ||
|
|
3bb06311a8 | ||
|
|
8d96681db6 | ||
|
|
f458355663 | ||
|
|
e9d7433a72 | ||
|
|
6195e07808 | ||
|
|
53059c01dd | ||
|
|
bb274822cc | ||
|
|
f74cee2932 | ||
|
|
92f1de07ae | ||
|
|
f040df8e2f | ||
|
|
ab7e640435 | ||
|
|
27ce549e75 | ||
|
|
09d30b92e0 | ||
|
|
bc0a47f768 | ||
|
|
75bab41034 | ||
|
|
94d6ab76ee | ||
|
|
1d913e026f | ||
|
|
974f6bff2f | ||
|
|
0ae9990f18 | ||
|
|
18ff96c5fe | ||
|
|
b39a68bda7 | ||
|
|
60437d7fc0 | ||
|
|
618d9015ab | ||
|
|
9b19bac7da | ||
|
|
6917030417 | ||
|
|
44a45fcd04 | ||
|
|
f7656f464e | ||
|
|
59b00a5a45 | ||
|
|
31f0cd02ab | ||
|
|
627c270025 | ||
|
|
5d0d9fbc80 | ||
|
|
92fea213f9 | ||
|
|
4fe138097b | ||
|
|
e25df96d23 | ||
|
|
8d82363163 | ||
|
|
d7345ad993 | ||
|
|
85368266ed | ||
|
|
38ac29be13 | ||
|
|
5e9ec4ee98 | ||
|
|
fef9efe4d4 | ||
|
|
2c42108df3 | ||
|
|
f91c4c7328 | ||
|
|
54237b1cbb | ||
|
|
c0f834f511 | ||
|
|
a87984806e | ||
|
|
1c40025666 | ||
|
|
f9170602d3 | ||
|
|
6cebb6b84f | ||
|
|
8f56220f2f | ||
|
|
be9a3667e6 | ||
|
|
c023e29020 | ||
|
|
8a02dc014e | ||
|
|
3f51536073 | ||
|
|
d2e91f8db6 | ||
|
|
caf7d53583 | ||
|
|
d3a8ecacad | ||
|
|
d68d94e7f8 | ||
|
|
dab2b23332 | ||
|
|
68ae2a460a | ||
|
|
d261899189 | ||
|
|
002a47bd1e | ||
|
|
bb9be1ee4b | ||
|
|
17e2266a69 | ||
|
|
41b772d385 | ||
|
|
c50e027ecd | ||
|
|
a5a03c2a41 | ||
|
|
991870b9c3 | ||
|
|
5de458e74f | ||
|
|
8b908cb43d | ||
|
|
1b3b7fbd1e | ||
|
|
b9031e9f20 | ||
|
|
21fe0f9cfb | ||
|
|
e0d93da2f5 | ||
|
|
b515a6f6f2 | ||
|
|
6998cc1e28 | ||
|
|
1acda72561 | ||
|
|
246c95c60a | ||
|
|
0855d7fe4d | ||
|
|
5d7fb66c1c | ||
|
|
6ab2a63218 | ||
|
|
b699937dee | ||
|
|
d6fe8c1a7d | ||
|
|
fa7d5e45f7 | ||
|
|
8efab7f746 | ||
|
|
3f29331dc6 | ||
|
|
92b82df78b | ||
|
|
fd9b1a1c5b | ||
|
|
bbff638212 | ||
|
|
c9f8e5786c | ||
|
|
4392d84da4 | ||
|
|
a47af06bb7 | ||
|
|
34821192fc | ||
|
|
3487f2fdf4 | ||
|
|
d3ec5f54fe | ||
|
|
0f1d381c7f | ||
|
|
edc0fb5e4b | ||
|
|
25a7667e36 | ||
|
|
d463e6bda7 | ||
|
|
cddf0917e3 | ||
|
|
6945270d49 | ||
|
|
3f29642f6c | ||
|
|
bb73f8f22e | ||
|
|
ca4fde938c | ||
|
|
e32bba1dfc | ||
|
|
1b7e1349ca | ||
|
|
9ca5489ef0 | ||
|
|
9d7fad14cf | ||
|
|
828ba240f3 | ||
|
|
486e13dd51 | ||
|
|
37071136b7 | ||
|
|
c0b8129924 | ||
|
|
fe90f8ce3d | ||
|
|
829c434c64 | ||
|
|
8b8707c811 | ||
|
|
87c92d40ca | ||
|
|
763048c8bd | ||
|
|
9b9e8a2adb | ||
|
|
47ca64ee63 | ||
|
|
e88c30edd1 | ||
|
|
4294ee3611 | ||
|
|
1920b0684d | ||
|
|
973d005c07 | ||
|
|
f70748359a | ||
|
|
8be2a14f66 | ||
|
|
f20d7b9321 | ||
|
|
1a44be4199 | ||
|
|
0e93df8e3e | ||
|
|
bb65e89139 | ||
|
|
e4c578afa2 | ||
|
|
d264dbd329 | ||
|
|
e316944a50 | ||
|
|
f4dee8a305 | ||
|
|
f9db217af0 | ||
|
|
773f3acfb3 | ||
|
|
270f2f9cea | ||
|
|
25bb4f3701 | ||
|
|
9dff0fa953 | ||
|
|
0e12adb210 | ||
|
|
1d0d7e0152 | ||
|
|
ca425808c5 | ||
|
|
6878a601a9 | ||
|
|
9f79025744 | ||
|
|
12fb0d36ea | ||
|
|
bb7b3e5de4 | ||
|
|
fdc891aa36 | ||
|
|
b11c558ba2 | ||
|
|
2a12fdc493 | ||
|
|
c0a49dec2d | ||
|
|
dbdd9a0022 | ||
|
|
a5c6c18f26 | ||
|
|
516a8e728a | ||
|
|
95cb6b4e71 | ||
|
|
4b12109e7f | ||
|
|
7dab2f5935 | ||
|
|
6841ad7fa8 | ||
|
|
c57321a4f7 | ||
|
|
245d2f5e95 | ||
|
|
9031890456 | ||
|
|
9e0ce5fb0c | ||
|
|
3ccca04f1c | ||
|
|
2b901b511c | ||
|
|
7c9f964eeb | ||
|
|
5312499107 | ||
|
|
26b77b29a7 | ||
|
|
1fb46d7fd2 | ||
|
|
917e2cd0c4 | ||
|
|
930f1c8bd3 | ||
|
|
1dc1fd83af | ||
|
|
2ecfde44f9 | ||
|
|
55284410c7 | ||
|
|
2e7b8fc468 | ||
|
|
d9174d1488 | ||
|
|
7f2703c5b6 | ||
|
|
2e30a35da9 | ||
|
|
db60e91042 | ||
|
|
3ebc7f7f42 | ||
|
|
b13ab5e0cf | ||
|
|
4b5187561a | ||
|
|
914316de39 | ||
|
|
e0ef501e6a | ||
|
|
529133d967 | ||
|
|
ad4ef7ed95 | ||
|
|
58e37e39ef | ||
|
|
a29b5056ae | ||
|
|
15031af381 | ||
|
|
d97767689b | ||
|
|
fbff3a3ed9 | ||
|
|
9ca797944b | ||
|
|
75bb8942ca | ||
|
|
b3f0b1be81 | ||
|
|
6a1bd40498 | ||
|
|
5417099e04 | ||
|
|
c890e824ee | ||
|
|
db79b8e51b | ||
|
|
aaf1067926 | ||
|
|
9d43685352 | ||
|
|
95b040d386 | ||
|
|
afc34e00be | ||
|
|
e743cc7b21 | ||
|
|
f3394584af | ||
|
|
095a84dd4b | ||
|
|
67463adf00 | ||
|
|
2a497acb56 | ||
|
|
8fe14b4754 | ||
|
|
84d7a56ab1 | ||
|
|
05e5fbcf80 | ||
|
|
9e787c7cce | ||
|
|
54b9063f1b | ||
|
|
3e01a9352c | ||
|
|
a89ccdec7d | ||
|
|
e747e8445c | ||
|
|
30d68fcf76 | ||
|
|
af75c2e6c9 | ||
|
|
69a6c09699 | ||
|
|
91f82a1a1c | ||
|
|
6868d1f053 | ||
|
|
279a0d3ee1 | ||
|
|
55cea2845c | ||
|
|
8c6f4d356d | ||
|
|
003a70b950 | ||
|
|
058bb26005 | ||
|
|
226f200006 | ||
|
|
238bfdd02c | ||
|
|
4b15395095 | ||
|
|
3c3f82ab54 | ||
|
|
bda368febf | ||
|
|
6a134ce04e | ||
|
|
67665e47ee | ||
|
|
ca9b48ee98 | ||
|
|
e2e8adf02f | ||
|
|
796be8ce29 | ||
|
|
f79b1f93c4 | ||
|
|
50808c866b | ||
|
|
0d6e9487d7 | ||
|
|
7bc34b9ff8 | ||
|
|
dac54d4ce5 | ||
|
|
c61f8d5b32 | ||
|
|
45c7e90479 | ||
|
|
83878dcbcd | ||
|
|
d5f7d69f39 | ||
|
|
e6c347217d | ||
|
|
1265f88cf8 | ||
|
|
8968937506 | ||
|
|
792e1abf74 | ||
|
|
a76e692183 | ||
|
|
33c735c853 | ||
|
|
288e3534b1 | ||
|
|
81f4e93c09 | ||
|
|
6caa01f051 | ||
|
|
bcd2ec815c | ||
|
|
f1fb843846 | ||
|
|
d27a1f1db8 | ||
|
|
b8f9a634e3 | ||
|
|
0e60bf4ca5 | ||
|
|
ebd34c853e | ||
|
|
43e62f2479 | ||
|
|
7ee8514f7e | ||
|
|
8458d1efd6 | ||
|
|
4eedbc118a | ||
|
|
f8628d32dc | ||
|
|
fe02dfc0de | ||
|
|
2bd921fe25 | ||
|
|
39af4fb521 | ||
|
|
5646f5ea92 | ||
|
|
9768a7349b | ||
|
|
aeb335ce07 | ||
|
|
67c1213a98 | ||
|
|
c7bde590dc | ||
|
|
fa73849783 | ||
|
|
cbf98657d3 | ||
|
|
5b9e294dec | ||
|
|
1bdfed6a90 | ||
|
|
8a39372c73 | ||
|
|
b51f0ed71e | ||
|
|
b5386573b5 | ||
|
|
b87ef92e37 | ||
|
|
b32c6a4f15 | ||
|
|
7b34dbd022 | ||
|
|
f708338b2d | ||
|
|
508cd56502 | ||
|
|
2d7e89407c | ||
|
|
8e25c6e2ab | ||
|
|
a937e8712e | ||
|
|
8625f14744 | ||
|
|
2773efec93 | ||
|
|
8fa4875885 | ||
|
|
6e16e1d9ed | ||
|
|
dfb6ee0f29 | ||
|
|
097375a6e8 | ||
|
|
70741dc99c | ||
|
|
db8fb59577 | ||
|
|
e927e7230d | ||
|
|
f80df1b824 | ||
|
|
4657f48a64 | ||
|
|
8bf183cea1 | ||
|
|
dab3d989e1 | ||
|
|
b5f1177bf8 | ||
|
|
60aacaa4bf | ||
|
|
696c431dce | ||
|
|
787b2bf04f | ||
|
|
612f657614 | ||
|
|
8961269675 | ||
|
|
76addf3a9e | ||
|
|
9c0ef09a39 | ||
|
|
fe33c4bf93 | ||
|
|
b73e94de7e | ||
|
|
6d3e2c7474 | ||
|
|
b6ca526ee7 | ||
|
|
fb45a14e00 | ||
|
|
37516b7fe6 | ||
|
|
0fefb316eb | ||
|
|
f9f6dfee6b | ||
|
|
0b566ecf1f | ||
|
|
a31a288819 | ||
|
|
75efe35e3d | ||
|
|
5f422ad605 | ||
|
|
a2c4b0a580 | ||
|
|
85c2864a9b | ||
|
|
2dcafc707b | ||
|
|
1389bac306 | ||
|
|
c4eab9ce82 | ||
|
|
59079675e9 | ||
|
|
502de4933f | ||
|
|
5e62a33f2e | ||
|
|
220c550181 | ||
|
|
bb99a4a6b1 | ||
|
|
9d1f985be6 | ||
|
|
9809ef5a78 | ||
|
|
c2a37d0cd8 | ||
|
|
62f707be6d | ||
|
|
22043c8d12 | ||
|
|
bde36461e5 | ||
|
|
23a9c72115 | ||
|
|
fcc95fa936 | ||
|
|
c45c1b3961 | ||
|
|
1a9fa8f52a | ||
|
|
7b9af8d237 | ||
|
|
b3f3fcff70 | ||
|
|
6362dd3cf8 | ||
|
|
09b5be5e64 | ||
|
|
cc5d73d1c6 | ||
|
|
1f6e1d238d | ||
|
|
675d361e62 | ||
|
|
142e8e79f2 | ||
|
|
6994c301b4 | ||
|
|
e871bea8aa | ||
|
|
d8159f6772 | ||
|
|
b84f235ffc | ||
|
|
3e3f1cacfa | ||
|
|
a0c0cbf3d5 | ||
|
|
49fb45859c | ||
|
|
f8cec10a6d | ||
|
|
bf7aff469d | ||
|
|
a70775ed30 | ||
|
|
7c130cc00f | ||
|
|
d4c695f28b | ||
|
|
4a89f9bb52 | ||
|
|
55b22ee18b | ||
|
|
4dd16d6ae3 | ||
|
|
162c9291e7 | ||
|
|
b871ab5058 | ||
|
|
53e585b594 | ||
|
|
af64822346 | ||
|
|
9610a52f9d | ||
|
|
b6e1f7b75f | ||
|
|
f6678586e0 | ||
|
|
c988ccdf76 | ||
|
|
516ae7d59b | ||
|
|
7180b1af82 | ||
|
|
6cd9eb0f0c | ||
|
|
35121a9b02 | ||
|
|
d8d83f2f11 | ||
|
|
3b831695a3 | ||
|
|
037ce702fe | ||
|
|
f0d61c0f1a | ||
|
|
b5e9ce18cd | ||
|
|
52dccc74d7 | ||
|
|
13367f4ab4 | ||
|
|
847be2d00a | ||
|
|
149703d0c8 | ||
|
|
d15ed599d9 | ||
|
|
b89861721b | ||
|
|
8f5025af62 | ||
|
|
ff560c6fef | ||
|
|
b2bea69f6e | ||
|
|
d318467b09 | ||
|
|
3731622722 | ||
|
|
79409a8359 | ||
|
|
605deefebd | ||
|
|
02d476d16c | ||
|
|
23065d44ef | ||
|
|
45c3d6828a | ||
|
|
d78b9f2c63 | ||
|
|
9f0810612a | ||
|
|
f1e767b9cc | ||
|
|
cc091f06fe | ||
|
|
a1a4042198 | ||
|
|
6041c8f1d9 | ||
|
|
5d53eddb32 | ||
|
|
e97783382d | ||
|
|
760eea01c8 | ||
|
|
4e837a865c | ||
|
|
32e852a392 | ||
|
|
544dc93dff | ||
|
|
3fa6977b1f | ||
|
|
3c65db405a | ||
|
|
b4aad97697 | ||
|
|
9c4dcb275c | ||
|
|
0b0a4491de | ||
|
|
dbfd564a03 | ||
|
|
3da45c53df | ||
|
|
7dfa19d48b | ||
|
|
f77f77ad3a | ||
|
|
76983002e6 | ||
|
|
240dfc1784 | ||
|
|
8a7a69cd50 | ||
|
|
7eff0dd2af | ||
|
|
115e887802 | ||
|
|
34b2b02025 | ||
|
|
b8151b1ddf | ||
|
|
a8ee4f2ba1 | ||
|
|
b27323c705 | ||
|
|
c49e5609a9 | ||
|
|
cbe8c43414 | ||
|
|
29b9afa6b3 | ||
|
|
bbbf77427e | ||
|
|
989aa925a0 | ||
|
|
51f93301fd | ||
|
|
9377fdffc1 | ||
|
|
a4fd6e9c8c | ||
|
|
7cc3d4e662 | ||
|
|
52265395c5 | ||
|
|
2303f9151f | ||
|
|
473c6cbbb8 | ||
|
|
281ff48189 | ||
|
|
8e1347c52c | ||
|
|
d7f027b9e2 | ||
|
|
2ce049cecb | ||
|
|
17c2ab9dc6 | ||
|
|
4f577c65a4 | ||
|
|
bc5f17ebf1 | ||
|
|
3501cdee08 | ||
|
|
6feb7c0200 | ||
|
|
f395da68d7 | ||
|
|
d3d4fc1434 | ||
|
|
c08571efba | ||
|
|
5c1d6bda76 | ||
|
|
cfbfdad2ab | ||
|
|
fb863ea14e | ||
|
|
97d89bb46f | ||
|
|
c168849dff | ||
|
|
aa20088c39 | ||
|
|
35cc847df7 | ||
|
|
65e907d79f | ||
|
|
a3bbf63561 | ||
|
|
72e47e419c | ||
|
|
133dda94a3 | ||
|
|
83a6e262c4 | ||
|
|
3bf6b162ca | ||
|
|
22acb8bdda | ||
|
|
d7b6dd90be | ||
|
|
a1349b1af9 | ||
|
|
74db90924e | ||
|
|
5acf4dbaad | ||
|
|
9dbdbb1b2f | ||
|
|
c9e9b0eeb7 | ||
|
|
aa365f7f34 | ||
|
|
0754a5cd72 | ||
|
|
8af1dbb6fd | ||
|
|
cff1049347 | ||
|
|
6b5623651c | ||
|
|
0f5b4b9707 | ||
|
|
b9d4be60ca | ||
|
|
b6643fa473 | ||
|
|
708715e705 | ||
|
|
ab3a0f58f1 | ||
|
|
97862fbeec | ||
|
|
6fb3206b22 | ||
|
|
f0e9257a62 | ||
|
|
238f1dd900 | ||
|
|
006af8fd78 | ||
|
|
c318c43002 | ||
|
|
e5442da247 | ||
|
|
83bc52bff4 | ||
|
|
235568dade | ||
|
|
83cc35664b | ||
|
|
69ccc12e7d | ||
|
|
bb3ab13a8e | ||
|
|
aeb4402a54 | ||
|
|
2e2da4fde7 | ||
|
|
4501dff4d3 | ||
|
|
71796c6ebf | ||
|
|
ab805b2173 | ||
|
|
08472517b9 | ||
|
|
78197453a1 | ||
|
|
3f9263892b | ||
|
|
0c2b3694c5 | ||
|
|
ae70cf344d | ||
|
|
052b169e9e | ||
|
|
bf3e6337b0 | ||
|
|
173b6f8ef0 | ||
|
|
afa322cc59 | ||
|
|
0a35243b07 | ||
|
|
8055cfb4f0 | ||
|
|
86ceb95e28 | ||
|
|
961b443f1f | ||
|
|
cfa41434ad | ||
|
|
817b1d5bc2 | ||
|
|
3172ec3a4b | ||
|
|
5956b771f0 | ||
|
|
c38e654db9 | ||
|
|
dc5750e6ab | ||
|
|
e66fc1ddc8 | ||
|
|
9dfec79a64 | ||
|
|
6d617f32fc | ||
|
|
b3826237d5 | ||
|
|
d8fb30298d | ||
|
|
80de20b557 | ||
|
|
1af776a4d6 | ||
|
|
8c518f7d3a | ||
|
|
02af15d4a4 | ||
|
|
06bca4b5d8 | ||
|
|
71faeb9a0e | ||
|
|
20214f6c00 | ||
|
|
dfd210125e | ||
|
|
c2a3987f3a | ||
|
|
7a4c7b36b8 | ||
|
|
081502fc2a | ||
|
|
eba9f4545c | ||
|
|
cd71fde158 | ||
|
|
7419df0979 | ||
|
|
80b19b9f8c | ||
|
|
02f58d5186 | ||
|
|
db30c5df85 | ||
|
|
1a5cca1bf7 | ||
|
|
26dea45698 | ||
|
|
0093561ec6 | ||
|
|
bf5b9537d8 | ||
|
|
d196e42780 | ||
|
|
88955a480d | ||
|
|
a8182b2c77 | ||
|
|
a432b7fead | ||
|
|
f5ef2d0ba2 | ||
|
|
3ce9965c19 | ||
|
|
996f508e3a | ||
|
|
437f373373 | ||
|
|
95ae2fdd19 | ||
|
|
ea16150d4f | ||
|
|
15256c70ef | ||
|
|
c2880f517b | ||
|
|
6dafc91239 | ||
|
|
6498c32a97 | ||
|
|
d7d9054f36 | ||
|
|
692391bd3e | ||
|
|
10a57b9b5f | ||
|
|
e898ea0745 | ||
|
|
2efb2543e1 | ||
|
|
29b1b7097c | ||
|
|
d528703fe7 | ||
|
|
895ab357a7 | ||
|
|
b400be18da | ||
|
|
30287a3eb4 | ||
|
|
f2bcf470d2 | ||
|
|
67eef2c1fd | ||
|
|
69d90e8fc3 | ||
|
|
060b4886da | ||
|
|
f3b43d2df6 | ||
|
|
48f2679391 | ||
|
|
dea88ee58c | ||
|
|
82f60d7989 | ||
|
|
1e64788a6b | ||
|
|
7b90ed3c5a | ||
|
|
6f3d293364 | ||
|
|
6fd696a661 | ||
|
|
1b72212533 | ||
|
|
e3c96d0ee0 | ||
|
|
ecb0249259 | ||
|
|
d8ddd6982c | ||
|
|
7b760ce237 | ||
|
|
898193fcef | ||
|
|
0f675bc4a9 | ||
|
|
5a034f7b6d | ||
|
|
4911cfdaa4 | ||
|
|
b550e61d9b | ||
|
|
557415c9ad | ||
|
|
8892ff7df3 | ||
|
|
425a9d23dc | ||
|
|
842fc6dbae | ||
|
|
11e4d35efb | ||
|
|
f73d736f54 | ||
|
|
90ac3c1cef | ||
|
|
753f61ee1f | ||
|
|
6810f410d3 | ||
|
|
4c6439c507 | ||
|
|
a7eed0a518 | ||
|
|
400fa2a7d1 | ||
|
|
70727b9f68 | ||
|
|
bd172d39c8 | ||
|
|
63d8ab7c11 | ||
|
|
abc361031c | ||
|
|
4f565a004f | ||
|
|
4d6d671fdc | ||
|
|
dfa9e527bd | ||
|
|
0e227a31b9 | ||
|
|
3b8d9608ef | ||
|
|
a28b5c7860 | ||
|
|
ab9e807bc0 | ||
|
|
dd399d8f2f | ||
|
|
3056824ff1 | ||
|
|
46440ebf40 | ||
|
|
acb557314f | ||
|
|
761eacc55d | ||
|
|
ffc7b165ad | ||
|
|
aad89b9bda | ||
|
|
5e8db0cead | ||
|
|
bb0a6e8a12 | ||
|
|
cda1e2e09a | ||
|
|
f424c1e999 | ||
|
|
32c3eb3a0e | ||
|
|
2db939ba6a | ||
|
|
14dbd73da2 | ||
|
|
51288b85ed | ||
|
|
3a730741c2 | ||
|
|
096e0a46f3 | ||
|
|
39b79f6474 | ||
|
|
47b3da1cd3 | ||
|
|
9d8e6014ce | ||
|
|
60e85591a9 | ||
|
|
cc6e404397 | ||
|
|
d976969deb | ||
|
|
aa05b6bead | ||
|
|
dd883b8937 | ||
|
|
8e7f55d863 | ||
|
|
3643862bfd | ||
|
|
25217a93c1 | ||
|
|
48f7110c0b | ||
|
|
e80abca658 | ||
|
|
f2d209cfaf | ||
|
|
733fd712d2 | ||
|
|
4cdeaa94c7 | ||
|
|
d4e613939e | ||
|
|
7400e20ff0 | ||
|
|
d935d71d3a | ||
|
|
7b30ef31ea | ||
|
|
0ee4f27ab6 | ||
|
|
238a31fea0 | ||
|
|
360d819c0d | ||
|
|
e74433aced | ||
|
|
b1001fcfea | ||
|
|
73d3310cf8 | ||
|
|
ef0039b8ff | ||
|
|
a759995e7b | ||
|
|
b1973934d7 | ||
|
|
971b5bc64e | ||
|
|
9050e6449f | ||
|
|
50bc8880ac | ||
|
|
acea2fe10f | ||
|
|
624a5d698b | ||
|
|
7b40e8df20 | ||
|
|
b008aed1f3 | ||
|
|
3f2eb254c3 | ||
|
|
c882953fdd | ||
|
|
4c5b5dd692 | ||
|
|
7e2218663e | ||
|
|
4d62e9584d | ||
|
|
76b191327f | ||
|
|
28793ef204 | ||
|
|
41a5591532 | ||
|
|
951be5e661 | ||
|
|
1c28cf0b15 | ||
|
|
95584c2d0f | ||
|
|
470d96e748 | ||
|
|
dd0b6add42 | ||
|
|
62d64c3ab0 | ||
|
|
576e3702e7 | ||
|
|
87f9222a87 | ||
|
|
8ad9f81356 | ||
|
|
c90408aa2c | ||
|
|
74a35ded53 | ||
|
|
66eee70d1e | ||
|
|
afa2fa2572 | ||
|
|
7b5b7f2134 | ||
|
|
e4364939de | ||
|
|
96ea8b124d | ||
|
|
7aea21ef35 | ||
|
|
54d462b263 | ||
|
|
34f874c6f0 | ||
|
|
f4eef557ee | ||
|
|
c9d8f42217 | ||
|
|
eff8abbeb1 | ||
|
|
34805225be | ||
|
|
13d723a026 | ||
|
|
ea7cbfa889 | ||
|
|
e7b1df98de | ||
|
|
84de33bd5f | ||
|
|
c482424b53 | ||
|
|
81ed86ec7d | ||
|
|
27671e0585 | ||
|
|
787bcb57ae | ||
|
|
c01210a443 | ||
|
|
676787cebd | ||
|
|
ad2105aeb2 | ||
|
|
0cb6e4a1bf | ||
|
|
5a6fc4336a | ||
|
|
ae4174204b | ||
|
|
cf74ae2cc3 | ||
|
|
4b2f014634 | ||
|
|
cac6ea4679 | ||
|
|
0d4ded3ae2 | ||
|
|
5ae4319d92 | ||
|
|
450ab23d76 | ||
|
|
aed2f4d5c8 | ||
|
|
cff004df76 | ||
|
|
843b69136b | ||
|
|
958f102e9e | ||
|
|
1bc1e58737 | ||
|
|
633f6e7de2 | ||
|
|
60c99b3888 | ||
|
|
1e6ed778f5 | ||
|
|
cd0335892b | ||
|
|
66c78b8f3d | ||
|
|
881087f968 | ||
|
|
86d015997b | ||
|
|
2cac7cecd2 | ||
|
|
ed9af377d2 | ||
|
|
513a4c71cf | ||
|
|
00887055cc | ||
|
|
d2ed5c6b27 | ||
|
|
478d4565af | ||
|
|
c2a7bed781 | ||
|
|
8ddc41fc70 | ||
|
|
b6fc1d2b52 | ||
|
|
be503ea028 | ||
|
|
a22a7a7d24 | ||
|
|
30fab22340 | ||
|
|
64d8e114ff | ||
|
|
b11f4d7cdd | ||
|
|
5253bc7c31 | ||
|
|
6971fa4614 | ||
|
|
d1c20de111 | ||
|
|
989ae94bac | ||
|
|
860bbdd363 | ||
|
|
795b5c34dc | ||
|
|
4931739194 | ||
|
|
a741425a66 | ||
|
|
c181a1946d | ||
|
|
dd3271f685 | ||
|
|
9e930acec5 | ||
|
|
f1caf7ad3a | ||
|
|
e2e1ddc151 | ||
|
|
68de4bbbde | ||
|
|
6289530f08 | ||
|
|
e4997f1efc | ||
|
|
b6316bcc21 | ||
|
|
987086358d | ||
|
|
3aeb2abf79 | ||
|
|
f5672f69d9 | ||
|
|
cb3d830e8e | ||
|
|
d3d494b574 |
@@ -1,66 +0,0 @@
|
||||
version: 1.0.{build}
|
||||
image: Visual Studio 2019
|
||||
configuration: Debug
|
||||
platform: Any CPU
|
||||
environment:
|
||||
AUTOUPDATER_Duplicati_SKIP_UPDATE: 1
|
||||
COVERALLS_REPO_TOKEN:
|
||||
secure: szQsrkP5rvra8L60SomD73/dFvRwot0UuyA566zqzI2qmLOr+MhLN0AyC8BTbhYY
|
||||
before_build:
|
||||
- ps: $env:UNITTEST_BASEFOLDER = "$Env:APPVEYOR_BUILD_FOLDER" + "\testdata"
|
||||
- cmd: nuget restore Duplicati.sln
|
||||
build:
|
||||
project: Duplicati.sln
|
||||
verbosity: minimal
|
||||
test_script:
|
||||
- ps: |
|
||||
nuget install OpenCover -Version 4.7.922 -OutputDirectory packages
|
||||
nuget install coveralls.net -Version 0.7.0 -OutputDirectory packages
|
||||
nuget install NUnit.Runners -Version 3.10.0 -OutputDirectory packages
|
||||
|
||||
$testDir = ".\Duplicati\UnitTest\bin\Debug"
|
||||
$tests = @("$testDir\Duplicati.UnitTest.dll")
|
||||
$testsPassed = $true
|
||||
|
||||
foreach ($elem in $tests) {
|
||||
$testResultsFile = "$elem" + ".xml"
|
||||
|
||||
.\packages\OpenCover.4.7.922\tools\OpenCover.Console.exe `
|
||||
-register:user `
|
||||
-target:.\packages\NUnit.ConsoleRunner.3.10.0\tools\nunit3-console.exe `
|
||||
"-targetargs:""$elem"" /result:""$testResultsFile""" `
|
||||
"-filter:+[Duplicati.Library.Main]* -[UnitTest]*" `
|
||||
-output:opencover.xml `
|
||||
-returntargetcode `
|
||||
|
||||
# Keep track of test failures so that we can throw an exception after
|
||||
# uploading coverage and test results.
|
||||
$testsPassed = $testsPassed -and $?
|
||||
|
||||
# Upload test results to AppVeyor.
|
||||
$wc = New-Object "System.Net.WebClient"
|
||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\""$testResultsFile""))
|
||||
}
|
||||
|
||||
if ($Env:COVERALLS_REPO_TOKEN) {
|
||||
$revision = git rev-parse HEAD
|
||||
$branch = git rev-parse --abbrev-ref HEAD
|
||||
$commitAuthor = git show --quiet --format="%aN" $revision
|
||||
$commitEmail = git show --quiet --format="%aE" $revision
|
||||
$commitMessage = git show --quiet --format="%s" $revision
|
||||
|
||||
.\packages\coveralls.net.0.7.0\tools\csmacnz.Coveralls.exe `
|
||||
--opencover -i opencover.xml `
|
||||
--repoToken "$Env:COVERALLS_REPO_TOKEN" `
|
||||
--commitId "$revision" `
|
||||
--commitBranch "$branch" `
|
||||
--commitAuthor "$commitAuthor" `
|
||||
--commitEmail "$commitEmail" `
|
||||
--commitMessage "$commitMessage" `
|
||||
--useRelativePaths `
|
||||
--basePath .\Duplicati\UnitTest\bin\Debug
|
||||
}
|
||||
|
||||
if (!$testsPassed) {
|
||||
throw "Tests failed."
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
*.csproj text
|
||||
*.sh text eol=lf
|
||||
#The #! in rules won't work if CRLF
|
||||
/ReleaseBuilder/Resources/debian/* text eol=lf
|
||||
/ReleaseBuilder/Resources/fedora/*.sh text eol=lf
|
||||
@@ -1,105 +0,0 @@
|
||||
name: Build release installers
|
||||
|
||||
on:
|
||||
workflow_dispatch
|
||||
|
||||
env:
|
||||
build_directory: "Duplicati/GUI/Duplicati.GUI.TrayIcon/bin/Release"
|
||||
|
||||
jobs:
|
||||
macbuild:
|
||||
name: mac build and installers
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Install NuGet
|
||||
uses: nuget/setup-nuget@v1.1.1
|
||||
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Restore NuGet Packages
|
||||
run: |
|
||||
nuget restore Duplicati.sln
|
||||
nuget restore "BuildTools/UpdateVersionStamp/UpdateVersionStamp.sln"
|
||||
|
||||
- name: Build Duplicati (macOS)
|
||||
run: |
|
||||
msbuild /property:Configuration=Release "BuildTools/UpdateVersionStamp/UpdateVersionStamp.sln"
|
||||
RELEASE_TIMESTAMP=$(date +%Y-%m-%d)
|
||||
RELEASE_TYPE="canary"
|
||||
RELEASE_INC_VERSION=$(cat Updates/build_version.txt)
|
||||
RELEASE_INC_VERSION=$((RELEASE_INC_VERSION+1))
|
||||
RELEASE_VERSION="2.0.7.${RELEASE_INC_VERSION}"
|
||||
RELEASE_NAME="${RELEASE_VERSION}_${RELEASE_TYPE}_${RELEASE_TIMESTAMP}"
|
||||
echo "${RELEASE_NAME}" > "Duplicati/License/VersionTag.txt"
|
||||
echo "${RELEASE_TYPE}" > "Duplicati/Library/AutoUpdater/AutoUpdateBuildChannel.txt"
|
||||
mono "BuildTools/UpdateVersionStamp/bin/Release/UpdateVersionStamp.exe" --version="${RELEASE_VERSION}"
|
||||
msbuild -p:DefineConstants=\"ENABLE_GTK\;XAMARIN_MAC\" -p:Configuration=Release Duplicati.sln
|
||||
|
||||
- name: Build installers (OSX)
|
||||
run: |
|
||||
Installer/OSX/artifact_mac.sh
|
||||
|
||||
- name: Upload build results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
retention-days: 5
|
||||
name: build-results-mac
|
||||
path: ~/artifacts/**/*
|
||||
|
||||
windowsbuild:
|
||||
name: windows installer
|
||||
runs-on: windows-latest
|
||||
needs: macbuild
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.3
|
||||
- name: Install NuGet
|
||||
uses: nuget/setup-nuget@v1.1.1
|
||||
- uses: actions/checkout@v3
|
||||
- name: Retrieve mac build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-results-mac
|
||||
path: ~/macartifacts
|
||||
- name: set env
|
||||
run: echo "ZIPBUILDFILE=$(resolve-path ~ | select-object -expandproperty path)\macartifacts\$(get-childitem ~\macartifacts\*.zip | select-object -first 1 -expandproperty name )" >> $env:GITHUB_ENV
|
||||
- name: Build installers (Windows)
|
||||
run: |
|
||||
echo ${{ env.ZIPBUILDFILE }}
|
||||
.\\Installer\\Windows\\artifact_win.bat ${{ env.ZIPBUILDFILE }}
|
||||
- name: Upload build results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
retention-days: 5
|
||||
name: build-results-windows
|
||||
path: ~/artifacts/**/*
|
||||
|
||||
debianbuild:
|
||||
name: debian like installer
|
||||
runs-on: ubuntu-latest
|
||||
needs: macbuild
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Retrieve mac build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-results-mac
|
||||
path: ~/macartifacts
|
||||
- name: set env
|
||||
run: echo "ZIPBUILDFILE=$(ls ~/macartifacts/*.zip | tail -1)" >> $GITHUB_ENV
|
||||
- name: Build installers (Deb)
|
||||
run: |
|
||||
echo ${{ env.ZIPBUILDFILE }}
|
||||
sudo apt install debhelper
|
||||
Installer/debian/artifact_deb.sh ${{ env.ZIPBUILDFILE }}
|
||||
- name: Upload build results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
retention-days: 5
|
||||
name: build-results-linux
|
||||
path: ~/artifacts/**/*
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
name: Build release installers from PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ labeled ]
|
||||
|
||||
env:
|
||||
build_directory: "Duplicati/GUI/Duplicati.GUI.TrayIcon/bin/Release"
|
||||
|
||||
jobs:
|
||||
macbuild:
|
||||
if: ${{ github.event.label.name == 'testbuild' }}
|
||||
name: mac build and installers
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
|
||||
steps:
|
||||
- name: Install NuGet
|
||||
uses: nuget/setup-nuget@v1.1.1
|
||||
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Restore NuGet Packages
|
||||
run: |
|
||||
nuget restore Duplicati.sln
|
||||
nuget restore "BuildTools/UpdateVersionStamp/UpdateVersionStamp.sln"
|
||||
|
||||
- name: Build Duplicati (macOS)
|
||||
run: |
|
||||
msbuild /property:Configuration=Release "BuildTools/UpdateVersionStamp/UpdateVersionStamp.sln"
|
||||
RELEASE_TIMESTAMP=$(date +%Y-%m-%d)
|
||||
RELEASE_TYPE="canary"
|
||||
RELEASE_INC_VERSION=$(cat Updates/build_version.txt)
|
||||
RELEASE_INC_VERSION=$((RELEASE_INC_VERSION+1))
|
||||
RELEASE_VERSION="2.0.7.${RELEASE_INC_VERSION}"
|
||||
RELEASE_NAME="${RELEASE_VERSION}_${RELEASE_TYPE}_${RELEASE_TIMESTAMP}"
|
||||
echo "${RELEASE_NAME}" > "Duplicati/License/VersionTag.txt"
|
||||
echo "${RELEASE_TYPE}" > "Duplicati/Library/AutoUpdater/AutoUpdateBuildChannel.txt"
|
||||
mono "BuildTools/UpdateVersionStamp/bin/Release/UpdateVersionStamp.exe" --version="${RELEASE_VERSION}"
|
||||
msbuild -p:DefineConstants=\"ENABLE_GTK\;XAMARIN_MAC\" -p:Configuration=Release Duplicati.sln
|
||||
|
||||
- name: Build installers (OSX)
|
||||
run: |
|
||||
Installer/OSX/artifact_mac.sh
|
||||
|
||||
- name: Upload build results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
retention-days: 5
|
||||
name: build-results-mac
|
||||
path: ~/artifacts/**/*
|
||||
|
||||
windowsbuild:
|
||||
name: windows installer
|
||||
runs-on: windows-latest
|
||||
needs: macbuild
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.3
|
||||
- name: Install NuGet
|
||||
uses: nuget/setup-nuget@v1.1.1
|
||||
- uses: actions/checkout@v3
|
||||
- name: Retrieve mac build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-results-mac
|
||||
path: ~/macartifacts
|
||||
- name: set env
|
||||
run: echo "ZIPBUILDFILE=$(resolve-path ~ | select-object -expandproperty path)\macartifacts\$(get-childitem ~\macartifacts\*.zip | select-object -first 1 -expandproperty name )" >> $env:GITHUB_ENV
|
||||
- name: Build installers (Windows)
|
||||
run: |
|
||||
echo ${{ env.ZIPBUILDFILE }}
|
||||
.\\Installer\\Windows\\artifact_win.bat ${{ env.ZIPBUILDFILE }}
|
||||
- name: Upload build results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
retention-days: 5
|
||||
name: build-results-windows
|
||||
path: ~/artifacts/**/*
|
||||
|
||||
debianbuild:
|
||||
name: debian like installer
|
||||
runs-on: ubuntu-latest
|
||||
needs: macbuild
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Retrieve mac build
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: build-results-mac
|
||||
path: ~/macartifacts
|
||||
- name: set env
|
||||
run: echo "ZIPBUILDFILE=$(ls ~/macartifacts/*.zip | tail -1)" >> $GITHUB_ENV
|
||||
- name: Build installers (Deb)
|
||||
run: |
|
||||
echo ${{ env.ZIPBUILDFILE }}
|
||||
sudo apt install debhelper
|
||||
Installer/debian/artifact_deb.sh ${{ env.ZIPBUILDFILE }}
|
||||
- name: Upload build results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
retention-days: 5
|
||||
name: build-results-linux
|
||||
path: ~/artifacts/**/*
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
name: Freebsd
|
||||
on:
|
||||
push:
|
||||
branches: "**freebsd**"
|
||||
pull_request:
|
||||
branches: "**freebsd**"
|
||||
|
||||
jobs:
|
||||
zip:
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Download dotnet
|
||||
# See also https://github.com/sec/dotnet-core-freebsd-source-build
|
||||
# See also https://github.com/Thefrank/dotnet-freebsd-crossbuild
|
||||
run: curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/v6.0.401-11/dotnet-sdk-6.0.401-freebsd-x64.tar.gz -o dn.tgz
|
||||
- name: Build
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
with:
|
||||
usesh: true
|
||||
# sync: sshfs
|
||||
prepare: pkg install -y curl libinotify libunwind git cmake ninja bash wget icu
|
||||
run: |
|
||||
#!/bin/bash
|
||||
set -x
|
||||
set -e
|
||||
pwd
|
||||
ls -lah
|
||||
whoami
|
||||
env
|
||||
freebsd-version
|
||||
df -h
|
||||
dmesg | grep memory
|
||||
swapinfo
|
||||
dd if=/dev/zero of=/root/swap1 bs=1m count=20480
|
||||
chmod 0600 /root/swap1
|
||||
mdconfig -a -t vnode -f /root/swap1 -u 0
|
||||
swapon /dev/md0
|
||||
df -h
|
||||
swapinfo
|
||||
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||
BUILD_DIR=`pwd`
|
||||
cd /var/tmp
|
||||
mkdir dn
|
||||
cd dn
|
||||
echo Unpacking .NET
|
||||
tar -xzf ${BUILD_DIR}/dn.tgz
|
||||
cd ${BUILD_DIR}
|
||||
mkdir /var/tmp/nuget
|
||||
export RVERSION=v6.0.401-11
|
||||
export VERSION=6.0.9
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.AspNetCore.App.Runtime.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.AspNetCore.App.Runtime.freebsd-x64.${VERSION}.nupkg
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.NETCore.App.Host.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.NETCore.App.Host.freebsd-x64.${VERSION}.nupkg
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.NETCore.App.Runtime.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.NETCore.App.Runtime.freebsd-x64.${VERSION}.nupkg
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.NETCore.App.Crossgen2.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.NETCore.App.Crossgen2.freebsd-x64.${VERSION}.nupkg
|
||||
/var/tmp/dn/dotnet nuget add source /var/tmp/nuget/
|
||||
|
||||
cp -R `pwd` /var/tmp/build
|
||||
cd /var/tmp/build
|
||||
|
||||
echo Restore
|
||||
/var/tmp/dn/dotnet restore --runtime=freebsd-x64 Duplicati.sln
|
||||
echo Build
|
||||
/var/tmp/dn/dotnet build Duplicati.sln
|
||||
echo Publish
|
||||
/var/tmp/dn/dotnet publish -c Release --runtime=freebsd-x64 -o publish Duplicati.sln
|
||||
|
||||
cp -R ./publish ${BUILD_DIR}/publish
|
||||
- name: Save Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: duplicati-freebsd-x64
|
||||
path: publish
|
||||
tests:
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Download dotnet
|
||||
# See also https://github.com/sec/dotnet-core-freebsd-source-build
|
||||
# See also https://github.com/Thefrank/dotnet-freebsd-crossbuild
|
||||
run: curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/v6.0.401-11/dotnet-sdk-6.0.401-freebsd-x64.tar.gz -o dn.tgz
|
||||
- name: Run test
|
||||
id: test
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
with:
|
||||
usesh: true
|
||||
# sync: sshfs
|
||||
prepare: pkg install -y curl libinotify libunwind git cmake ninja bash wget icu
|
||||
run: |
|
||||
#!/bin/bash
|
||||
set -x
|
||||
set -e
|
||||
pwd
|
||||
ls -lah
|
||||
whoami
|
||||
env
|
||||
freebsd-version
|
||||
df -h
|
||||
dmesg | grep memory
|
||||
swapinfo
|
||||
dd if=/dev/zero of=/root/swap1 bs=1m count=20480
|
||||
chmod 0600 /root/swap1
|
||||
mdconfig -a -t vnode -f /root/swap1 -u 0
|
||||
swapon /dev/md0
|
||||
df -h
|
||||
swapinfo
|
||||
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||
BUILD_DIR=`pwd`
|
||||
cd /var/tmp
|
||||
mkdir dn
|
||||
cd dn
|
||||
echo Unpacking .NET
|
||||
tar -xzf ${BUILD_DIR}/dn.tgz
|
||||
cd ${BUILD_DIR}
|
||||
mkdir /var/tmp/nuget
|
||||
export RVERSION=v6.0.401-11
|
||||
export VERSION=6.0.9
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.AspNetCore.App.Runtime.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.AspNetCore.App.Runtime.freebsd-x64.${VERSION}.nupkg
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.NETCore.App.Host.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.NETCore.App.Host.freebsd-x64.${VERSION}.nupkg
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.NETCore.App.Runtime.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.NETCore.App.Runtime.freebsd-x64.${VERSION}.nupkg
|
||||
curl -L https://github.com/Thefrank/dotnet-freebsd-crossbuild/releases/download/${RVERSION}/Microsoft.NETCore.App.Crossgen2.freebsd-x64.${VERSION}.nupkg -o /var/tmp/nuget/Microsoft.NETCore.App.Crossgen2.freebsd-x64.${VERSION}.nupkg
|
||||
/var/tmp/dn/dotnet nuget add source /var/tmp/nuget/
|
||||
|
||||
cp -R `pwd` /var/tmp/build
|
||||
cd /var/tmp/build
|
||||
|
||||
echo Restore
|
||||
/var/tmp/dn/dotnet restore --runtime=freebsd-x64 Duplicati.sln
|
||||
echo Testing
|
||||
mkdir -p ${BUILD_DIR}/duplicati_testdata/logs
|
||||
mkdir -p /var/tmp/duplicati_testdata
|
||||
ln -s ${BUILD_DIR}/duplicati_testdata/logs /var/tmp/duplicati_testdata/logs
|
||||
export UNITTEST_BASEFOLDER=/var/tmp/duplicati_testdata
|
||||
/var/tmp/dn/dotnet test --runtime=freebsd-x64 --verbosity minimal Duplicati.sln
|
||||
- name: Archive Test Logs
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: test-logs
|
||||
path: duplicati_testdata/logs/*
|
||||
@@ -8,8 +8,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
actions: write
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-issue-stale: 15
|
||||
days-before-issue-close: 15
|
||||
@@ -22,4 +23,4 @@ jobs:
|
||||
only-labels: "pending user feedback"
|
||||
exempt-issue-labels: "bug,enhancement,good first issue,backend enhancement,backend issue,backup corruption,bounty,bugreport attached,core logic,docker,filters,help wanted,linux,localization,MacOS,mono,performance issue,reproduced,server side,ssl/tls issue,Synology,tests,translation,UI,windows"
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
operations-per-run: 500
|
||||
|
||||
+17
-75
@@ -2,9 +2,6 @@ name: Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
build_directory: "Duplicati/GUI/Duplicati.GUI.TrayIcon/bin/Release"
|
||||
|
||||
jobs:
|
||||
unit_tests:
|
||||
name: Unit tests
|
||||
@@ -12,84 +9,29 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
- name: Add msbuild to PATH (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.x
|
||||
|
||||
- name: Install NuGet
|
||||
uses: nuget/setup-nuget@v1
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v3
|
||||
- name: Restore NuGet dependencies
|
||||
run: dotnet restore Duplicati.sln
|
||||
|
||||
- name: Restore NuGet Packages
|
||||
run: nuget restore Duplicati.sln
|
||||
- name: Build Duplicati
|
||||
run: dotnet build --no-restore Duplicati.sln
|
||||
|
||||
- name: Install Additional Dependencies
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: sudo apt-get install gtk-sharp2
|
||||
- name: Run unit tests
|
||||
run: dotnet test --no-build --verbosity minimal Duplicati.sln
|
||||
|
||||
- name: Build Duplicati (Linux and macOS)
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: msbuild -p:Configuration=Release -p:DefineConstants=ENABLE_GTK Duplicati.sln
|
||||
|
||||
- name: Build Duplicati (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: msbuild -p:Configuration=Release Duplicati.sln
|
||||
|
||||
- name: Run Unit Tests (Linux and macOS)
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: |
|
||||
export DEBUG_OUTPUT=1
|
||||
nuget install NUnit.Runners -Version 3.12.0 -OutputDirectory nunit
|
||||
mono nunit/NUnit.ConsoleRunner.3.12.0/tools/nunit3-console.exe Duplicati/UnitTest/bin/Release/Duplicati.UnitTest.dll
|
||||
|
||||
- name: Run Unit Tests (Windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
run: |
|
||||
nuget install NUnit.Runners -Version 3.12.0 -OutputDirectory nunit
|
||||
nunit/NUnit.ConsoleRunner.3.12.0/tools/nunit3-console.exe Duplicati/UnitTest/bin/Release/Duplicati.UnitTest.dll
|
||||
|
||||
ui_tests:
|
||||
name: UI tests
|
||||
selenium:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Some of these steps duplicate those in the unit_tests job above. This
|
||||
# can be cleaned up using a composite run steps action once it supports
|
||||
# what we need (https://github.com/actions/runner/issues/646).
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install NuGet
|
||||
uses: nuget/setup-nuget@v1
|
||||
|
||||
- name: Restore NuGet Packages
|
||||
run: nuget restore Duplicati.sln
|
||||
|
||||
- name: Install Additional Dependencies
|
||||
run: sudo apt-get install gtk-sharp2
|
||||
|
||||
- name: Build Duplicati
|
||||
run: msbuild -p:Configuration=Release -p:DefineConstants=ENABLE_GTK Duplicati.sln
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip3 install selenium
|
||||
pip3 install --upgrade urllib3
|
||||
pip3 install chromedriver-autoinstaller
|
||||
|
||||
- name: Run UI tests
|
||||
run: |
|
||||
cp -r Duplicati/Server/webroot "${{ env.build_directory }}"/webroot
|
||||
mono "${{ env.build_directory }}"/Duplicati.Server.exe &
|
||||
sleep 30
|
||||
python3 guiTests/guiTest.py --use-chrome
|
||||
- uses: actions/checkout@v4
|
||||
- name: Selenium
|
||||
run: pipeline/selenium/test.sh
|
||||
|
||||
+3
-10
@@ -4,24 +4,17 @@ obj/
|
||||
*.userprefs
|
||||
*.user
|
||||
*.suo
|
||||
Installer/Paraffin.exe
|
||||
Installer/account_info
|
||||
Duplicati/Localization/compiled
|
||||
Duplicati/Localization/*/
|
||||
Duplicati/Localization/*.diff.csv
|
||||
Duplicati/Localization/*.new.csv
|
||||
Duplicati/Localization/*.updated.csv
|
||||
Duplicati/Localization/report.*.xml
|
||||
Installer/incLocFiles.*.wxs
|
||||
Duplicati/Server/webroot/extjs-*
|
||||
Installer/binfiles.wxs
|
||||
Installer/generated-keys.xml
|
||||
Installer/oem
|
||||
Updates/build
|
||||
packages
|
||||
changelog-news.txt
|
||||
binfiles.wxs
|
||||
.idea/
|
||||
.vs/
|
||||
|
||||
Installer/debian/*.buildinfo
|
||||
/publish/
|
||||
ReleaseBuilder/build-temp/
|
||||
ReleaseBuilder/Resources/Windows/binfiles.wxs
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
language: minimal
|
||||
services: docker
|
||||
before_install:
|
||||
- sudo apt-get install moreutils
|
||||
- set -o pipefail
|
||||
addons:
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "duplicati/duplicati"
|
||||
description: "Duplicati Build submitted via Travis CI"
|
||||
notification_email: kenneth@duplicati.com
|
||||
build_command_prepend: "msbuild /t:Clean"
|
||||
build_command: "msbuild /t:Rebuild"
|
||||
branch_pattern: coverity_scan
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: "ijaQDcVcMo/utuP514FiDZVGR5LJbATWmYDmgRIIaI0YG2Rk6uuJp9XXDXr8sx66JWttPGgs7Htqfy50VKHdr7nsfyCQCRNGmqF+OJeUgAQMj5spxn9A7PZY9+GVhnXoJ06wvYjCv5MPeLBMDK/KpIM5Ny5IG+TKzQy4U7Dyg0riMUT61aqzxSjTGfHZPmaqBICJTzsRmeGHglemFUz/1B4NAN+IeAtXoH9YIfA2LjJfYmMLckPgFQLKN/tQRaGPWXh77y0qVgA++K8UVu5W3yGo3JXBPDdabGgKs9BPlfN5/Ixnkcy6ekAubDA/Aspur9x7/szj4/AnGMY6frNB33nQcnJQZ/51GYKr6CXCmjoJQuWc8ZKdEMqDn3w/kyEzvluSjAsJNRVboeWPE4VfpAeUBsjQ+TuEQi8WXhN8VJgZV7yCkVlZTVbhtOxMPsBiFb74lpWC2iQuWLJv9ED6vyXZVzZhNtfjXNXNZzIwYxbcd7I0ZQ8fmDstFnvBJveJby2ZRpECXTbc03eIUq1SAaVJJY2r47RD1PwVqM3xvUTljIqtKdyIz915mEOjqG1BnCDaiGHYJ4byuDDeIUZO9X70s60Gh4hupZA2Ruup0v7SfYgkto6aNcStd0NYd716Vd7hqXNTp6nu01L5YYJDY4h5sHyBXVXbxCKlUb01kUw="
|
||||
- USAGEREPORTER_Duplicati_LEVEL=none
|
||||
- AUTOUPDATER_Duplicati_SKIP_UPDATE=1
|
||||
- BUILD_DIR=${TRAVIS_BUILD_DIR}/../.build
|
||||
- TEST_DIR=${TRAVIS_BUILD_DIR}/../.test
|
||||
- ROOT_DIR="$TRAVIS_BUILD_DIR"
|
||||
|
||||
# matrix expansion within jobs would be good:
|
||||
# https://github.com/travis-ci/travis-ci/issues/8295
|
||||
|
||||
# There is one cache per branch, so concurrent builds on different branches possible!
|
||||
# DO NOT SET ENVIRONMENT VARIABLES WITHIN JOBS, OR CACHES WILL NOT BE SHARED AMONGST JOBS!
|
||||
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: build
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- ${ROOT_DIR}/pipeline/jobs/build_job.sh
|
||||
|
||||
|
||||
- stage: tests
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories BulkNormal
|
||||
- stage: tests
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories BulkNoSize
|
||||
- stage: tests
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories SVNDataLong,SVNData,RecoveryTool,ProblematicPath,SymLink
|
||||
- stage: tests
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- travis_wait ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories Border
|
||||
- stage: tests
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- ${ROOT_DIR}/pipeline/jobs/unittest_job.sh --testcategories Filter,Targeted,Purge,Serialization,WebApi,Utility,UriUtility,IO,ImportExport,Disruption,RestoreHandler,RepairHandler,DeleteHandler,Controller
|
||||
|
||||
- stage: tests
|
||||
cache:
|
||||
directories:
|
||||
- $BUILD_DIR
|
||||
script:
|
||||
- ${ROOT_DIR}/pipeline/jobs/selenium_job.sh
|
||||
addons:
|
||||
sauce_connect:
|
||||
username: $SAUCE_USERNAME
|
||||
access_key: $SAUCE_ACCESS_KEY
|
||||
Vendored
+81
@@ -0,0 +1,81 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch TrayIcon executable",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Executables/net8/Duplicati.GUI.TrayIcon/bin/Debug/net8.0/Duplicati.GUI.TrayIcon",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Launch Server executable",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Executables/net8/Duplicati.Server/bin/Debug/net8.0/Duplicati.Server",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Launch CommandLine executable",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine/bin/Debug/net8.0/Duplicati.CommandLine",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Launch AutoUpdater executable",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine.AutoUpdater/bin/Debug/net8.0/Duplicati.CommandLine.AutoUpdater",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Launch ConfigurationImporter executable",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine.ConfigurationImporter/bin/Debug/net8.0/Duplicati.CommandLine.ConfigurationImporter",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "Launch RecoveryTool executable",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/Executables/net8/Duplicati.CommandLine.RecoveryTool/bin/Debug/net8.0/Duplicati.CommandLine.RecoveryTool",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole"
|
||||
},
|
||||
{
|
||||
"name": "C#: Duplicati.GUI.TrayIcon Debug",
|
||||
"type": "dotnet",
|
||||
"request": "launch",
|
||||
"projectPath": "${workspaceFolder}/Executables/net8/Duplicati.GUI.TrayIcon/Duplicati.GUI.TrayIcon.csproj"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"build",
|
||||
// Ask dotnet build to generate full paths for file names.
|
||||
"/property:GenerateFullPaths=true",
|
||||
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{17E3EB29-87FD-4BE9-A531-8DAD8B295494}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<RootNamespace>AutoUpdateBuilder</RootNamespace>
|
||||
<AssemblyName>AutoUpdateBuilder</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Compression\Duplicati.Library.Compression.csproj">
|
||||
<Project>{19ECCE09-B5EB-406C-8C57-BAC66997D469}</Project>
|
||||
<Name>Duplicati.Library.Compression</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj">
|
||||
<Project>{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}</Project>
|
||||
<Name>Duplicati.Library.Encryption</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Interface\Duplicati.Library.Interface.csproj">
|
||||
<Project>{C5899F45-B0FF-483C-9D38-24A9FCAAB237}</Project>
|
||||
<Name>Duplicati.Library.Interface</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Logging\Duplicati.Library.Logging.csproj">
|
||||
<Project>{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}</Project>
|
||||
<Name>Duplicati.Library.Logging</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj">
|
||||
<Project>{7E119745-1F62-43F0-936C-F312A1912C0B}</Project>
|
||||
<Name>Duplicati.Library.AutoUpdater</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\License\Duplicati.License.csproj">
|
||||
<Project>{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}</Project>
|
||||
<Name>Duplicati.License</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,74 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoUpdateBuilder", "AutoUpdateBuilder.csproj", "{17E3EB29-87FD-4BE9-A531-8DAD8B295494}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Compression", "..\..\Duplicati\Library\Compression\Duplicati.Library.Compression.csproj", "{19ECCE09-B5EB-406C-8C57-BAC66997D469}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Utility", "..\..\Duplicati\Library\Utility\Duplicati.Library.Utility.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Interface", "..\..\Duplicati\Library\Interface\Duplicati.Library.Interface.csproj", "{C5899F45-B0FF-483C-9D38-24A9FCAAB237}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Logging", "..\..\Duplicati\Library\Logging\Duplicati.Library.Logging.csproj", "{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Encryption", "..\..\Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj", "{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.AutoUpdater", "..\..\Duplicati\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj", "{7E119745-1F62-43F0-936C-F312A1912C0B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.License", "..\..\Duplicati\License\Duplicati.License.csproj", "{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Localization", "..\..\Duplicati\Library\Localization\Duplicati.Library.Localization.csproj", "{B68F2214-951F-4F78-8488-66E1ED3F50BF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Common", "..\..\Duplicati\Library\Common\Duplicati.Library.Common.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{17E3EB29-87FD-4BE9-A531-8DAD8B295494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{17E3EB29-87FD-4BE9-A531-8DAD8B295494}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{17E3EB29-87FD-4BE9-A531-8DAD8B295494}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{17E3EB29-87FD-4BE9-A531-8DAD8B295494}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = AutoUpdateBuilder.csproj
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,184 +0,0 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace AutoUpdateBuilder
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static RSACryptoServiceProvider privkey;
|
||||
|
||||
private static string keyfile;
|
||||
private static string keyfilepassword;
|
||||
|
||||
private static void CompareToManifestPublicKey()
|
||||
{
|
||||
if (Duplicati.Library.AutoUpdater.AutoUpdateSettings.SignKey == null || privkey.ToXmlString(false) != Duplicati.Library.AutoUpdater.AutoUpdateSettings.SignKey.ToXmlString(false))
|
||||
{
|
||||
Console.WriteLine("The public key in the project is not the same as the public key from the file");
|
||||
Console.WriteLine("Try setting the key to: ");
|
||||
Console.WriteLine(privkey.ToXmlString(false));
|
||||
System.Environment.Exit(5);
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadKeyFromFile()
|
||||
{
|
||||
using (var enc = new Duplicati.Library.Encryption.AESEncryption(keyfilepassword, new Dictionary<string, string>()))
|
||||
using (var ms = new System.IO.MemoryStream())
|
||||
using (var fs = System.IO.File.OpenRead(keyfile))
|
||||
{
|
||||
enc.Decrypt(fs, ms);
|
||||
ms.Position = 0;
|
||||
|
||||
using (var sr = new System.IO.StreamReader(ms))
|
||||
privkey.FromXmlString(sr.ReadToEnd());
|
||||
}
|
||||
}
|
||||
|
||||
public static int Main(string[] _args)
|
||||
{
|
||||
var args = new List<string>(_args);
|
||||
var opts = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args);
|
||||
|
||||
opts.TryGetValue("input", out string inputfolder);
|
||||
opts.TryGetValue("output", out string outputfolder);
|
||||
opts.TryGetValue("allow-new-key", out string allowNewKey);
|
||||
opts.TryGetValue("keyfile", out keyfile);
|
||||
opts.TryGetValue("manifest", out string manifestfile);
|
||||
opts.TryGetValue("keyfile-password", out keyfilepassword);
|
||||
|
||||
var usedoptions = new [] { "allow-new-key", "input", "output", "keyfile", "manifest", "keyfile-password" };
|
||||
|
||||
if (string.IsNullOrWhiteSpace(inputfolder))
|
||||
{
|
||||
Console.WriteLine("Missing input folder");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(outputfolder))
|
||||
{
|
||||
Console.WriteLine("Missing output folder");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(keyfile))
|
||||
{
|
||||
Console.WriteLine("Missing keyfile");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (!System.IO.Directory.Exists(inputfolder))
|
||||
{
|
||||
Console.WriteLine("Input folder not found");
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(keyfilepassword))
|
||||
{
|
||||
Console.WriteLine("Enter keyfile passphrase: ");
|
||||
keyfilepassword = Console.ReadLine().Trim();
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists(keyfile))
|
||||
{
|
||||
Console.WriteLine("Keyfile not found, creating new");
|
||||
var newkey = RSA.Create().ToXmlString(true);
|
||||
using (var enc = new Duplicati.Library.Encryption.AESEncryption(keyfilepassword, new Dictionary<string, string>()))
|
||||
using (var fs = System.IO.File.OpenWrite(keyfile))
|
||||
using (var ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(newkey)))
|
||||
enc.Encrypt(ms, fs);
|
||||
}
|
||||
|
||||
if (!System.IO.Directory.Exists(outputfolder))
|
||||
System.IO.Directory.CreateDirectory(outputfolder);
|
||||
|
||||
privkey = (RSACryptoServiceProvider) RSA.Create();
|
||||
|
||||
LoadKeyFromFile();
|
||||
|
||||
if (!Boolean.TryParse(allowNewKey, out Boolean newKeyAllowed) || !newKeyAllowed)
|
||||
{
|
||||
CompareToManifestPublicKey();
|
||||
}
|
||||
|
||||
Duplicati.Library.AutoUpdater.UpdateInfo updateInfo;
|
||||
|
||||
using (var fs = System.IO.File.OpenRead(manifestfile))
|
||||
using (var sr = new System.IO.StreamReader(fs))
|
||||
using (var jr = new Newtonsoft.Json.JsonTextReader(sr))
|
||||
updateInfo = new Newtonsoft.Json.JsonSerializer().Deserialize<Duplicati.Library.AutoUpdater.UpdateInfo>(jr);
|
||||
|
||||
var isopts = new Dictionary<string, string>(opts, StringComparer.InvariantCultureIgnoreCase);
|
||||
foreach (var usedopt in usedoptions)
|
||||
{
|
||||
isopts.Remove(usedopt);
|
||||
}
|
||||
|
||||
foreach (var k in updateInfo.GetType().GetFields())
|
||||
{
|
||||
if (!isopts.ContainsKey(k.Name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
//Console.WriteLine("Setting {0} to {1}", k.Name, isopts[k.Name]);
|
||||
if (k.FieldType == typeof(string[]))
|
||||
k.SetValue(updateInfo, isopts[k.Name].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
|
||||
else if (k.FieldType == typeof(Version))
|
||||
k.SetValue(updateInfo, new Version(isopts[k.Name]));
|
||||
else if (k.FieldType == typeof(int))
|
||||
k.SetValue(updateInfo, int.Parse(isopts[k.Name]));
|
||||
else if (k.FieldType == typeof(long))
|
||||
k.SetValue(updateInfo, long.Parse(isopts[k.Name]));
|
||||
else
|
||||
k.SetValue(updateInfo, isopts[k.Name]);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Failed setting {0} to {1}: {2}", k.Name, isopts[k.Name], ex.Message);
|
||||
}
|
||||
|
||||
isopts.Remove(k.Name);
|
||||
}
|
||||
|
||||
foreach (var opt in isopts)
|
||||
{
|
||||
Console.WriteLine("Warning! unused option: {0} = {1}", opt.Key, opt.Value);
|
||||
}
|
||||
|
||||
using (var tf = new Duplicati.Library.Utility.TempFile())
|
||||
{
|
||||
using (var fs = System.IO.File.OpenWrite(tf))
|
||||
using (var tw = new System.IO.StreamWriter(fs))
|
||||
new Newtonsoft.Json.JsonSerializer().Serialize(tw, updateInfo);
|
||||
|
||||
Duplicati.Library.AutoUpdater.UpdaterManager.CreateUpdatePackage(privkey, inputfolder, outputfolder, tf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("AutoUpdateBuilder")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/></startup></configuration>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.2" targetFramework="net471" />
|
||||
</packages>
|
||||
@@ -1,59 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProjectGuid>{3E891818-579A-4C06-8066-4C702BFA5921}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<RootNamespace>DependencyFinder</RootNamespace>
|
||||
<AssemblyName>DependencyFinder</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<Commandlineparameters>../../../../Duplicati/GUI/Duplicati.GUI.TrayIcon/bin/Debug</Commandlineparameters>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Cecil, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Mdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Mdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Pdb, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Pdb.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mono.Cecil.Rocks, Version=0.9.6.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Mono.Cecil.0.9.6.4\lib\net45\Mono.Cecil.Rocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,17 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyFinder", "DependencyFinder.csproj", "{3E891818-579A-4C06-8066-4C702BFA5921}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3E891818-579A-4C06-8066-4C702BFA5921}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{3E891818-579A-4C06-8066-4C702BFA5921}.Debug|x86.Build.0 = Debug|x86
|
||||
{3E891818-579A-4C06-8066-4C702BFA5921}.Release|x86.ActiveCfg = Release|x86
|
||||
{3E891818-579A-4C06-8066-4C702BFA5921}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,85 +0,0 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace DependencyFinder
|
||||
{
|
||||
class MainClass
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var lst =
|
||||
Directory.EnumerateFiles(args[0], "*.exe", SearchOption.AllDirectories).Union(
|
||||
Directory.EnumerateFiles(args[0], "*.dll", SearchOption.AllDirectories))
|
||||
.Select(x => {
|
||||
try { return AssemblyDefinition.ReadAssembly(x); }
|
||||
catch { return null; }
|
||||
}).Where(x => x != null)
|
||||
.Distinct();
|
||||
|
||||
PoC(lst, Console.Out, new [] { args[0] });
|
||||
|
||||
}
|
||||
|
||||
//Adapted from: https://stackoverflow.com/questions/9262464/tool-to-show-assembly-dependencies
|
||||
public static void PoC(IEnumerable<AssemblyDefinition> assemblies, TextWriter writer, IEnumerable<string> searchfolders)
|
||||
{
|
||||
var resolver = new DefaultAssemblyResolver();
|
||||
searchfolders.ToList().ForEach(x => resolver.AddSearchDirectory(x));
|
||||
|
||||
//writer.WriteLine("digraph Dependencies {");
|
||||
var loaded = assemblies
|
||||
.SelectMany(a => a.Modules.Cast<ModuleDefinition>())
|
||||
.SelectMany(m => m.AssemblyReferences.Cast<AssemblyNameReference>())
|
||||
.Distinct()
|
||||
.Select(asm => {
|
||||
var dllname = asm.Name + ".dll";
|
||||
//Console.WriteLine("Probing for {0}", dllname);
|
||||
try { return AssemblyDefinition.ReadAssembly(dllname); }
|
||||
catch { }
|
||||
try { return resolver.Resolve(asm.FullName); }
|
||||
catch { }
|
||||
|
||||
return null;
|
||||
})
|
||||
.Where(assembly => assembly != null)
|
||||
.ToList();
|
||||
|
||||
//loaded.ForEach(a => a.MainModule.ReadSymbols());
|
||||
|
||||
loaded.Select(x => x.FullName).Distinct().OrderBy(x => x).ToList().ForEach(x => writer.WriteLine("{0}", x));
|
||||
/*loaded.ForEach(a =>
|
||||
{
|
||||
foreach (var r in a.MainModule.AssemblyReferences.Cast<AssemblyNameReference>())
|
||||
writer.WriteLine(@"""{0}"" -> ""{1}"";", r.Name, a.Name.Name);
|
||||
} );*/
|
||||
|
||||
//writer.WriteLine("}");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("DependencyFinder")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("kenneth")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/></startup></configuration>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Mono.Cecil" version="0.9.6.4" targetFramework="net471" />
|
||||
</packages>
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProjectGuid>{72B910F2-8E80-4955-A0D6-ED4C35CEE665}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>GnupgSigningTool</RootNamespace>
|
||||
<AssemblyName>GnupgSigningTool</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj">
|
||||
<Project>{2cf2d90e-c25b-47ad-91e0-98451bab8058}</Project>
|
||||
<Name>Duplicati.Library.Encryption</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Interface\Duplicati.Library.Interface.csproj">
|
||||
<Project>{C5899F45-B0FF-483C-9D38-24A9FCAAB237}</Project>
|
||||
<Name>Duplicati.Library.Interface</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,42 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29123.88
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GnupgSigningTool", "GnupgSigningTool.csproj", "{72B910F2-8E80-4955-A0D6-ED4C35CEE665}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Utility", "..\..\Duplicati\Library\Utility\Duplicati.Library.Utility.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Encryption", "..\..\Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj", "{2CF2D90E-C25B-47AD-91E0-98451BAB8058}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Interface", "..\..\Duplicati\Library\Interface\Duplicati.Library.Interface.csproj", "{C5899F45-B0FF-483C-9D38-24A9FCAAB237}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{72B910F2-8E80-4955-A0D6-ED4C35CEE665}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{72B910F2-8E80-4955-A0D6-ED4C35CEE665}.Debug|x86.Build.0 = Debug|x86
|
||||
{72B910F2-8E80-4955-A0D6-ED4C35CEE665}.Release|x86.ActiveCfg = Release|x86
|
||||
{72B910F2-8E80-4955-A0D6-ED4C35CEE665}.Release|x86.Build.0 = Release|x86
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {71CC6B1F-7F52-4059-8761-30B3D0501ECC}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,128 +0,0 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GnupgSigningTool
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
|
||||
private static string keyfilepassword;
|
||||
|
||||
private static string gpgkeypassphrase;
|
||||
private static string gpgkeyfile;
|
||||
private static string gpgpath;
|
||||
private static string gpgkeyid;
|
||||
private static bool useArmor;
|
||||
|
||||
private static string inputFile;
|
||||
private static string signatureFile;
|
||||
|
||||
private static void SpawnGPG()
|
||||
{
|
||||
|
||||
var armorOption = useArmor ? "--armor" : "";
|
||||
|
||||
var gpgArgument = string.Format("--pinentry-mode loopback --passphrase-fd 0 --batch --yes {0} -u \"{1}\" --output \"{2}\" --detach-sig \"{3}\"",
|
||||
armorOption,
|
||||
gpgkeyid,
|
||||
signatureFile,
|
||||
inputFile);
|
||||
|
||||
var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = gpgpath,
|
||||
Arguments = gpgArgument,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false
|
||||
});
|
||||
|
||||
proc.StandardInput.WriteLine(gpgkeypassphrase);
|
||||
|
||||
proc.WaitForExit();
|
||||
}
|
||||
|
||||
private static void LoadGPGKeyIdAndPassphrase()
|
||||
{
|
||||
using (var enc = new Duplicati.Library.Encryption.AESEncryption(keyfilepassword, new Dictionary<string, string>()))
|
||||
using (var ms = new System.IO.MemoryStream())
|
||||
using (var fs = System.IO.File.OpenRead(gpgkeyfile))
|
||||
{
|
||||
try
|
||||
{
|
||||
enc.Decrypt(fs, ms);
|
||||
}
|
||||
catch (System.Security.Cryptography.CryptographicException e)
|
||||
{
|
||||
throw new ArgumentException("Failed to decrypt gpg secret credentials file: {0}\n", e.Message);
|
||||
}
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
using (var sr = new System.IO.StreamReader(ms))
|
||||
{
|
||||
var lines = sr.ReadToEnd().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
gpgkeyid = lines[0];
|
||||
gpgkeypassphrase = lines[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void Main(string[] _args)
|
||||
{
|
||||
var args = new List<string>(_args);
|
||||
var opts = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args);
|
||||
|
||||
opts.TryGetValue("inputfile", out inputFile);
|
||||
opts.TryGetValue("signaturefile", out signatureFile);
|
||||
opts.TryGetValue("keyfile-password", out keyfilepassword);
|
||||
opts.TryGetValue("gpgkeyfile", out gpgkeyfile);
|
||||
opts.TryGetValue("gpgpath", out gpgpath);
|
||||
opts.TryGetValue("armor", out string armor);
|
||||
|
||||
useArmor = Boolean.TryParse(armor, out useArmor) && useArmor;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(gpgkeyfile))
|
||||
{
|
||||
throw new ArgumentException("No gpgfile with encrypted credentials specified.");
|
||||
}
|
||||
|
||||
if (!System.IO.File.Exists(gpgkeyfile))
|
||||
{
|
||||
throw new ArgumentException("Specified file with encrypted gpg credentials not found.");
|
||||
}
|
||||
|
||||
LoadGPGKeyIdAndPassphrase();
|
||||
|
||||
if (gpgkeyid is null || gpgkeypassphrase is null)
|
||||
{
|
||||
throw new ArgumentException("Could not fetch gpg key id or gpg passphrase.");
|
||||
}
|
||||
|
||||
gpgpath = gpgpath ?? Duplicati.Library.Encryption.GPGEncryption.GetGpgProgramPath();
|
||||
|
||||
SpawnGPG();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/></startup></configuration>
|
||||
@@ -1,11 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>license_upgrader</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>license_upgrader</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace UpdateVersionStamp
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
private static readonly string DIR_SEP = Path.DirectorySeparatorChar.ToString();
|
||||
private static readonly Dictionary<string, Regex> FILEMAP;
|
||||
|
||||
static Program()
|
||||
{
|
||||
var versionre = @"(?<version>\d+\.\d+\.(\*|(\d+(\.(\*|\d+)))?))";
|
||||
FILEMAP = new Dictionary<string, Regex>(StringComparer.InvariantCultureIgnoreCase);
|
||||
FILEMAP.Add("AssemblyInfo.cs", new Regex(@"(\[assembly\: AssemblyVersion\(\""" + versionre + @"""\)\])|(\[assembly\: AssemblyFileVersion\(\""" + versionre + @"\""\)\])|(\[assembly\: AssemblyFileVersionAttribute\(\""" + versionre + @"\""\)\])"));
|
||||
FILEMAP.Add("UpgradeData.wxi", new Regex(@"\<\?define ProductVersion\=\""" + versionre + @"\"" \?\>"));
|
||||
FILEMAP.Add("AssemblyRedirects.xml", new Regex(@"newVersion\=\""" + versionre + @"\"""));
|
||||
FILEMAP.Add("index.html", new Regex(@"\?v\=" + versionre));
|
||||
FILEMAP.Add("login.html", new Regex(@"\?v\=" + versionre));
|
||||
FILEMAP.Add("app.js", new Regex(@"\?v\=" + versionre));
|
||||
}
|
||||
|
||||
private class Options
|
||||
{
|
||||
public string sourcefolder = Path.GetFullPath(Environment.CurrentDirectory);
|
||||
public string ignorefilter = null;
|
||||
public string version = null;
|
||||
public string versiontag = null;
|
||||
|
||||
public void Fixup()
|
||||
{
|
||||
sourcefolder = Duplicati.Library.Common.IO.Util.AppendDirSeparator(System.IO.Path.GetFullPath(sourcefolder.Replace("/", DIR_SEP)));
|
||||
if (ignorefilter != null)
|
||||
ignorefilter =ignorefilter.Replace("/", DIR_SEP);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main(string[] _args)
|
||||
{
|
||||
List<string> args = new List<string>(_args);
|
||||
Dictionary<string, string> options = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args);
|
||||
Options opt = new Options();
|
||||
|
||||
foreach (FieldInfo fi in opt.GetType().GetFields())
|
||||
if (options.ContainsKey(fi.Name))
|
||||
fi.SetValue(opt, options[fi.Name]);
|
||||
|
||||
opt.Fixup();
|
||||
|
||||
Duplicati.Library.Utility.IFilter filter = null;
|
||||
if (!string.IsNullOrEmpty(opt.ignorefilter))
|
||||
filter = new Duplicati.Library.Utility.FilterExpression(opt.ignorefilter, false);
|
||||
|
||||
Func<string, bool> isFile = (string x) => !x.EndsWith(DIR_SEP);
|
||||
|
||||
var paths = Duplicati.Library.Utility.Utility.EnumerateFileSystemEntries(opt.sourcefolder)
|
||||
.Where(x => Duplicati.Library.Utility.FilterExpression.Matches(filter, x))
|
||||
.Where(x => isFile(x) && FILEMAP.ContainsKey(Path.GetFileName(x)))
|
||||
.Select(x =>
|
||||
{
|
||||
var m = FILEMAP[Path.GetFileName(x)].Match(File.ReadAllText(x));
|
||||
return m.Success ?
|
||||
new { File = x, Version = new Version(m.Groups["version"].Value.Replace("*", "0")), Display = m.Groups["version"].Value }
|
||||
: null;
|
||||
})
|
||||
.Where(x => x != null)
|
||||
.ToArray(); //No need to re-eval
|
||||
|
||||
if (paths.Count() == 0)
|
||||
{
|
||||
Console.WriteLine("No files found to update...");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var p in paths)
|
||||
Console.WriteLine("{0}\t:{1}", p.Display, p.File);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(opt.version))
|
||||
{
|
||||
var maxv = paths.Select(x => x.Version).Max();
|
||||
opt.version = new Version(
|
||||
maxv.Major,
|
||||
maxv.Minor,
|
||||
maxv.Build,
|
||||
maxv.Revision).ToString();
|
||||
}
|
||||
|
||||
//Sanity check
|
||||
var nv = new Version(opt.version).ToString(4);
|
||||
|
||||
foreach (var p in paths)
|
||||
{
|
||||
var re = FILEMAP[Path.GetFileName(p.File)];
|
||||
var txt = File.ReadAllText(p.File);
|
||||
//var m = re.Match(txt).Groups["version"];
|
||||
txt = re.Replace(txt, (m) => {
|
||||
var t = m.Groups["version"];
|
||||
return m.Value.Replace(t.Value, nv);
|
||||
});
|
||||
File.WriteAllText(p.File, txt);
|
||||
}
|
||||
|
||||
Console.WriteLine("Updated {0} files to version {1}", paths.Count(), opt.version);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
[assembly: AssemblyTitle("UpdateVersionStamp")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>10.0.0</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{1920C3B0-98A0-410F-8972-9C19FA616FE5}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<RootNamespace>UpdateVersionStamp</RootNamespace>
|
||||
<AssemblyName>UpdateVersionStamp</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<Commandlineparameters>--sourcefolder=../.. --version=2.0.0.0 --version-tag=20140405</Commandlineparameters>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Duplicati\Library\Common\Duplicati.Library.Common.csproj">
|
||||
<Project>{D63E53E4-A458-4C2F-914D-92F715F58ACF}</Project>
|
||||
<Name>Duplicati.Library.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,35 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UpdateVersionStamp", "UpdateVersionStamp.csproj", "{1920C3B0-98A0-410F-8972-9C19FA616FE5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Utility", "..\..\Duplicati\Library\Utility\Duplicati.Library.Utility.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Common", "..\..\Duplicati\Library\Common\Duplicati.Library.Common.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1920C3B0-98A0-410F-8972-9C19FA616FE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1920C3B0-98A0-410F-8972-9C19FA616FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1920C3B0-98A0-410F-8972-9C19FA616FE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1920C3B0-98A0-410F-8972-9C19FA616FE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = UpdateVersionStamp.csproj
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/></startup></configuration>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="NGettext" version="0.6.4" targetFramework="net471" />
|
||||
</packages>
|
||||
@@ -1,334 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26730.12
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Utility", "Duplicati\Library\Utility\Duplicati.Library.Utility.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Main", "Duplicati\Library\Main\Duplicati.Library.Main.csproj", "{10D2D1B7-C664-41D8-9B3A-00040C3D421B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.File", "Duplicati\Library\Backend\File\Duplicati.Library.Backend.File.csproj", "{FC9B7611-836F-4127-8B44-A7C31F506807}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Compression", "Duplicati\Library\Compression\Duplicati.Library.Compression.csproj", "{19ECCE09-B5EB-406C-8C57-BAC66997D469}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Encryption", "Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj", "{2CF2D90E-C25B-47AD-91E0-98451BAB8058}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Logging", "Duplicati\Library\Logging\Duplicati.Library.Logging.csproj", "{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine", "Duplicati\CommandLine\Duplicati.CommandLine.csproj", "{81765A64-3661-4E3E-B850-2F6F87A51F74}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Interface", "Duplicati\Library\Interface\Duplicati.Library.Interface.csproj", "{C5899F45-B0FF-483C-9D38-24A9FCAAB237}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.DynamicLoader", "Duplicati\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj", "{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Snapshots", "Duplicati\Library\Snapshots\Duplicati.Library.Snapshots.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Modules.Builtin", "Duplicati\Library\Modules\Builtin\Duplicati.Library.Modules.Builtin.csproj", "{52826615-7964-47FE-B4B3-1B2DBDF605B9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.License", "Duplicati\License\Duplicati.License.csproj", "{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.SSHv2", "Duplicati\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj", "{FF2BF37C-E502-4C98-BEA0-701671DDFA08}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.WEBDAV", "Duplicati\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj", "{BAE27510-8B5D-44B2-B33E-372A98908041}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.OneDrive", "Duplicati\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj", "{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.TahoeLAFS", "Duplicati\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj", "{C0270709-2A40-43B5-8CF1-69581B9FA2A1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.CloudFiles", "Duplicati\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj", "{1BFAE226-8364-4086-825C-BB83F6F3EE4C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.FTP", "Duplicati\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj", "{F61679A9-E5DE-468A-B5A4-05F92D0143D2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.S3", "Duplicati\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj", "{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.AzureBlob", "Duplicati\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj", "{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Localization", "Duplicati\Library\Localization\Duplicati.Library.Localization.csproj", "{B68F2214-951F-4F78-8488-66E1ED3F50BF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.AutoUpdater", "Duplicati\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj", "{7E119745-1F62-43F0-936C-F312A1912C0B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.SQLiteHelper", "Duplicati\Library\SQLiteHelper\Duplicati.Library.SQLiteHelper.csproj", "{2C838169-B187-4B09-8768-1C24C2521C8D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.UsageReporter", "Duplicati\Library\UsageReporter\Duplicati.Library.UsageReporter.csproj", "{BB014EA5-CE2C-4444-8D30-38983A0E8553}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.OAuthHelper", "Duplicati\Library\Backend\OAuthHelper\Duplicati.Library.OAuthHelper.csproj", "{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.BackendTool", "Duplicati\CommandLine\BackendTool\Duplicati.CommandLine.BackendTool.csproj", "{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.BackendTester", "Duplicati\CommandLine\BackendTester\Duplicati.CommandLine.BackendTester.csproj", "{E7280DCA-7776-4A73-B9B5-41FD77FC8799}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.GoogleServices", "Duplicati\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj", "{5489181D-950C-44AF-873C-45EB0A3B6BD2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.OpenStack", "Duplicati\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj", "{D9E4E686-423C-48EC-A392-404E7C00860C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.RecoveryTool", "Duplicati\CommandLine\RecoveryTool\Duplicati.CommandLine.RecoveryTool.csproj", "{4A010589-76E6-4F05-A5C4-4598D5DF11F8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Box", "Duplicati\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj", "{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.AlternativeFTP", "Duplicati\Library\Backend\AlternativeFTP\Duplicati.Library.Backend.AlternativeFTP.csproj", "{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Backblaze", "Duplicati\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj", "{61C43D61-4368-4942-84A3-1EB623F4EF2A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Dropbox", "Duplicati\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj", "{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Mega", "Duplicati\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj", "{6643A5AE-AB38-453F-ADCE-408E35A81A83}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.SharePoint", "Duplicati\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj", "{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Tools", "Duplicati\Tools\Duplicati.Tools.csproj", "{0797AA22-C5DD-4950-BB60-34765AB8C6DD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Sia", "Duplicati\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj", "{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Common", "Duplicati\Library\Common\Duplicati.Library.Common.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Jottacloud", "Duplicati\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj", "{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Rclone", "Duplicati\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj", "{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Storj", "Duplicati\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj", "{AE035E01-C917-4F13-A35E-78F21C1A2F17}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.TencentCOS", "Duplicati\Library\Backend\TencentCOS\Duplicati.Library.Backend.TencentCOS.csproj", "{545DD6D4-9476-42D6-B51C-A28E000C489E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Tardigrade", "Duplicati\Library\Backend\Tardigrade\Duplicati.Library.Backend.Tardigrade.csproj", "{9A04CB37-DA72-4008-9703-3AC5191974E9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Idrivee2", "Duplicati\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj", "{6B594D23-B629-465C-B799-70EE9E56C218}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{10D2D1B7-C664-41D8-9B3A-00040C3D421B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC9B7611-836F-4127-8B44-A7C31F506807}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC9B7611-836F-4127-8B44-A7C31F506807}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC9B7611-836F-4127-8B44-A7C31F506807}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{81765A64-3661-4E3E-B850-2F6F87A51F74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{81765A64-3661-4E3E-B850-2F6F87A51F74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C5899F45-B0FF-483C-9D38-24A9FCAAB237}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{52826615-7964-47FE-B4B3-1B2DBDF605B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{52826615-7964-47FE-B4B3-1B2DBDF605B9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FF2BF37C-E502-4C98-BEA0-701671DDFA08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BAE27510-8B5D-44B2-B33E-372A98908041}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BAE27510-8B5D-44B2-B33E-372A98908041}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BAE27510-8B5D-44B2-B33E-372A98908041}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C0270709-2A40-43B5-8CF1-69581B9FA2A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1BFAE226-8364-4086-825C-BB83F6F3EE4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F61679A9-E5DE-468A-B5A4-05F92D0143D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B68F2214-951F-4F78-8488-66E1ED3F50BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7E119745-1F62-43F0-936C-F312A1912C0B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2C838169-B187-4B09-8768-1C24C2521C8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2C838169-B187-4B09-8768-1C24C2521C8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2C838169-B187-4B09-8768-1C24C2521C8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2C838169-B187-4B09-8768-1C24C2521C8D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BB014EA5-CE2C-4444-8D30-38983A0E8553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BB014EA5-CE2C-4444-8D30-38983A0E8553}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BB014EA5-CE2C-4444-8D30-38983A0E8553}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BB014EA5-CE2C-4444-8D30-38983A0E8553}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E7280DCA-7776-4A73-B9B5-41FD77FC8799}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5489181D-950C-44AF-873C-45EB0A3B6BD2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5489181D-950C-44AF-873C-45EB0A3B6BD2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5489181D-950C-44AF-873C-45EB0A3B6BD2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5489181D-950C-44AF-873C-45EB0A3B6BD2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D9E4E686-423C-48EC-A392-404E7C00860C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D9E4E686-423C-48EC-A392-404E7C00860C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D9E4E686-423C-48EC-A392-404E7C00860C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D9E4E686-423C-48EC-A392-404E7C00860C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D60AD540-0E7D-40CE-83AE-D26E01FFE9B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D60AD540-0E7D-40CE-83AE-D26E01FFE9B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D60AD540-0E7D-40CE-83AE-D26E01FFE9B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D60AD540-0E7D-40CE-83AE-D26E01FFE9B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4A010589-76E6-4F05-A5C4-4598D5DF11F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4A010589-76E6-4F05-A5C4-4598D5DF11F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4A010589-76E6-4F05-A5C4-4598D5DF11F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4A010589-76E6-4F05-A5C4-4598D5DF11F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{61C43D61-4368-4942-84A3-1EB623F4EF2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{61C43D61-4368-4942-84A3-1EB623F4EF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{61C43D61-4368-4942-84A3-1EB623F4EF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{61C43D61-4368-4942-84A3-1EB623F4EF2A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6643A5AE-AB38-453F-ADCE-408E35A81A83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6643A5AE-AB38-453F-ADCE-408E35A81A83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6643A5AE-AB38-453F-ADCE-408E35A81A83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6643A5AE-AB38-453F-ADCE-408E35A81A83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0797AA22-C5DD-4950-BB60-34765AB8C6DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0797AA22-C5DD-4950-BB60-34765AB8C6DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0797AA22-C5DD-4950-BB60-34765AB8C6DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0797AA22-C5DD-4950-BB60-34765AB8C6DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D63E53E4-A458-4C2F-914D-92F715F58ACF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C16639F6-DACC-4DD9-86CD-8B937516B340}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C16639F6-DACC-4DD9-86CD-8B937516B340}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C16639F6-DACC-4DD9-86CD-8B937516B340}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C16639F6-DACC-4DD9-86CD-8B937516B340}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3221EB9F-EE08-460E-B236-CD594688FC5F}
|
||||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = Duplicati\CommandLine\Duplicati.CommandLine.csproj
|
||||
Policies = $0
|
||||
$0.StandardHeader = $1
|
||||
$1.Text = @ Copyright (C) ${Year}, The Duplicati Team\nhttps://duplicati.com, hello@duplicati.com\n\nPermission is hereby granted, free of charge, to any person obtaining a \ncopy of this software and associated documentation files (the "Software"), \nto deal in the Software without restriction, including without limitation \nthe rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the \nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in \nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS \nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \nDEALINGS IN THE SOFTWARE.\n
|
||||
$1.IncludeInNewFiles = True
|
||||
$0.DotNetNamingPolicy = $2
|
||||
$2.DirectoryNamespaceAssociation = PrefixedHierarchical
|
||||
$2.ResourceNamePolicy = FileFormatDefault
|
||||
$0.TextStylePolicy = $5
|
||||
$3.inheritsSet = VisualStudio
|
||||
$3.scope = text/plain
|
||||
$3.FileWidth = 120
|
||||
$3.EolMarker = Windows
|
||||
$3.inheritsScope = text/plain
|
||||
$0.CSharpFormattingPolicy = $4
|
||||
$4.IndentSwitchBody = True
|
||||
$4.AnonymousMethodBraceStyle = NextLine
|
||||
$4.PropertyBraceStyle = NextLine
|
||||
$4.PropertyGetBraceStyle = NextLine
|
||||
$4.PropertySetBraceStyle = NextLine
|
||||
$4.EventBraceStyle = NextLine
|
||||
$4.EventAddBraceStyle = NextLine
|
||||
$4.EventRemoveBraceStyle = NextLine
|
||||
$4.StatementBraceStyle = NextLine
|
||||
$4.ElseNewLinePlacement = NewLine
|
||||
$4.ElseIfNewLinePlacement = SameLine
|
||||
$4.CatchNewLinePlacement = NewLine
|
||||
$4.FinallyNewLinePlacement = NewLine
|
||||
$4.BeforeMethodDeclarationParentheses = False
|
||||
$4.BeforeMethodCallParentheses = False
|
||||
$4.BeforeConstructorDeclarationParentheses = False
|
||||
$4.BeforeIndexerDeclarationBracket = False
|
||||
$4.BeforeDelegateDeclarationParentheses = False
|
||||
$4.NewParentheses = False
|
||||
$4.ForParentheses = False
|
||||
$4.ForeachParentheses = False
|
||||
$4.LockParentheses = False
|
||||
$4.UsingParentheses = False
|
||||
$4.SpacesBeforeBrackets = False
|
||||
$4.inheritsSet = Mono
|
||||
$4.inheritsScope = text/x-csharp
|
||||
$4.scope = text/x-csharp
|
||||
$5.FileWidth = 120
|
||||
$5.EolMarker = Windows
|
||||
$5.inheritsSet = VisualStudio
|
||||
$5.inheritsScope = text/plain
|
||||
$5.scope = text/plain
|
||||
EndGlobalSection
|
||||
GlobalSection(SubversionScc) = preSolution
|
||||
Svn-Managed = True
|
||||
Manager = AnkhSVN - Subversion Support for Visual Studio
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Duplicati.Library.Utility;
|
||||
using Duplicati.Server;
|
||||
using Duplicati.Server.Serialization.Interface;
|
||||
|
||||
namespace Duplicati.WebserverCore.Abstractions;
|
||||
|
||||
public interface IScheduler
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes scheduler
|
||||
/// </summary>
|
||||
/// <param name="worker">The worker thread</param>
|
||||
void Init(WorkerThread<Runner.IRunnerData> worker);
|
||||
|
||||
IList<Tuple<long, string>> GetSchedulerQueueIds();
|
||||
|
||||
/// <summary>
|
||||
/// Terminates the thread. Any items still in queue will be removed
|
||||
/// </summary>
|
||||
/// <param name="wait">True if the call should block until the thread has exited, false otherwise</param>
|
||||
void Terminate(bool wait);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to the event that is triggered when the schedule changes
|
||||
/// </summary>
|
||||
void SubScribeToNewSchedule(Action handler);
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot copy of the current schedule list
|
||||
/// </summary>
|
||||
List<KeyValuePair<DateTime, ISchedule>> Schedule { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot copy of the current worker queue, that is items that are scheduled, but waiting for execution
|
||||
/// </summary>
|
||||
List<Runner.IRunnerData> WorkerQueue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Forces the scheduler to re-evaluate the order.
|
||||
/// Call this method if something changes
|
||||
/// </summary>
|
||||
void Reschedule();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using Duplicati.Library.Utility;
|
||||
using Duplicati.Server;
|
||||
|
||||
namespace Duplicati.Library.RestAPI.Abstractions;
|
||||
|
||||
public interface IWorkerThreadsManager
|
||||
{
|
||||
void Spawn(Action<Runner.IRunnerData> item);
|
||||
|
||||
Tuple<long, string>? CurrentTask { get; }
|
||||
WorkerThread<Runner.IRunnerData>? WorkerThread { get; }
|
||||
void UpdateThrottleSpeeds();
|
||||
|
||||
long AddTask(Runner.IRunnerData data, bool skipQueue = false);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Duplicati.Server.Database;
|
||||
using Duplicati.Server.Serialization;
|
||||
using Duplicati.Server.Serialization.Interface;
|
||||
|
||||
namespace Duplicati.Library.RestAPI;
|
||||
|
||||
public static class BackupImportExportHandler
|
||||
{
|
||||
public static void RemovePasswords(IBackup backup)
|
||||
{
|
||||
backup.SanitizeSettings();
|
||||
backup.SanitizeTargetUrl();
|
||||
}
|
||||
|
||||
public static byte[] ExportToJSON(Connection connection, IBackup backup, string passphrase)
|
||||
{
|
||||
Server.Serializable.ImportExportStructure ipx = connection.PrepareBackupForExport(backup);
|
||||
|
||||
byte[] data;
|
||||
using (var ms = new System.IO.MemoryStream())
|
||||
{
|
||||
using (var sw = new System.IO.StreamWriter(ms))
|
||||
{
|
||||
Serializer.SerializeJson(sw, ipx, true);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(passphrase))
|
||||
{
|
||||
ms.Position = 0;
|
||||
using (var ms2 = new System.IO.MemoryStream())
|
||||
{
|
||||
using (var m = new Duplicati.Library.Encryption.AESEncryption(passphrase, new Dictionary<string, string>()))
|
||||
{
|
||||
m.Encrypt(ms, ms2);
|
||||
data = ms2.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static Server.Serializable.ImportExportStructure ImportBackup(string configurationFile, bool importMetadata, Func<string> getPassword, Dictionary<string, string> advancedOptions)
|
||||
{
|
||||
// This removes the ID and DBPath from the backup configuration.
|
||||
Server.Serializable.ImportExportStructure importedStructure = LoadConfiguration(configurationFile, importMetadata, getPassword);
|
||||
|
||||
// This will create the Duplicati-server.sqlite database file if it doesn't exist.
|
||||
using (Duplicati.Server.Database.Connection connection = FIXMEGlobal.GetDatabaseConnection(advancedOptions))
|
||||
{
|
||||
if (connection.Backups.Any(x => x.Name.Equals(importedStructure.Backup.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new InvalidOperationException($"A backup with the name {importedStructure.Backup.Name} already exists.");
|
||||
}
|
||||
|
||||
string error = connection.ValidateBackup(importedStructure.Backup, importedStructure.Schedule);
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
throw new InvalidOperationException(error);
|
||||
}
|
||||
|
||||
// This creates a new ID and DBPath.
|
||||
connection.AddOrUpdateBackupAndSchedule(importedStructure.Backup, importedStructure.Schedule);
|
||||
}
|
||||
|
||||
return importedStructure;
|
||||
}
|
||||
|
||||
public static Server.Serializable.ImportExportStructure LoadConfiguration(string filename, bool importMetadata, Func<string> getPassword)
|
||||
{
|
||||
Server.Serializable.ImportExportStructure ipx;
|
||||
|
||||
var buf = new byte[3];
|
||||
using (var fs = System.IO.File.OpenRead(filename))
|
||||
{
|
||||
Duplicati.Library.Utility.Utility.ForceStreamRead(fs, buf, buf.Length);
|
||||
|
||||
fs.Position = 0;
|
||||
if (buf[0] == 'A' && buf[1] == 'E' && buf[2] == 'S')
|
||||
{
|
||||
using (var m = new Duplicati.Library.Encryption.AESEncryption(getPassword(), new Dictionary<string, string>()))
|
||||
{
|
||||
using (var m2 = m.Decrypt(fs))
|
||||
{
|
||||
using (var sr = new System.IO.StreamReader(m2))
|
||||
{
|
||||
ipx = Serializer.Deserialize<Server.Serializable.ImportExportStructure>(sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var sr = new System.IO.StreamReader(fs))
|
||||
{
|
||||
ipx = Serializer.Deserialize<Server.Serializable.ImportExportStructure>(sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ipx.Backup == null)
|
||||
{
|
||||
throw new Exception("No backup found in document");
|
||||
}
|
||||
|
||||
if (ipx.Backup.Metadata == null)
|
||||
{
|
||||
ipx.Backup.Metadata = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
if (!importMetadata)
|
||||
{
|
||||
ipx.Backup.Metadata.Clear();
|
||||
}
|
||||
|
||||
ipx.Backup.ID = null;
|
||||
ipx.Backup.DBPath = null;
|
||||
|
||||
if (ipx.Schedule != null)
|
||||
{
|
||||
ipx.Schedule.ID = -1;
|
||||
}
|
||||
|
||||
return ipx;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace Duplicati.Server.Database
|
||||
{
|
||||
this.ID = null;
|
||||
}
|
||||
|
||||
|
||||
internal void LoadChildren(Connection con)
|
||||
{
|
||||
if (this.IsTemporary)
|
||||
@@ -69,7 +69,9 @@ namespace Duplicati.Server.Database
|
||||
this.Metadata = con.GetMetadata(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void SetDBPath(string path) => this.DBPath = path;
|
||||
|
||||
/// <summary>
|
||||
/// The backup ID
|
||||
/// </summary>
|
||||
@@ -94,27 +96,27 @@ namespace Duplicati.Server.Database
|
||||
/// The path to the local database
|
||||
/// </summary>
|
||||
public string DBPath { get; internal set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The backup source folders and files
|
||||
/// </summary>
|
||||
public string[] Sources { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The backup settings
|
||||
/// </summary>
|
||||
public ISetting[] Settings { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The filters applied to the source files
|
||||
/// </summary>
|
||||
public IFilter[] Filters { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The backup metadata
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Metadata { get; set; }
|
||||
|
||||
public IDictionary<string, string> Metadata { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating if this instance is not persisted to the database
|
||||
/// </summary>
|
||||
+1279
-1265
File diff suppressed because it is too large
Load Diff
+14
-14
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
Notifications not yet acknowledged by the user
|
||||
*/
|
||||
CREATE TABLE "Notification" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Type" TEXT NOT NULL,
|
||||
"Title" TEXT NOT NULL,
|
||||
"Message" TEXT NOT NULL,
|
||||
"Exception" TEXT NOT NULL,
|
||||
"BackupID" TEXT NULL,
|
||||
"Action" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Notifications not yet acknowledged by the user
|
||||
*/
|
||||
CREATE TABLE "Notification" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Type" TEXT NOT NULL,
|
||||
"Title" TEXT NOT NULL,
|
||||
"Message" TEXT NOT NULL,
|
||||
"Exception" TEXT NOT NULL,
|
||||
"BackupID" TEXT NULL,
|
||||
"Action" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
Key/value storage for frontends
|
||||
*/
|
||||
CREATE TABLE "UIStorage" (
|
||||
"Scheme" TEXT NOT NULL,
|
||||
"Key" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Key/value storage for frontends
|
||||
*/
|
||||
CREATE TABLE "UIStorage" (
|
||||
"Scheme" TEXT NOT NULL,
|
||||
"Key" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
+11
-11
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
Long-term temporary file records
|
||||
*/
|
||||
CREATE TABLE "TempFile" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Origin" TEXT NOT NULL,
|
||||
"Path" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL,
|
||||
"Expires" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Long-term temporary file records
|
||||
*/
|
||||
CREATE TABLE "TempFile" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Origin" TEXT NOT NULL,
|
||||
"Path" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL,
|
||||
"Expires" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
Token Family table
|
||||
*/
|
||||
CREATE TABLE "TokenFamily" (
|
||||
"ID" TEXT PRIMARY KEY,
|
||||
"UserId" TEXT NOT NULL,
|
||||
"Counter" INTEGER NOT NULL,
|
||||
"LastUpdated" INTEGER NOT NULL
|
||||
);
|
||||
+168
-158
@@ -1,158 +1,168 @@
|
||||
/*
|
||||
* The primary table that stores all backups.
|
||||
*
|
||||
* The name and tag are free form user strings.
|
||||
* The tags are comma separated
|
||||
* the TargetURL is the url to remote storage,
|
||||
* and the DBPath is the path to the local database
|
||||
*/
|
||||
CREATE TABLE "Backup" (
|
||||
"ID" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Description" TEXT NOT NULL DEFAULT '',
|
||||
"Tags" TEXT NOT NULL,
|
||||
"TargetURL" TEXT NOT NULL,
|
||||
"DBPath" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The table that stores all schedules
|
||||
*
|
||||
* Tags is a comma separated parsed field that indicates
|
||||
* which backups to run when activated.
|
||||
* special tags are ID:1 which means backup with ID = 1
|
||||
*
|
||||
* Time is the scheduled time, and lastRun is the last time the backup was executed
|
||||
*
|
||||
* Rule is a special parsed field
|
||||
*/
|
||||
CREATE TABLE "Schedule" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Tags" TEXT NOT NULL,
|
||||
"Time" INTEGER NOT NULL,
|
||||
"Repeat" TEXT NOT NULL,
|
||||
"LastRun" INTEGER NOT NULL,
|
||||
"Rule" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The source table is a list of source folders and files
|
||||
*/
|
||||
CREATE TABLE "Source" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Path" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The filter table contains all filters associated with a backup.
|
||||
* The special backupID -1 means "applied to all backups"
|
||||
* The expression is the filter, if the filter is a regular
|
||||
* expression, it is surrounded by hard brackets [ ]
|
||||
*/
|
||||
CREATE TABLE "Filter" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Order" INTEGER NOT NULL,
|
||||
"Include" INTEGER NOT NULL,
|
||||
"Expression" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* All options are stored in this table
|
||||
*
|
||||
* The special backupID -1 means "applied to all backups".
|
||||
*
|
||||
* The filter is used to indicate what the option applies to,
|
||||
* for instance backend:s3 will only apply to backends of type S3
|
||||
*
|
||||
* The name and value are the option name and value
|
||||
*/
|
||||
CREATE TABLE "Option" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Filter" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* Recorded metadata about a backup
|
||||
* This table contains metadata, such as when the backup was last started,
|
||||
* how long it took, how many files there were, how big the backup set was,
|
||||
* how much data was uploaded, downloaded, how fast, how much space is left,
|
||||
* and similar data. Programs can use this information to improve the display,
|
||||
* but cannot count on these values being present
|
||||
*/
|
||||
CREATE TABLE "Metadata" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The log of operations initiated by the scheduler/user
|
||||
*/
|
||||
CREATE TABLE "Log" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Description" TEXT NOT NULL,
|
||||
"Start" INTEGER NOT NULL,
|
||||
"Finish" INTEGER NOT NULL,
|
||||
"Result" TEXT NOT NULL,
|
||||
"SuggestedIcon" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The log of errors
|
||||
*/
|
||||
CREATE TABLE "ErrorLog" (
|
||||
"BackupID" INTEGER,
|
||||
"Message" TEXT NOT NULL,
|
||||
"Exception" TEXT,
|
||||
"Timestamp" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Internal version tracking
|
||||
*/
|
||||
CREATE TABLE "Version" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Version" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Notifications not yet acknowledged by the user
|
||||
*/
|
||||
CREATE TABLE "Notification" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Type" TEXT NOT NULL,
|
||||
"Title" TEXT NOT NULL,
|
||||
"Message" TEXT NOT NULL,
|
||||
"Exception" TEXT NOT NULL,
|
||||
"BackupID" TEXT NULL,
|
||||
"Action" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL,
|
||||
"LogEntryID" TEXT NULL,
|
||||
"MessageID" TEXT NULL,
|
||||
"MessageLogTag" TEXT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Key/value storage for frontends
|
||||
*/
|
||||
CREATE TABLE "UIStorage" (
|
||||
"Scheme" TEXT NOT NULL,
|
||||
"Key" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Long-term temporary file records
|
||||
*/
|
||||
CREATE TABLE "TempFile" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Origin" TEXT NOT NULL,
|
||||
"Path" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL,
|
||||
"Expires" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO "Version" ("Version") VALUES (6);
|
||||
|
||||
/*
|
||||
* The primary table that stores all backups.
|
||||
*
|
||||
* The name and tag are free form user strings.
|
||||
* The tags are comma separated
|
||||
* the TargetURL is the url to remote storage,
|
||||
* and the DBPath is the path to the local database
|
||||
*/
|
||||
CREATE TABLE "Backup" (
|
||||
"ID" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Description" TEXT NOT NULL DEFAULT '',
|
||||
"Tags" TEXT NOT NULL,
|
||||
"TargetURL" TEXT NOT NULL,
|
||||
"DBPath" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The table that stores all schedules
|
||||
*
|
||||
* Tags is a comma separated parsed field that indicates
|
||||
* which backups to run when activated.
|
||||
* special tags are ID:1 which means backup with ID = 1
|
||||
*
|
||||
* Time is the scheduled time, and lastRun is the last time the backup was executed
|
||||
*
|
||||
* Rule is a special parsed field
|
||||
*/
|
||||
CREATE TABLE "Schedule" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Tags" TEXT NOT NULL,
|
||||
"Time" INTEGER NOT NULL,
|
||||
"Repeat" TEXT NOT NULL,
|
||||
"LastRun" INTEGER NOT NULL,
|
||||
"Rule" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The source table is a list of source folders and files
|
||||
*/
|
||||
CREATE TABLE "Source" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Path" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The filter table contains all filters associated with a backup.
|
||||
* The special backupID -1 means "applied to all backups"
|
||||
* The expression is the filter, if the filter is a regular
|
||||
* expression, it is surrounded by hard brackets [ ]
|
||||
*/
|
||||
CREATE TABLE "Filter" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Order" INTEGER NOT NULL,
|
||||
"Include" INTEGER NOT NULL,
|
||||
"Expression" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* All options are stored in this table
|
||||
*
|
||||
* The special backupID -1 means "applied to all backups".
|
||||
*
|
||||
* The filter is used to indicate what the option applies to,
|
||||
* for instance backend:s3 will only apply to backends of type S3
|
||||
*
|
||||
* The name and value are the option name and value
|
||||
*/
|
||||
CREATE TABLE "Option" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Filter" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* Recorded metadata about a backup
|
||||
* This table contains metadata, such as when the backup was last started,
|
||||
* how long it took, how many files there were, how big the backup set was,
|
||||
* how much data was uploaded, downloaded, how fast, how much space is left,
|
||||
* and similar data. Programs can use this information to improve the display,
|
||||
* but cannot count on these values being present
|
||||
*/
|
||||
CREATE TABLE "Metadata" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The log of operations initiated by the scheduler/user
|
||||
*/
|
||||
CREATE TABLE "Log" (
|
||||
"BackupID" INTEGER NOT NULL,
|
||||
"Description" TEXT NOT NULL,
|
||||
"Start" INTEGER NOT NULL,
|
||||
"Finish" INTEGER NOT NULL,
|
||||
"Result" TEXT NOT NULL,
|
||||
"SuggestedIcon" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
* The log of errors
|
||||
*/
|
||||
CREATE TABLE "ErrorLog" (
|
||||
"BackupID" INTEGER,
|
||||
"Message" TEXT NOT NULL,
|
||||
"Exception" TEXT,
|
||||
"Timestamp" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Internal version tracking
|
||||
*/
|
||||
CREATE TABLE "Version" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Version" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Notifications not yet acknowledged by the user
|
||||
*/
|
||||
CREATE TABLE "Notification" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Type" TEXT NOT NULL,
|
||||
"Title" TEXT NOT NULL,
|
||||
"Message" TEXT NOT NULL,
|
||||
"Exception" TEXT NOT NULL,
|
||||
"BackupID" TEXT NULL,
|
||||
"Action" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL,
|
||||
"LogEntryID" TEXT NULL,
|
||||
"MessageID" TEXT NULL,
|
||||
"MessageLogTag" TEXT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Key/value storage for frontends
|
||||
*/
|
||||
CREATE TABLE "UIStorage" (
|
||||
"Scheme" TEXT NOT NULL,
|
||||
"Key" TEXT NOT NULL,
|
||||
"Value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Long-term temporary file records
|
||||
*/
|
||||
CREATE TABLE "TempFile" (
|
||||
"ID" INTEGER PRIMARY KEY,
|
||||
"Origin" TEXT NOT NULL,
|
||||
"Path" TEXT NOT NULL,
|
||||
"Timestamp" INTEGER NOT NULL,
|
||||
"Expires" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
/*
|
||||
Token Family table
|
||||
*/
|
||||
CREATE TABLE "TokenFamily" (
|
||||
"ID" TEXT PRIMARY KEY,
|
||||
"UserId" TEXT NOT NULL,
|
||||
"Counter" INTEGER NOT NULL,
|
||||
"LastUpdated" INTEGER NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO "Version" ("Version") VALUES (7);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Duplicati.Library.RestAPI.Database
|
||||
{
|
||||
public static class DatabaseConnectionSchemaMarker
|
||||
{
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -33,7 +33,7 @@ namespace Duplicati.Server.Database
|
||||
public string Exception { get; set; }
|
||||
public string BackupID { get; set; }
|
||||
public string Action { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public string LogEntryID { get; set; }
|
||||
public string MessageID { get; set; }
|
||||
public string MessageLogTag { get; set; }
|
||||
+17
-17
@@ -33,38 +33,38 @@ namespace Duplicati.Server.Database
|
||||
public string Repeat { get; set; }
|
||||
public DateTime LastRun { get; set; }
|
||||
public string Rule { get; set; }
|
||||
|
||||
|
||||
public DayOfWeek[] AllowedDays
|
||||
{
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.Rule))
|
||||
return null;
|
||||
|
||||
var days = (from n in this.Rule.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
where n.StartsWith("AllowedWeekDays=", StringComparison.OrdinalIgnoreCase)
|
||||
select n.Substring("AllowedWeekDays=".Length).Split(new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
|
||||
|
||||
var days = (from n in this.Rule.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
where n.StartsWith("AllowedWeekDays=", StringComparison.OrdinalIgnoreCase)
|
||||
select n.Substring("AllowedWeekDays=".Length).Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
.FirstOrDefault();
|
||||
|
||||
|
||||
|
||||
|
||||
if (days == null)
|
||||
return null;
|
||||
|
||||
return (from n in days
|
||||
return (from n in days
|
||||
where Enum.TryParse<DayOfWeek>(n, true, out _)
|
||||
select (DayOfWeek)Enum.Parse(typeof(DayOfWeek), n, true))
|
||||
.ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
|
||||
var parts =
|
||||
string.IsNullOrEmpty(this.Rule) ?
|
||||
|
||||
var parts =
|
||||
string.IsNullOrEmpty(this.Rule) ?
|
||||
new string[0] :
|
||||
(from n in this.Rule.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
where !n.StartsWith("AllowedWeekDays=", StringComparison.OrdinalIgnoreCase)
|
||||
select n);
|
||||
|
||||
(from n in this.Rule.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
where !n.StartsWith("AllowedWeekDays=", StringComparison.OrdinalIgnoreCase)
|
||||
select n);
|
||||
|
||||
if (value != null && value.Length != 0)
|
||||
parts = parts.Union(new string[] {
|
||||
"AllowedWeekDays=" +
|
||||
@@ -74,7 +74,7 @@ namespace Duplicati.Server.Database
|
||||
select Enum.GetName(typeof(DayOfWeek), n)).Distinct()
|
||||
)
|
||||
}).Distinct();
|
||||
|
||||
|
||||
this.Rule = string.Join(";", parts);
|
||||
}
|
||||
}
|
||||
+641
-567
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -0,0 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Database\Database schema\**" />
|
||||
<Compile Remove="Database\Database schema\DatabaseConnectionSchemaMarker.cs" />
|
||||
<EmbeddedResource Include="Database\DatabaseConnectionSchemaMarker.cs" />
|
||||
<EmbeddedResource Include="newbackup.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Win32.SystemEvents" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Duplicati\CommandLine\CLI\Duplicati.CommandLine.csproj" />
|
||||
<ProjectReference Include="..\Duplicati\Library\Common\Duplicati.Library.Common.csproj" />
|
||||
<ProjectReference Include="..\Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj" />
|
||||
<ProjectReference Include="..\Duplicati\Library\Main\Duplicati.Library.Main.csproj" />
|
||||
<ProjectReference Include="..\Duplicati\Library\Snapshots\Duplicati.Library.Snapshots.csproj" />
|
||||
<ProjectReference Include="..\Duplicati\Library\SQLiteHelper\Duplicati.Library.SQLiteHelper.csproj" />
|
||||
<ProjectReference Include="..\Duplicati\Server\Duplicati.Server.Serialization\Duplicati.Server.Serialization.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="WebServer\Kestrel\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+75
-97
@@ -1,97 +1,75 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles synchronized waiting for events
|
||||
/// </summary>
|
||||
public class EventPollNotify
|
||||
{
|
||||
/// <summary>
|
||||
/// The lock that grants exclusive access to control structures
|
||||
/// </summary>
|
||||
private readonly object m_lock = new object();
|
||||
/// <summary>
|
||||
/// The current eventID
|
||||
/// </summary>
|
||||
private long m_eventNo = 0;
|
||||
/// <summary>
|
||||
/// The list of subscribed waiting threads
|
||||
/// </summary>
|
||||
private readonly Queue<System.Threading.ManualResetEvent> m_waitQueue = new Queue<System.Threading.ManualResetEvent>();
|
||||
|
||||
/// <summary>
|
||||
/// An eventhandler for subscribing to event updates without blocking
|
||||
/// </summary>
|
||||
public event EventHandler NewEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current event ID
|
||||
/// </summary>
|
||||
public long EventNo { get { return m_eventNo; } }
|
||||
|
||||
/// <summary>
|
||||
/// Call to wait for an event that is newer than the current known event
|
||||
/// </summary>
|
||||
/// <param name="eventId">The last known event id</param>
|
||||
/// <param name="milliseconds">The number of milliseconds to block</param>
|
||||
/// <returns>The current event id</returns>
|
||||
public long Wait(long eventId, int milliseconds)
|
||||
{
|
||||
System.Threading.ManualResetEvent mre;
|
||||
lock (m_lock)
|
||||
{
|
||||
//If a newer event has already occured, return immediately
|
||||
if (eventId != m_eventNo)
|
||||
return m_eventNo;
|
||||
|
||||
//Otherwise register this thread as waiting
|
||||
mre = new System.Threading.ManualResetEvent(false);
|
||||
m_waitQueue.Enqueue(mre);
|
||||
}
|
||||
|
||||
//Wait until we are signalled or the time has elapsed
|
||||
mre.WaitOne(milliseconds, false);
|
||||
return m_eventNo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals that an event has occurred and notifies all waiting threads
|
||||
/// </summary>
|
||||
public void SignalNewEvent()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
m_eventNo++;
|
||||
while (m_waitQueue.Count > 0)
|
||||
m_waitQueue.Dequeue().Set();
|
||||
}
|
||||
|
||||
if (NewEvent != null)
|
||||
NewEvent(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles synchronized waiting for events
|
||||
/// </summary>
|
||||
public class EventPollNotify
|
||||
{
|
||||
/// <summary>
|
||||
/// The lock that grants exclusive access to control structures
|
||||
/// </summary>
|
||||
private readonly object m_lock = new object();
|
||||
/// <summary>
|
||||
/// The current eventID
|
||||
/// </summary>
|
||||
private long m_eventNo = 0;
|
||||
/// <summary>
|
||||
/// The list of subscribed waiting threads
|
||||
/// </summary>
|
||||
private readonly Queue<System.Threading.ManualResetEvent> m_waitQueue = new Queue<System.Threading.ManualResetEvent>();
|
||||
|
||||
/// <summary>
|
||||
/// An eventhandler for subscribing to event updates without blocking
|
||||
/// </summary>
|
||||
public event EventHandler NewEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current event ID
|
||||
/// </summary>
|
||||
public long EventNo { get { return m_eventNo; } }
|
||||
|
||||
/// <summary>
|
||||
/// Call to wait for an event that is newer than the current known event
|
||||
/// </summary>
|
||||
/// <param name="eventId">The last known event id</param>
|
||||
/// <param name="milliseconds">The number of milliseconds to block</param>
|
||||
/// <returns>The current event id</returns>
|
||||
public long Wait(long eventId, int milliseconds)
|
||||
{
|
||||
System.Threading.ManualResetEvent mre;
|
||||
lock (m_lock)
|
||||
{
|
||||
//If a newer event has already occured, return immediately
|
||||
if (eventId != m_eventNo)
|
||||
return m_eventNo;
|
||||
|
||||
//Otherwise register this thread as waiting
|
||||
mre = new System.Threading.ManualResetEvent(false);
|
||||
m_waitQueue.Enqueue(mre);
|
||||
}
|
||||
|
||||
//Wait until we are signalled or the time has elapsed
|
||||
mre.WaitOne(milliseconds, false);
|
||||
return m_eventNo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals that an event has occurred and notifies all waiting threads
|
||||
/// </summary>
|
||||
public void SignalNewEvent()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
m_eventNo++;
|
||||
while (m_waitQueue.Count > 0)
|
||||
m_waitQueue.Dequeue().Set();
|
||||
}
|
||||
|
||||
if (NewEvent != null)
|
||||
NewEvent(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
|
||||
using Duplicati.Server;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Duplicati.Library.RestAPI.Abstractions;
|
||||
using Duplicati.Library.Utility;
|
||||
using Duplicati.WebserverCore.Abstractions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Duplicati.Library.RestAPI
|
||||
{
|
||||
/**
|
||||
* In the absense of dependancy injection, there is a significant amount of variables exposed through Program as globals.
|
||||
* This causes a problem decoupling classes and leads to circular dependancies.
|
||||
*/
|
||||
public static class FIXMEGlobal
|
||||
{
|
||||
/// <summary>
|
||||
/// The placeholder for passwords in the UI
|
||||
/// </summary>
|
||||
public const string PASSWORD_PLACEHOLDER = "**********";
|
||||
|
||||
public static IServiceProvider Provider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is the only access to the database
|
||||
/// </summary>
|
||||
public static Server.Database.Connection DataConnection;
|
||||
|
||||
/// <summary>
|
||||
/// A delegate method for creating a copy of the current progress state
|
||||
/// </summary>
|
||||
public static Func<Duplicati.Server.Serialization.Interface.IProgressEventData> GenerateProgressState;
|
||||
|
||||
/// <summary>
|
||||
/// The status event signaler, used to control long polling of status updates
|
||||
/// </summary>
|
||||
public static EventPollNotify StatusEventNotifyer => Provider.GetRequiredService<EventPollNotify>();
|
||||
|
||||
/// <summary>
|
||||
/// For keeping and incrementing last last events Ids of db save and last notification
|
||||
/// </summary>
|
||||
public static INotificationUpdateService NotificationUpdateService => Provider.GetRequiredService<INotificationUpdateService>();
|
||||
/// <summary>
|
||||
/// Checks if the server has started and is listening for events
|
||||
/// </summary>
|
||||
public static bool IsServerStarted => Provider != null;
|
||||
|
||||
/// <summary>
|
||||
/// This is the working thread
|
||||
/// </summary>
|
||||
public static WorkerThread<Runner.IRunnerData> WorkThread =>
|
||||
Provider.GetRequiredService<IWorkerThreadsManager>().WorkerThread;
|
||||
|
||||
public static IWorkerThreadsManager WorkerThreadsManager =>
|
||||
Provider.GetRequiredService<IWorkerThreadsManager>();
|
||||
|
||||
public static Action StartOrStopUsageReporter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the folder where Duplicati data is stored
|
||||
/// </summary>
|
||||
public static string DataFolder;
|
||||
|
||||
/// <summary>
|
||||
/// This is the scheduling thread
|
||||
/// </summary>
|
||||
public static IScheduler Scheduler => Provider.GetRequiredService<IScheduler>();
|
||||
|
||||
/// <summary>
|
||||
/// The log redirect handler
|
||||
/// </summary>
|
||||
public static readonly LogWriteHandler LogHandler = new LogWriteHandler();
|
||||
|
||||
public static Func<Dictionary<string, string>, Server.Database.Connection> GetDatabaseConnection;
|
||||
|
||||
/// <summary>
|
||||
/// The update poll thread.
|
||||
/// </summary>
|
||||
public static UpdatePollThread UpdatePoller => Provider.GetRequiredService<UpdatePollThread>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used to check the origin of the web server (e.g. Tray icon or a stand alone Server)
|
||||
/// </summary>
|
||||
public static string Origin = "Server";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The application exit event
|
||||
/// </summary>
|
||||
public static System.Threading.ManualResetEvent ApplicationExitEvent;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// List of completed task results
|
||||
/// </summary>
|
||||
public static readonly List<KeyValuePair<long, Exception>> TaskResultCache = new List<KeyValuePair<long, Exception>>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is the lock to be used before manipulating the shared resources
|
||||
/// </summary>
|
||||
public static readonly object MainLock = new object();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -18,388 +18,408 @@
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Duplicati.Library.Common;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This class keeps track of the users modifications regarding
|
||||
/// throttling and pause/resume
|
||||
/// </summary>
|
||||
public class LiveControls
|
||||
{
|
||||
/// <summary>
|
||||
/// The tag used for logging
|
||||
/// </summary>
|
||||
private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType<LiveControls>();
|
||||
|
||||
/// <summary>
|
||||
/// An event that is activated when the pause state changes
|
||||
/// </summary>
|
||||
public event EventHandler StateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// An event that is activated when the thread priority changes
|
||||
/// </summary>
|
||||
public event EventHandler ThreadPriorityChanged;
|
||||
|
||||
/// <summary>
|
||||
/// An event that is activated when the throttle speed changes
|
||||
/// </summary>
|
||||
public event EventHandler ThrottleSpeedChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The possible states for the live control
|
||||
/// </summary>
|
||||
public enum LiveControlState
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the backups are running
|
||||
/// </summary>
|
||||
Running,
|
||||
/// <summary>
|
||||
/// Indicates that the backups are currently suspended
|
||||
/// </summary>
|
||||
Paused
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current control state
|
||||
/// </summary>
|
||||
private LiveControlState m_state;
|
||||
|
||||
/// <summary>
|
||||
/// A value that indicates if the current pause state is caused by being suspended
|
||||
/// </summary>
|
||||
private bool m_pausedForSuspend = false;
|
||||
|
||||
/// <summary>
|
||||
/// The time to pause for, used to ensure that a user set pause can override the suspend pause
|
||||
/// </summary>
|
||||
private DateTime m_suspendMinimumPause = new DateTime(0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current state for the control
|
||||
/// </summary>
|
||||
public LiveControlState State { get { return m_state; } }
|
||||
|
||||
/// <summary>
|
||||
/// The internal variable that tracks the the priority
|
||||
/// </summary>
|
||||
private System.Threading.ThreadPriority? m_priority;
|
||||
|
||||
/// <summary>
|
||||
/// The internal variable that tracks the upload limit
|
||||
/// </summary>
|
||||
private long? m_uploadLimit;
|
||||
|
||||
/// <summary>
|
||||
/// The internal variable that tracks the download limit
|
||||
/// </summary>
|
||||
private long? m_downloadLimit;
|
||||
|
||||
/// <summary>
|
||||
/// The object that ensures concurrent operations
|
||||
/// </summary>
|
||||
private readonly object m_lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current overridden thread priority
|
||||
/// </summary>
|
||||
public System.Threading.ThreadPriority? ThreadPriority
|
||||
{
|
||||
get { return m_priority; }
|
||||
set
|
||||
{
|
||||
if (m_priority != value)
|
||||
{
|
||||
m_priority = value;
|
||||
if (ThreadPriorityChanged != null)
|
||||
ThreadPriorityChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current upload limit in bps
|
||||
/// </summary>
|
||||
public long? UploadLimit
|
||||
{
|
||||
get { return m_uploadLimit; }
|
||||
set
|
||||
{
|
||||
if (m_uploadLimit != value)
|
||||
{
|
||||
m_uploadLimit = value;
|
||||
if (ThrottleSpeedChanged != null)
|
||||
ThrottleSpeedChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the download limit in bps
|
||||
/// </summary>
|
||||
public long? DownloadLimit
|
||||
{
|
||||
get { return m_downloadLimit; }
|
||||
set
|
||||
{
|
||||
if (m_downloadLimit != value)
|
||||
{
|
||||
m_downloadLimit = value;
|
||||
if (ThrottleSpeedChanged != null)
|
||||
ThrottleSpeedChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The timer that is activated after a pause period.
|
||||
/// </summary>
|
||||
private readonly System.Threading.Timer m_waitTimer;
|
||||
|
||||
/// <summary>
|
||||
/// The time that the current pause is expected to expire
|
||||
/// </summary>
|
||||
private DateTime m_waitTimeExpiration = new DateTime(0);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the LiveControl
|
||||
/// </summary>
|
||||
public LiveControls(Database.ServerSettings settings)
|
||||
{
|
||||
m_state = LiveControlState.Running;
|
||||
m_waitTimer = new System.Threading.Timer(m_waitTimer_Tick, this, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.StartupDelayDuration) && settings.StartupDelayDuration != "0")
|
||||
{
|
||||
long milliseconds = 0;
|
||||
try { milliseconds = (long)Duplicati.Library.Utility.Timeparser.ParseTimeSpan(settings.StartupDelayDuration).TotalMilliseconds; }
|
||||
catch {}
|
||||
|
||||
if (milliseconds > 0)
|
||||
{
|
||||
m_waitTimeExpiration = DateTime.Now.AddMilliseconds(milliseconds);
|
||||
m_waitTimer.Change(milliseconds, System.Threading.Timeout.Infinite);
|
||||
m_state = LiveControlState.Paused;
|
||||
}
|
||||
}
|
||||
|
||||
m_priority = settings.ThreadPriorityOverride;
|
||||
if (!string.IsNullOrEmpty(settings.DownloadSpeedLimit))
|
||||
try
|
||||
{
|
||||
m_downloadLimit = Library.Utility.Sizeparser.ParseSize(settings.DownloadSpeedLimit, "kb");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Library.Logging.Log.WriteErrorMessage(LOGTAG, "ParseDownloadLimitError", ex, "Failed to parse download limit: {0}", settings.DownloadSpeedLimit);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.UploadSpeedLimit))
|
||||
try
|
||||
{
|
||||
m_uploadLimit = Library.Utility.Sizeparser.ParseSize(settings.UploadSpeedLimit, "kb");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Library.Logging.Log.WriteErrorMessage(LOGTAG, "ParseUploadLimitError", ex, "Failed to parse upload limit: {0}", settings.UploadSpeedLimit);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!Platform.IsClientPosix)
|
||||
RegisterHibernateMonitor();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that occurs when the timeout duration is exceeded
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
private void m_waitTimer_Tick(object sender)
|
||||
{
|
||||
lock (m_lock)
|
||||
Resume();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper to reset the timeout timer
|
||||
/// </summary>
|
||||
/// <param name="timeout">The time to wait</param>
|
||||
private void ResetTimer(string timeout)
|
||||
{
|
||||
lock (m_lock)
|
||||
if (!string.IsNullOrEmpty(timeout))
|
||||
{
|
||||
long milliseconds = (long)Duplicati.Library.Utility.Timeparser.ParseTimeSpan(timeout).TotalMilliseconds;
|
||||
m_waitTimeExpiration = DateTime.Now.AddMilliseconds(milliseconds);
|
||||
m_waitTimer.Change(milliseconds, System.Threading.Timeout.Infinite);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_waitTimeExpiration = new DateTime(0);
|
||||
m_waitTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper to set the pause mode
|
||||
/// </summary>
|
||||
private void SetPauseMode()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_state == LiveControlState.Running)
|
||||
{
|
||||
m_state = LiveControlState.Paused;
|
||||
if (StateChanged != null)
|
||||
StateChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the backups until resumed
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
lock(m_lock)
|
||||
{
|
||||
var fireEvent = m_waitTimeExpiration.Ticks != 0 && m_state == LiveControlState.Paused && StateChanged != null;
|
||||
|
||||
ResetTimer(null);
|
||||
|
||||
if (fireEvent)
|
||||
StateChanged(this, null);
|
||||
else
|
||||
SetPauseMode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes a backups to the running state
|
||||
/// </summary>
|
||||
public void Resume()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_state == LiveControlState.Paused)
|
||||
{
|
||||
//Make sure that the timer is cleared
|
||||
ResetTimer(null);
|
||||
|
||||
m_state = LiveControlState.Running;
|
||||
if (StateChanged != null)
|
||||
StateChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the backups for a given period
|
||||
/// </summary>
|
||||
/// <param name="timeout">The duration to wait</param>
|
||||
public void Pause(string timeout)
|
||||
{
|
||||
Pause(Duplicati.Library.Utility.Timeparser.ParseTimeSpan(timeout));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the backups for a given period
|
||||
/// </summary>
|
||||
/// <param name="timeout">The duration to wait</param>
|
||||
public void Pause(TimeSpan timeout)
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
m_waitTimeExpiration = DateTime.Now.AddMilliseconds((long)timeout.TotalMilliseconds);
|
||||
m_waitTimer.Change((long)timeout.TotalMilliseconds, System.Threading.Timeout.Infinite);
|
||||
|
||||
//We change the time, so we issue a new event
|
||||
if (m_state == LiveControlState.Paused && StateChanged != null)
|
||||
StateChanged(this, null);
|
||||
else
|
||||
SetPauseMode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time the current pause is expected to end
|
||||
/// </summary>
|
||||
public DateTime EstimatedPauseEnd { get { return m_waitTimeExpiration; } }
|
||||
|
||||
/// <summary>
|
||||
/// Method for calling a Win32 API
|
||||
/// </summary>
|
||||
private void RegisterHibernateMonitor()
|
||||
{
|
||||
Microsoft.Win32.SystemEvents.PowerModeChanged += new Microsoft.Win32.PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A monitor for detecting when the system hibernates or resumes
|
||||
/// </summary>
|
||||
/// <param name="sender">Unused sender parameter</param>
|
||||
/// <param name="_e">The event information</param>
|
||||
private void SystemEvents_PowerModeChanged(object sender, object _e)
|
||||
{
|
||||
Microsoft.Win32.PowerModeChangedEventArgs e = _e as Microsoft.Win32.PowerModeChangedEventArgs;
|
||||
if (e == null)
|
||||
return;
|
||||
|
||||
if (e.Mode == Microsoft.Win32.PowerModes.Suspend)
|
||||
{
|
||||
//If we are running, register as being paused due to suspending
|
||||
if (this.m_state == LiveControlState.Running)
|
||||
{
|
||||
this.SetPauseMode();
|
||||
m_pausedForSuspend = true;
|
||||
m_suspendMinimumPause = new DateTime(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_waitTimeExpiration.Ticks != 0)
|
||||
{
|
||||
m_pausedForSuspend = true;
|
||||
m_suspendMinimumPause = this.EstimatedPauseEnd;
|
||||
ResetTimer(null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (e.Mode == Microsoft.Win32.PowerModes.Resume)
|
||||
{
|
||||
//If we have been been paused due to suspending, we un-pause now
|
||||
if (m_pausedForSuspend)
|
||||
{
|
||||
long delayTicks = (m_suspendMinimumPause - DateTime.Now).Ticks;
|
||||
|
||||
var appset = Program.DataConnection.ApplicationSettings;
|
||||
if (!string.IsNullOrEmpty(appset.StartupDelayDuration) && appset.StartupDelayDuration != "0")
|
||||
try { delayTicks = Math.Max(delayTicks, Library.Utility.Timeparser.ParseTimeSpan(appset.StartupDelayDuration).Ticks); }
|
||||
catch { }
|
||||
|
||||
if (delayTicks > 0)
|
||||
{
|
||||
this.Pause(TimeSpan.FromTicks(delayTicks));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Resume();
|
||||
}
|
||||
}
|
||||
|
||||
m_pausedForSuspend = false;
|
||||
m_suspendMinimumPause = new DateTime(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
using Duplicati.Library.IO;
|
||||
using Duplicati.Server.Database;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This class keeps track of the users modifications regarding
|
||||
/// throttling and pause/resume
|
||||
/// </summary>
|
||||
public class LiveControls : ILiveControls
|
||||
{
|
||||
/// <summary>
|
||||
/// The tag used for logging
|
||||
/// </summary>
|
||||
private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType<LiveControls>();
|
||||
|
||||
/// <summary>
|
||||
/// An event that is activated when the pause state changes
|
||||
/// </summary>
|
||||
public event EventHandler StateChanged;
|
||||
|
||||
/// <summary>
|
||||
/// An event that is activated when the thread priority changes
|
||||
/// </summary>
|
||||
public event EventHandler ThreadPriorityChanged;
|
||||
|
||||
/// <summary>
|
||||
/// An event that is activated when the throttle speed changes
|
||||
/// </summary>
|
||||
public event EventHandler ThrottleSpeedChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The possible states for the live control
|
||||
/// </summary>
|
||||
public enum LiveControlState
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the backups are running
|
||||
/// </summary>
|
||||
Running,
|
||||
/// <summary>
|
||||
/// Indicates that the backups are currently suspended
|
||||
/// </summary>
|
||||
Paused
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current control state
|
||||
/// </summary>
|
||||
private LiveControlState m_state;
|
||||
|
||||
/// <summary>
|
||||
/// A value that indicates if the current pause state is caused by being suspended
|
||||
/// </summary>
|
||||
private bool m_pausedForSuspend = false;
|
||||
|
||||
/// <summary>
|
||||
/// The time to pause for, used to ensure that a user set pause can override the suspend pause
|
||||
/// </summary>
|
||||
private DateTime m_suspendMinimumPause = new DateTime(0);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current state for the control
|
||||
/// </summary>
|
||||
public LiveControlState State { get { return m_state; } }
|
||||
|
||||
public bool IsPaused => State == LiveControlState.Paused;
|
||||
|
||||
/// <summary>
|
||||
/// The internal variable that tracks the the priority
|
||||
/// </summary>
|
||||
private System.Threading.ThreadPriority? m_priority;
|
||||
|
||||
/// <summary>
|
||||
/// The internal variable that tracks the upload limit
|
||||
/// </summary>
|
||||
private long? m_uploadLimit;
|
||||
|
||||
/// <summary>
|
||||
/// The internal variable that tracks the download limit
|
||||
/// </summary>
|
||||
private long? m_downloadLimit;
|
||||
|
||||
/// <summary>
|
||||
/// The object that ensures concurrent operations
|
||||
/// </summary>
|
||||
private readonly object m_lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current overridden thread priority
|
||||
/// </summary>
|
||||
public System.Threading.ThreadPriority? ThreadPriority
|
||||
{
|
||||
get { return m_priority; }
|
||||
set
|
||||
{
|
||||
if (m_priority != value)
|
||||
{
|
||||
m_priority = value;
|
||||
if (ThreadPriorityChanged != null)
|
||||
ThreadPriorityChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current upload limit in bps
|
||||
/// </summary>
|
||||
public long? UploadLimit
|
||||
{
|
||||
get { return m_uploadLimit; }
|
||||
set
|
||||
{
|
||||
if (m_uploadLimit != value)
|
||||
{
|
||||
m_uploadLimit = value;
|
||||
if (ThrottleSpeedChanged != null)
|
||||
ThrottleSpeedChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the download limit in bps
|
||||
/// </summary>
|
||||
public long? DownloadLimit
|
||||
{
|
||||
get { return m_downloadLimit; }
|
||||
set
|
||||
{
|
||||
if (m_downloadLimit != value)
|
||||
{
|
||||
m_downloadLimit = value;
|
||||
if (ThrottleSpeedChanged != null)
|
||||
ThrottleSpeedChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The timer that is activated after a pause period.
|
||||
/// </summary>
|
||||
private System.Threading.Timer m_waitTimer;
|
||||
|
||||
/// <summary>
|
||||
/// The time that the current pause is expected to expire
|
||||
/// </summary>
|
||||
private DateTime m_waitTimeExpiration = new DateTime(0);
|
||||
|
||||
/// <summary>
|
||||
/// The connection to use
|
||||
/// </summary>
|
||||
private readonly Connection m_connection;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the LiveControl
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection to use</param>
|
||||
public LiveControls(Connection connection)
|
||||
{
|
||||
m_connection = connection;
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the LiveControl
|
||||
/// </summary>
|
||||
private void Init()
|
||||
{
|
||||
var settings = m_connection.ApplicationSettings;
|
||||
m_state = LiveControlState.Running;
|
||||
m_waitTimer = new System.Threading.Timer(m_waitTimer_Tick, this, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.StartupDelayDuration) && settings.StartupDelayDuration != "0")
|
||||
{
|
||||
long milliseconds = 0;
|
||||
try { milliseconds = (long)Duplicati.Library.Utility.Timeparser.ParseTimeSpan(settings.StartupDelayDuration).TotalMilliseconds; }
|
||||
catch { }
|
||||
|
||||
if (milliseconds > 0)
|
||||
{
|
||||
m_waitTimeExpiration = DateTime.Now.AddMilliseconds(milliseconds);
|
||||
m_waitTimer.Change(milliseconds, System.Threading.Timeout.Infinite);
|
||||
m_state = LiveControlState.Paused;
|
||||
}
|
||||
}
|
||||
|
||||
m_priority = settings.ThreadPriorityOverride;
|
||||
if (!string.IsNullOrEmpty(settings.DownloadSpeedLimit))
|
||||
try
|
||||
{
|
||||
m_downloadLimit = Library.Utility.Sizeparser.ParseSize(settings.DownloadSpeedLimit, "kb");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Library.Logging.Log.WriteErrorMessage(LOGTAG, "ParseDownloadLimitError", ex, "Failed to parse download limit: {0}", settings.DownloadSpeedLimit);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.UploadSpeedLimit))
|
||||
try
|
||||
{
|
||||
m_uploadLimit = Library.Utility.Sizeparser.ParseSize(settings.UploadSpeedLimit, "kb");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Library.Logging.Log.WriteErrorMessage(LOGTAG, "ParseUploadLimitError", ex, "Failed to parse upload limit: {0}", settings.UploadSpeedLimit);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (OperatingSystem.IsWindows())
|
||||
RegisterHibernateMonitor();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event that occurs when the timeout duration is exceeded
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
private void m_waitTimer_Tick(object sender)
|
||||
{
|
||||
lock (m_lock)
|
||||
Resume();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper to reset the timeout timer
|
||||
/// </summary>
|
||||
/// <param name="timeout">The time to wait</param>
|
||||
private void ResetTimer(string timeout)
|
||||
{
|
||||
lock (m_lock)
|
||||
if (!string.IsNullOrEmpty(timeout))
|
||||
{
|
||||
long milliseconds = (long)Duplicati.Library.Utility.Timeparser.ParseTimeSpan(timeout).TotalMilliseconds;
|
||||
m_waitTimeExpiration = DateTime.Now.AddMilliseconds(milliseconds);
|
||||
m_waitTimer.Change(milliseconds, System.Threading.Timeout.Infinite);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_waitTimeExpiration = new DateTime(0);
|
||||
m_waitTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper to set the pause mode
|
||||
/// </summary>
|
||||
private void SetPauseMode()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_state == LiveControlState.Running)
|
||||
{
|
||||
m_state = LiveControlState.Paused;
|
||||
if (StateChanged != null)
|
||||
StateChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the backups until resumed
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
var fireEvent = m_waitTimeExpiration.Ticks != 0 && m_state == LiveControlState.Paused && StateChanged != null;
|
||||
|
||||
ResetTimer(null);
|
||||
|
||||
if (fireEvent)
|
||||
StateChanged(this, null);
|
||||
else
|
||||
SetPauseMode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes a backups to the running state
|
||||
/// </summary>
|
||||
public void Resume()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_state == LiveControlState.Paused)
|
||||
{
|
||||
//Make sure that the timer is cleared
|
||||
ResetTimer(null);
|
||||
|
||||
m_state = LiveControlState.Running;
|
||||
if (StateChanged != null)
|
||||
StateChanged(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the backups for a given period
|
||||
/// </summary>
|
||||
/// <param name="timeout">The duration to wait</param>
|
||||
public void Pause(string timeout)
|
||||
{
|
||||
Pause(Duplicati.Library.Utility.Timeparser.ParseTimeSpan(timeout));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the backups for a given period
|
||||
/// </summary>
|
||||
/// <param name="timeout">The duration to wait</param>
|
||||
public void Pause(TimeSpan timeout)
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
m_waitTimeExpiration = DateTime.Now.AddMilliseconds((long)timeout.TotalMilliseconds);
|
||||
m_waitTimer.Change((long)timeout.TotalMilliseconds, System.Threading.Timeout.Infinite);
|
||||
|
||||
//We change the time, so we issue a new event
|
||||
if (m_state == LiveControlState.Paused && StateChanged != null)
|
||||
StateChanged(this, null);
|
||||
else
|
||||
SetPauseMode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time the current pause is expected to end
|
||||
/// </summary>
|
||||
public DateTime EstimatedPauseEnd { get { return m_waitTimeExpiration; } }
|
||||
|
||||
/// <summary>
|
||||
/// Method for calling a Win32 API
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
private void RegisterHibernateMonitor()
|
||||
{
|
||||
Microsoft.Win32.SystemEvents.PowerModeChanged += new Microsoft.Win32.PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A monitor for detecting when the system hibernates or resumes
|
||||
/// </summary>
|
||||
/// <param name="sender">Unused sender parameter</param>
|
||||
/// <param name="_e">The event information</param>
|
||||
[SupportedOSPlatform("windows")]
|
||||
private void SystemEvents_PowerModeChanged(object sender, object _e)
|
||||
{
|
||||
Microsoft.Win32.PowerModeChangedEventArgs e = _e as Microsoft.Win32.PowerModeChangedEventArgs;
|
||||
if (e == null)
|
||||
return;
|
||||
|
||||
if (e.Mode == Microsoft.Win32.PowerModes.Suspend)
|
||||
{
|
||||
//If we are running, register as being paused due to suspending
|
||||
if (this.m_state == LiveControlState.Running)
|
||||
{
|
||||
this.SetPauseMode();
|
||||
m_pausedForSuspend = true;
|
||||
m_suspendMinimumPause = new DateTime(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_waitTimeExpiration.Ticks != 0)
|
||||
{
|
||||
m_pausedForSuspend = true;
|
||||
m_suspendMinimumPause = this.EstimatedPauseEnd;
|
||||
ResetTimer(null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (e.Mode == Microsoft.Win32.PowerModes.Resume)
|
||||
{
|
||||
//If we have been been paused due to suspending, we un-pause now
|
||||
if (m_pausedForSuspend)
|
||||
{
|
||||
long delayTicks = (m_suspendMinimumPause - DateTime.Now).Ticks;
|
||||
|
||||
var appset = m_connection.ApplicationSettings;
|
||||
if (!string.IsNullOrEmpty(appset.StartupDelayDuration) && appset.StartupDelayDuration != "0")
|
||||
try { delayTicks = Math.Max(delayTicks, Library.Utility.Timeparser.ParseTimeSpan(appset.StartupDelayDuration).Ticks); }
|
||||
catch { }
|
||||
|
||||
if (delayTicks > 0)
|
||||
{
|
||||
this.Pause(TimeSpan.FromTicks(delayTicks));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Resume();
|
||||
}
|
||||
}
|
||||
|
||||
m_pausedForSuspend = false;
|
||||
m_suspendMinimumPause = new DateTime(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+25
-23
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -134,7 +134,7 @@ namespace Duplicati.Server
|
||||
this.ExceptionID = exception.HelpID;
|
||||
else
|
||||
this.ExceptionID = entry.Exception.GetType().FullName;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,15 +154,15 @@ namespace Duplicati.Server
|
||||
{
|
||||
m_buffer = new T[size];
|
||||
if (initial != null)
|
||||
foreach(var t in initial)
|
||||
foreach (var t in initial)
|
||||
this.Enqueue(t);
|
||||
}
|
||||
|
||||
|
||||
public int Length { get { return m_length; } }
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
{
|
||||
m_key++;
|
||||
m_buffer[m_head] = item;
|
||||
@@ -178,7 +178,7 @@ namespace Duplicati.Server
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
var k = m_key;
|
||||
for(var i = 0; i < m_length; i++)
|
||||
for (var i = 0; i < m_length; i++)
|
||||
if (m_key != k)
|
||||
throw new InvalidOperationException("Buffer was modified while reading");
|
||||
else
|
||||
@@ -194,7 +194,7 @@ namespace Duplicati.Server
|
||||
|
||||
public T[] FlatArray(Func<T, bool> filter = null)
|
||||
{
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
if (filter == null)
|
||||
return this.ToArray();
|
||||
else
|
||||
@@ -222,7 +222,7 @@ namespace Duplicati.Server
|
||||
|
||||
public void RenewTimeout(LogMessageType type)
|
||||
{
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
{
|
||||
m_timeouts[(int)type] = DateTime.Now.AddSeconds(30);
|
||||
m_anytimeouts = true;
|
||||
@@ -249,12 +249,12 @@ namespace Duplicati.Server
|
||||
UpdateLogLevel();
|
||||
|
||||
offset = offset.ToUniversalTime();
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_buffer == null)
|
||||
return new LogEntry[0];
|
||||
|
||||
return m_buffer.FlatArray((x) => x.When > offset && x.Type >= level );
|
||||
|
||||
return m_buffer.FlatArray((x) => x.When > offset && x.Type >= level);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,18 +263,20 @@ namespace Duplicati.Server
|
||||
RenewTimeout(level);
|
||||
UpdateLogLevel();
|
||||
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_buffer == null)
|
||||
return new LogEntry[0];
|
||||
|
||||
var buffer = m_buffer.FlatArray((x) => x.ID > id && x.Type >= level );
|
||||
|
||||
var buffer = m_buffer.FlatArray((x) => x.ID > id && x.Type >= level);
|
||||
// Return the <page_size> newest entries
|
||||
if (buffer.Length > pagesize) {
|
||||
if (buffer.Length > pagesize)
|
||||
{
|
||||
var index = buffer.Length - pagesize;
|
||||
return buffer.Skip(index).Take(pagesize).ToArray();
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
@@ -284,13 +286,13 @@ namespace Duplicati.Server
|
||||
{
|
||||
var i = 0;
|
||||
return (from n in m_timeouts
|
||||
let ix = i++
|
||||
where n > DateTime.Now
|
||||
select ix).ToArray();
|
||||
let ix = i++
|
||||
where n > DateTime.Now
|
||||
select ix).ToArray();
|
||||
}
|
||||
|
||||
private void UpdateLogLevel()
|
||||
{
|
||||
{
|
||||
m_logLevel =
|
||||
(LogMessageType)(GetActiveTimeouts().Union(new int[] { (int)m_serverloglevel }).Min());
|
||||
}
|
||||
@@ -300,9 +302,9 @@ namespace Duplicati.Server
|
||||
|
||||
public void WriteMessage(Duplicati.Library.Logging.LogEntry entry)
|
||||
{
|
||||
if (entry.Level < m_logLevel)
|
||||
if (entry.Level < m_logLevel)
|
||||
return;
|
||||
|
||||
|
||||
if (m_serverfile != null && entry.Level >= m_serverloglevel)
|
||||
try
|
||||
{
|
||||
@@ -312,7 +314,7 @@ namespace Duplicati.Server
|
||||
{
|
||||
}
|
||||
|
||||
lock(m_lock)
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_anytimeouts)
|
||||
{
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace Duplicati.Library.RestAPI;
|
||||
|
||||
public interface INotificationUpdateService
|
||||
{
|
||||
/// <summary>
|
||||
/// An event ID that increases whenever the database is updated
|
||||
/// </summary>
|
||||
long LastDataUpdateId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// An event ID that increases whenever a notification is updated
|
||||
/// </summary>
|
||||
long LastNotificationUpdateId { get; }
|
||||
|
||||
void IncrementLastDataUpdateId();
|
||||
void IncrementLastNotificationUpdateId();
|
||||
}
|
||||
|
||||
public class NotificationUpdateService : INotificationUpdateService
|
||||
{
|
||||
/// <summary>
|
||||
/// An event ID that increases whenever the database is updated
|
||||
/// </summary>
|
||||
public long LastDataUpdateId { get; private set; } = 0;
|
||||
|
||||
private readonly object _lastDataUpdateIdLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// An event ID that increases whenever a notification is updated
|
||||
/// </summary>
|
||||
public long LastNotificationUpdateId { get; private set; } = 0;
|
||||
|
||||
private readonly object _lastNotificationUpdateIdLock = new();
|
||||
|
||||
public void IncrementLastDataUpdateId()
|
||||
{
|
||||
lock (_lastDataUpdateIdLock)
|
||||
{
|
||||
LastDataUpdateId++;
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementLastNotificationUpdateId()
|
||||
{
|
||||
lock (_lastNotificationUpdateIdLock)
|
||||
{
|
||||
LastNotificationUpdateId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,392 +18,435 @@
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Duplicati.Library.Utility;
|
||||
|
||||
using Duplicati.Server.Serialization.Interface;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles scheduled runs of backups
|
||||
/// </summary>
|
||||
public class Scheduler
|
||||
{
|
||||
private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType<Scheduler>();
|
||||
|
||||
/// <summary>
|
||||
/// The thread that runs the scheduler
|
||||
/// </summary>
|
||||
private readonly Thread m_thread;
|
||||
/// <summary>
|
||||
/// A termination flag
|
||||
/// </summary>
|
||||
private volatile bool m_terminate;
|
||||
/// <summary>
|
||||
/// The worker thread that is invoked to do work
|
||||
/// </summary>
|
||||
private readonly WorkerThread<Runner.IRunnerData> m_worker;
|
||||
/// <summary>
|
||||
/// The wait event
|
||||
/// </summary>
|
||||
private readonly AutoResetEvent m_event;
|
||||
/// <summary>
|
||||
/// The data synchronization lock
|
||||
/// </summary>
|
||||
private readonly object m_lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// An event that is raised when the schedule changes
|
||||
/// </summary>
|
||||
public event EventHandler NewSchedule;
|
||||
|
||||
/// <summary>
|
||||
/// The currently scheduled items
|
||||
/// </summary>
|
||||
private KeyValuePair<DateTime, ISchedule>[] m_schedule;
|
||||
|
||||
/// <summary>
|
||||
/// List of update tasks, used to set the timestamp on the schedule once completed
|
||||
/// </summary>
|
||||
private readonly Dictionary<Server.Runner.IRunnerData, Tuple<ISchedule, DateTime, DateTime>> m_updateTasks;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new scheduler
|
||||
/// </summary>
|
||||
/// <param name="worker">The worker thread</param>
|
||||
public Scheduler(WorkerThread<Server.Runner.IRunnerData> worker)
|
||||
{
|
||||
m_thread = new Thread(new ThreadStart(Runner));
|
||||
m_worker = worker;
|
||||
m_worker.CompletedWork += OnCompleted;
|
||||
m_worker.StartingWork += OnStartingWork;
|
||||
m_schedule = new KeyValuePair<DateTime, ISchedule>[0];
|
||||
m_terminate = false;
|
||||
m_event = new AutoResetEvent(false);
|
||||
m_updateTasks = new Dictionary<Server.Runner.IRunnerData, Tuple<ISchedule, DateTime, DateTime>>();
|
||||
m_thread.IsBackground = true;
|
||||
m_thread.Name = "TaskScheduler";
|
||||
m_thread.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces the scheduler to re-evaluate the order.
|
||||
/// Call this method if something changes
|
||||
/// </summary>
|
||||
public void Reschedule()
|
||||
{
|
||||
m_event.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot copy of the current schedule list
|
||||
/// </summary>
|
||||
public List<KeyValuePair<DateTime, ISchedule>> Schedule
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (m_lock)
|
||||
return m_schedule.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot copy of the current worker queue, that is items that are scheduled, but waiting for execution
|
||||
/// </summary>
|
||||
public List<Runner.IRunnerData> WorkerQueue
|
||||
{
|
||||
get
|
||||
{
|
||||
return (from t in m_worker.CurrentTasks where t != null select t).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminates the thread. Any items still in queue will be removed
|
||||
/// </summary>
|
||||
/// <param name="wait">True if the call should block until the thread has exited, false otherwise</param>
|
||||
public void Terminate(bool wait)
|
||||
{
|
||||
m_terminate = true;
|
||||
m_event.Set();
|
||||
|
||||
if (wait)
|
||||
m_thread.Join();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next valid date, given the start and the interval
|
||||
/// </summary>
|
||||
/// <param name="basetime">The base time</param>
|
||||
/// <param name="firstdate">The first allowed date</param>
|
||||
/// <param name="repetition">The repetition interval</param>
|
||||
/// <param name="allowedDays">The days the backup is allowed to run</param>
|
||||
/// <returns>The next valid date, or throws an exception if no such date can be found</returns>
|
||||
public static DateTime GetNextValidTime(DateTime basetime, DateTime firstdate, string repetition, DayOfWeek[] allowedDays)
|
||||
{
|
||||
var res = basetime;
|
||||
|
||||
var i = 50000;
|
||||
while (res < firstdate && i-- > 0)
|
||||
res = Timeparser.ParseTimeInterval(repetition, res);
|
||||
|
||||
// If we arrived somewhere after the first allowed date
|
||||
if (res >= firstdate)
|
||||
{
|
||||
var ts = Timeparser.ParseTimeSpan(repetition);
|
||||
|
||||
if (ts.TotalDays >= 1)
|
||||
{
|
||||
// We jump in days, so we pick the first valid day after firstdate
|
||||
|
||||
for (var n = 0; n < 8; n++)
|
||||
if (IsDateAllowed(res, allowedDays))
|
||||
break;
|
||||
else
|
||||
res = res.AddDays(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We jump less than a day, so we keep adding the repetition until
|
||||
// we hit a valid day
|
||||
|
||||
i = 50000;
|
||||
while (!IsDateAllowed(res, allowedDays) && i-- > 0)
|
||||
res = Timeparser.ParseTimeInterval(repetition, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsDateAllowed(res, allowedDays) || res < firstdate)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (allowedDays != null)
|
||||
foreach (DayOfWeek w in allowedDays)
|
||||
{
|
||||
if (sb.Length != 0)
|
||||
sb.Append(", ");
|
||||
sb.Append(w.ToString());
|
||||
}
|
||||
|
||||
throw new Exception(Strings.Scheduler.InvalidTimeSetupError(basetime, repetition, sb.ToString()));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private void OnCompleted(WorkerThread<Runner.IRunnerData> worker, Runner.IRunnerData task)
|
||||
{
|
||||
Tuple<ISchedule, DateTime, DateTime> t = null;
|
||||
lock(m_lock)
|
||||
{
|
||||
if (task != null && m_updateTasks.TryGetValue(task, out t))
|
||||
m_updateTasks.Remove(task);
|
||||
}
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
t.Item1.Time = t.Item2;
|
||||
t.Item1.LastRun = t.Item3;
|
||||
Program.DataConnection.AddOrUpdateSchedule(t.Item1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnStartingWork(WorkerThread<Runner.IRunnerData> worker, Runner.IRunnerData task)
|
||||
{
|
||||
if (task is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock(m_lock)
|
||||
{
|
||||
if (m_updateTasks.TryGetValue(task, out Tuple<ISchedule, DateTime, DateTime> scheduleInfo))
|
||||
{
|
||||
// Item2 is the scheduled start time (Time in the Schedule table).
|
||||
// Item3 is the actual start time (LastRun in the Schedule table).
|
||||
m_updateTasks[task] = Tuple.Create(scheduleInfo.Item1, scheduleInfo.Item2, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The actual scheduling procedure
|
||||
/// </summary>
|
||||
private void Runner()
|
||||
{
|
||||
var scheduled = new Dictionary<long, KeyValuePair<long, DateTime>>();
|
||||
while (!m_terminate)
|
||||
{
|
||||
//TODO: As this is executed repeatedly we should cache it
|
||||
// to avoid frequent db lookups
|
||||
|
||||
//Determine schedule list
|
||||
var lst = Program.DataConnection.Schedules;
|
||||
foreach(var sc in lst)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(sc.Repeat))
|
||||
{
|
||||
KeyValuePair<long, DateTime> startkey;
|
||||
|
||||
DateTime last = new DateTime(0, DateTimeKind.Utc);
|
||||
DateTime start;
|
||||
var scticks = sc.Time.Ticks;
|
||||
|
||||
if (!scheduled.TryGetValue(sc.ID, out startkey) || startkey.Key != scticks)
|
||||
{
|
||||
start = new DateTime(scticks, DateTimeKind.Utc);
|
||||
last = sc.LastRun;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = startkey.Value;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Recover from timedrift issues by overriding the dates if the last run date is in the future.
|
||||
if (last > DateTime.UtcNow)
|
||||
{
|
||||
start = DateTime.UtcNow;
|
||||
last = DateTime.UtcNow;
|
||||
}
|
||||
start = GetNextValidTime(start, last, sc.Repeat, sc.AllowedDays);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Program.DataConnection.LogError(sc.ID.ToString(), "Scheduler failed to find next date", ex);
|
||||
}
|
||||
|
||||
//If time is exceeded, run it now
|
||||
if (start <= DateTime.UtcNow)
|
||||
{
|
||||
var jobsToRun = new List<Server.Runner.IRunnerData>();
|
||||
//TODO: Cache this to avoid frequent lookups
|
||||
foreach(var id in Program.DataConnection.GetBackupIDsForTags(sc.Tags).Distinct().Select(x => x.ToString()))
|
||||
{
|
||||
//See if it is already queued
|
||||
var tmplst = from n in m_worker.CurrentTasks
|
||||
where n.Operation == Duplicati.Server.Serialization.DuplicatiOperation.Backup
|
||||
select n.Backup;
|
||||
var tastTemp = m_worker.CurrentTask;
|
||||
if (tastTemp != null && tastTemp.Operation == Duplicati.Server.Serialization.DuplicatiOperation.Backup)
|
||||
tmplst = tmplst.Union(new [] { tastTemp.Backup });
|
||||
|
||||
//If it is not already in queue, put it there
|
||||
if (!tmplst.Any(x => x.ID == id))
|
||||
{
|
||||
var entry = Program.DataConnection.GetBackup(id);
|
||||
if (entry != null)
|
||||
{
|
||||
Dictionary<string, string> options = Duplicati.Server.Runner.GetCommonOptions();
|
||||
Duplicati.Server.Runner.ApplyOptions(entry, options);
|
||||
if ((new Duplicati.Library.Main.Options(options)).DisableOnBattery && (Duplicati.Library.Utility.Power.PowerSupply.GetSource() == Duplicati.Library.Utility.Power.PowerSupply.Source.Battery))
|
||||
{
|
||||
Duplicati.Library.Logging.Log.WriteInformationMessage(LOGTAG, "BackupDisabledOnBattery", "Scheduled backup disabled while on battery power.");
|
||||
}
|
||||
else
|
||||
{
|
||||
jobsToRun.Add(Server.Runner.CreateTask(Duplicati.Server.Serialization.DuplicatiOperation.Backup, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate next time, by finding the first entry later than now
|
||||
try
|
||||
{
|
||||
start = GetNextValidTime(start, new DateTime(Math.Max(DateTime.UtcNow.AddSeconds(1).Ticks, start.AddSeconds(1).Ticks), DateTimeKind.Utc), sc.Repeat, sc.AllowedDays);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Program.DataConnection.LogError(sc.ID.ToString(), "Scheduler failed to find next date", ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
Server.Runner.IRunnerData lastJob = jobsToRun.LastOrDefault();
|
||||
if (lastJob != null)
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
// The actual last run time will be updated when the StartingWork event is raised.
|
||||
m_updateTasks[lastJob] = new Tuple<ISchedule, DateTime, DateTime>(sc, start, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var job in jobsToRun)
|
||||
m_worker.AddTask(job);
|
||||
|
||||
if (start < DateTime.UtcNow)
|
||||
{
|
||||
//TODO: Report this somehow
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
scheduled[sc.ID] = new KeyValuePair<long,DateTime>(scticks, start);
|
||||
}
|
||||
}
|
||||
|
||||
var existing = lst.ToDictionary(x => x.ID);
|
||||
//Sort them, lock as we assign the m_schedule variable
|
||||
lock(m_lock)
|
||||
m_schedule = (from n in scheduled
|
||||
where existing.ContainsKey(n.Key)
|
||||
orderby n.Value.Value
|
||||
select new KeyValuePair<DateTime, ISchedule>(n.Value.Value, existing[n.Key])).ToArray();
|
||||
|
||||
// Remove unused entries
|
||||
foreach(var c in (from n in scheduled where !existing.ContainsKey(n.Key) select n.Key).ToArray())
|
||||
scheduled.Remove(c);
|
||||
|
||||
//Raise event if needed
|
||||
if (NewSchedule != null)
|
||||
NewSchedule(this, null);
|
||||
|
||||
int waittime = 0;
|
||||
|
||||
//Figure out a sensible amount of time to sleep the thread
|
||||
if (scheduled.Count > 0)
|
||||
{
|
||||
//When is the next run scheduled?
|
||||
TimeSpan nextrun = scheduled.Values.Min((x) => x.Value) - DateTime.UtcNow;
|
||||
if (nextrun.TotalMilliseconds < 0)
|
||||
continue;
|
||||
|
||||
//Don't sleep for more than 5 minutes
|
||||
waittime = (int)Math.Min(nextrun.TotalMilliseconds, 60 * 1000 * 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
//No tasks, check back later
|
||||
waittime = 60 * 1000;
|
||||
}
|
||||
|
||||
//Waiting on the event, enables a wakeup call from termination
|
||||
// never use waittime = 0
|
||||
m_event.WaitOne(Math.Max(100, waittime), false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the time is at an allowed weekday, false otherwise
|
||||
/// </summary>
|
||||
/// <param name="time">The time to evaluate</param>
|
||||
/// <param name="allowedDays">The allowed days</param>
|
||||
/// <returns>True if the backup is allowed to run, false otherwise</returns>
|
||||
private static bool IsDateAllowed(DateTime time, DayOfWeek[] allowedDays)
|
||||
{
|
||||
var localTime = time.ToLocalTime();
|
||||
if (allowedDays == null || allowedDays.Length == 0)
|
||||
return true;
|
||||
else
|
||||
return Array.IndexOf<DayOfWeek>(allowedDays, localTime.DayOfWeek) >= 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Duplicati.Library.Utility;
|
||||
using Duplicati.Library.RestAPI;
|
||||
|
||||
// TODO: Rewrite this class.
|
||||
// It should just signal what new backups to run, and not mix with the worker thread.
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles scheduled runs of backups
|
||||
/// </summary>
|
||||
public class Scheduler
|
||||
{
|
||||
private static readonly string LOGTAG = Duplicati.Library.Logging.Log.LogTagFromType<Scheduler>();
|
||||
|
||||
/// <summary>
|
||||
/// The thread that runs the scheduler
|
||||
/// </summary>
|
||||
private Thread m_thread;
|
||||
|
||||
/// <summary>
|
||||
/// A termination flag
|
||||
/// </summary>
|
||||
private volatile bool m_terminate;
|
||||
|
||||
/// <summary>
|
||||
/// The worker thread that is invoked to do work
|
||||
/// </summary>
|
||||
private WorkerThread<Runner.IRunnerData> m_worker;
|
||||
|
||||
/// <summary>
|
||||
/// The wait event
|
||||
/// </summary>
|
||||
private AutoResetEvent m_event;
|
||||
|
||||
/// <summary>
|
||||
/// The data synchronization lock
|
||||
/// </summary>
|
||||
private readonly object m_lock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// An event that is raised when the schedule changes
|
||||
/// </summary>
|
||||
public event EventHandler NewSchedule;
|
||||
|
||||
/// <summary>
|
||||
/// The currently scheduled items
|
||||
/// </summary>
|
||||
private KeyValuePair<DateTime, ISchedule>[] m_schedule;
|
||||
|
||||
/// <summary>
|
||||
/// List of update tasks, used to set the timestamp on the schedule once completed
|
||||
/// </summary>
|
||||
private Dictionary<Server.Runner.IRunnerData, Tuple<ISchedule, DateTime, DateTime>> m_updateTasks;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new scheduler
|
||||
/// </summary>
|
||||
public Scheduler()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes scheduler
|
||||
/// </summary>
|
||||
/// <param name="worker">The worker thread</param>
|
||||
public void Init(WorkerThread<Runner.IRunnerData> worker)
|
||||
{
|
||||
m_thread = new Thread(new ThreadStart(Runner));
|
||||
m_worker = worker;
|
||||
m_worker.CompletedWork += OnCompleted;
|
||||
m_worker.StartingWork += OnStartingWork;
|
||||
m_schedule = new KeyValuePair<DateTime, ISchedule>[0];
|
||||
m_terminate = false;
|
||||
m_event = new AutoResetEvent(false);
|
||||
m_updateTasks = new Dictionary<Server.Runner.IRunnerData, Tuple<ISchedule, DateTime, DateTime>>();
|
||||
m_thread.IsBackground = true;
|
||||
m_thread.Name = "TaskScheduler";
|
||||
m_thread.Start();
|
||||
}
|
||||
|
||||
public IList<Tuple<long, string>> GetSchedulerQueueIds()
|
||||
{
|
||||
return (from n in WorkerQueue
|
||||
where n.Backup != null
|
||||
select new Tuple<long, string>(n.TaskID, n.Backup.ID)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces the scheduler to re-evaluate the order.
|
||||
/// Call this method if something changes
|
||||
/// </summary>
|
||||
public void Reschedule()
|
||||
{
|
||||
m_event.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot copy of the current schedule list
|
||||
/// </summary>
|
||||
public List<KeyValuePair<DateTime, ISchedule>> Schedule
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (m_lock)
|
||||
return m_schedule.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A snapshot copy of the current worker queue, that is items that are scheduled, but waiting for execution
|
||||
/// </summary>
|
||||
public List<Runner.IRunnerData> WorkerQueue
|
||||
{
|
||||
get { return (from t in m_worker.CurrentTasks where t != null select t).ToList(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminates the thread. Any items still in queue will be removed
|
||||
/// </summary>
|
||||
/// <param name="wait">True if the call should block until the thread has exited, false otherwise</param>
|
||||
public void Terminate(bool wait)
|
||||
{
|
||||
m_terminate = true;
|
||||
m_event.Set();
|
||||
|
||||
if (wait)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_thread.Join();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next valid date, given the start and the interval
|
||||
/// </summary>
|
||||
/// <param name="basetime">The base time</param>
|
||||
/// <param name="firstdate">The first allowed date</param>
|
||||
/// <param name="repetition">The repetition interval</param>
|
||||
/// <param name="allowedDays">The days the backup is allowed to run</param>
|
||||
/// <returns>The next valid date, or throws an exception if no such date can be found</returns>
|
||||
public static DateTime GetNextValidTime(DateTime basetime, DateTime firstdate, string repetition,
|
||||
DayOfWeek[] allowedDays)
|
||||
{
|
||||
var res = basetime;
|
||||
|
||||
var i = 50000;
|
||||
while (res < firstdate && i-- > 0)
|
||||
res = Timeparser.ParseTimeInterval(repetition, res);
|
||||
|
||||
// If we arrived somewhere after the first allowed date
|
||||
if (res >= firstdate)
|
||||
{
|
||||
var ts = Timeparser.ParseTimeSpan(repetition);
|
||||
|
||||
if (ts.TotalDays >= 1)
|
||||
{
|
||||
// We jump in days, so we pick the first valid day after firstdate
|
||||
|
||||
for (var n = 0; n < 8; n++)
|
||||
if (IsDateAllowed(res, allowedDays))
|
||||
break;
|
||||
else
|
||||
res = res.AddDays(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We jump less than a day, so we keep adding the repetition until
|
||||
// we hit a valid day
|
||||
|
||||
i = 50000;
|
||||
while (!IsDateAllowed(res, allowedDays) && i-- > 0)
|
||||
res = Timeparser.ParseTimeInterval(repetition, res);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsDateAllowed(res, allowedDays) || res < firstdate)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (allowedDays != null)
|
||||
foreach (DayOfWeek w in allowedDays)
|
||||
{
|
||||
if (sb.Length != 0)
|
||||
sb.Append(", ");
|
||||
sb.Append(w.ToString());
|
||||
}
|
||||
|
||||
throw new Exception(Strings.Scheduler.InvalidTimeSetupError(basetime, repetition, sb.ToString()));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private void OnCompleted(WorkerThread<Runner.IRunnerData> worker, Runner.IRunnerData task)
|
||||
{
|
||||
Tuple<ISchedule, DateTime, DateTime> t = null;
|
||||
lock (m_lock)
|
||||
{
|
||||
if (task != null && m_updateTasks.TryGetValue(task, out t))
|
||||
m_updateTasks.Remove(task);
|
||||
}
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
t.Item1.Time = t.Item2;
|
||||
t.Item1.LastRun = t.Item3;
|
||||
FIXMEGlobal.DataConnection.AddOrUpdateSchedule(t.Item1);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStartingWork(WorkerThread<Runner.IRunnerData> worker, Runner.IRunnerData task)
|
||||
{
|
||||
if (task is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (m_lock)
|
||||
{
|
||||
if (m_updateTasks.TryGetValue(task, out Tuple<ISchedule, DateTime, DateTime> scheduleInfo))
|
||||
{
|
||||
// Item2 is the scheduled start time (Time in the Schedule table).
|
||||
// Item3 is the actual start time (LastRun in the Schedule table).
|
||||
m_updateTasks[task] = Tuple.Create(scheduleInfo.Item1, scheduleInfo.Item2, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The actual scheduling procedure
|
||||
/// </summary>
|
||||
private void Runner()
|
||||
{
|
||||
var scheduled = new Dictionary<long, KeyValuePair<long, DateTime>>();
|
||||
while (!m_terminate)
|
||||
{
|
||||
//TODO: As this is executed repeatedly we should cache it
|
||||
// to avoid frequent db lookups
|
||||
|
||||
//Determine schedule list
|
||||
var lst = FIXMEGlobal.DataConnection.Schedules;
|
||||
foreach (var sc in lst)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(sc.Repeat))
|
||||
{
|
||||
KeyValuePair<long, DateTime> startkey;
|
||||
|
||||
DateTime last = new DateTime(0, DateTimeKind.Utc);
|
||||
DateTime start;
|
||||
var scticks = sc.Time.Ticks;
|
||||
|
||||
if (!scheduled.TryGetValue(sc.ID, out startkey) || startkey.Key != scticks)
|
||||
{
|
||||
start = new DateTime(scticks, DateTimeKind.Utc);
|
||||
last = sc.LastRun;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = startkey.Value;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Recover from timedrift issues by overriding the dates if the last run date is in the future.
|
||||
if (last > DateTime.UtcNow)
|
||||
{
|
||||
start = DateTime.UtcNow;
|
||||
last = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
start = GetNextValidTime(start, last, sc.Repeat, sc.AllowedDays);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FIXMEGlobal.DataConnection.LogError(sc.ID.ToString(), "Scheduler failed to find next date",
|
||||
ex);
|
||||
}
|
||||
|
||||
//If time is exceeded, run it now
|
||||
if (start <= DateTime.UtcNow)
|
||||
{
|
||||
var jobsToRun = new List<Server.Runner.IRunnerData>();
|
||||
//TODO: Cache this to avoid frequent lookups
|
||||
foreach (var id in FIXMEGlobal.DataConnection.GetBackupIDsForTags(sc.Tags).Distinct()
|
||||
.Select(x => x.ToString()))
|
||||
{
|
||||
//See if it is already queued
|
||||
var tmplst = from n in m_worker.CurrentTasks
|
||||
where n.Operation == Duplicati.Server.Serialization.DuplicatiOperation.Backup
|
||||
select n.Backup;
|
||||
var tastTemp = m_worker.CurrentTask;
|
||||
if (tastTemp != null && tastTemp.Operation ==
|
||||
Duplicati.Server.Serialization.DuplicatiOperation.Backup)
|
||||
tmplst = tmplst.Union(new[] { tastTemp.Backup });
|
||||
|
||||
//If it is not already in queue, put it there
|
||||
if (!tmplst.Any(x => x.ID == id))
|
||||
{
|
||||
var entry = FIXMEGlobal.DataConnection.GetBackup(id);
|
||||
if (entry != null)
|
||||
{
|
||||
Dictionary<string, string> options = Duplicati.Server.Runner.GetCommonOptions();
|
||||
Duplicati.Server.Runner.ApplyOptions(entry, options);
|
||||
if ((new Duplicati.Library.Main.Options(options)).DisableOnBattery &&
|
||||
(Duplicati.Library.Utility.Power.PowerSupply.GetSource() ==
|
||||
Duplicati.Library.Utility.Power.PowerSupply.Source.Battery))
|
||||
{
|
||||
Duplicati.Library.Logging.Log.WriteInformationMessage(LOGTAG,
|
||||
"BackupDisabledOnBattery",
|
||||
"Scheduled backup disabled while on battery power.");
|
||||
}
|
||||
else
|
||||
{
|
||||
jobsToRun.Add(Server.Runner.CreateTask(
|
||||
Duplicati.Server.Serialization.DuplicatiOperation.Backup, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate next time, by finding the first entry later than now
|
||||
try
|
||||
{
|
||||
start = GetNextValidTime(start,
|
||||
new DateTime(
|
||||
Math.Max(DateTime.UtcNow.AddSeconds(1).Ticks, start.AddSeconds(1).Ticks),
|
||||
DateTimeKind.Utc), sc.Repeat, sc.AllowedDays);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FIXMEGlobal.DataConnection.LogError(sc.ID.ToString(),
|
||||
"Scheduler failed to find next date", ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
Server.Runner.IRunnerData lastJob = jobsToRun.LastOrDefault();
|
||||
if (lastJob != null)
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
// The actual last run time will be updated when the StartingWork event is raised.
|
||||
m_updateTasks[lastJob] =
|
||||
new Tuple<ISchedule, DateTime, DateTime>(sc, start, DateTime.UtcNow);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var job in jobsToRun)
|
||||
m_worker.AddTask(job);
|
||||
|
||||
if (start < DateTime.UtcNow)
|
||||
{
|
||||
//TODO: Report this somehow
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
scheduled[sc.ID] = new KeyValuePair<long, DateTime>(scticks, start);
|
||||
}
|
||||
}
|
||||
|
||||
var existing = lst.ToDictionary(x => x.ID);
|
||||
//Sort them, lock as we assign the m_schedule variable
|
||||
lock (m_lock)
|
||||
m_schedule = (from n in scheduled
|
||||
where existing.ContainsKey(n.Key)
|
||||
orderby n.Value.Value
|
||||
select new KeyValuePair<DateTime, ISchedule>(n.Value.Value, existing[n.Key])).ToArray();
|
||||
|
||||
// Remove unused entries
|
||||
foreach (var c in (from n in scheduled where !existing.ContainsKey(n.Key) select n.Key).ToArray())
|
||||
scheduled.Remove(c);
|
||||
|
||||
//Raise event if needed
|
||||
// TODO: This triggers a new data event and a reconnect with long-poll
|
||||
if (NewSchedule != null)
|
||||
NewSchedule(this, null);
|
||||
|
||||
int waittime = 0;
|
||||
|
||||
//Figure out a sensible amount of time to sleep the thread
|
||||
if (scheduled.Count > 0)
|
||||
{
|
||||
//When is the next run scheduled?
|
||||
TimeSpan nextrun = scheduled.Values.Min((x) => x.Value) - DateTime.UtcNow;
|
||||
if (nextrun.TotalMilliseconds < 0)
|
||||
continue;
|
||||
|
||||
//Don't sleep for more than 5 minutes
|
||||
waittime = (int)Math.Min(nextrun.TotalMilliseconds, 60 * 1000 * 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: This should be handled with events, instead of one wakeup per minute
|
||||
//No tasks, check back later
|
||||
waittime = 60 * 1000;
|
||||
}
|
||||
|
||||
//Waiting on the event, enables a wakeup call from termination
|
||||
// never use waittime = 0
|
||||
m_event.WaitOne(Math.Max(100, waittime), false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the time is at an allowed weekday, false otherwise
|
||||
/// </summary>
|
||||
/// <param name="time">The time to evaluate</param>
|
||||
/// <param name="allowedDays">The allowed days</param>
|
||||
/// <returns>True if the backup is allowed to run, false otherwise</returns>
|
||||
private static bool IsDateAllowed(DateTime time, DayOfWeek[] allowedDays)
|
||||
{
|
||||
var localTime = time.ToLocalTime();
|
||||
if (allowedDays == null || allowedDays.Length == 0)
|
||||
return true;
|
||||
else
|
||||
return Array.IndexOf<DayOfWeek>(allowedDays, localTime.DayOfWeek) >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -18,7 +18,6 @@
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Duplicati.Server.Serializable
|
||||
+242
-242
@@ -1,242 +1,242 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Duplicati.Server.Serialization.Interface;
|
||||
|
||||
namespace Duplicati.Server.Serializable
|
||||
{
|
||||
/// <summary>
|
||||
/// The server config
|
||||
/// </summary>
|
||||
public static class ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Shared implementation for reporting dynamic modules
|
||||
/// </summary>
|
||||
private class DynamicModule : IDynamicModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for backend interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IBackend backend)
|
||||
{
|
||||
this.Key = backend.ProtocolKey;
|
||||
this.Description = backend.Description;
|
||||
this.DisplayName = backend.DisplayName;
|
||||
if (backend.SupportedCommands != null)
|
||||
this.Options = backend.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for compression module interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.ICompression module)
|
||||
{
|
||||
this.Key = module.FilenameExtension;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for encryption module interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IEncryption module)
|
||||
{
|
||||
this.Key = module.FilenameExtension;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for generic module interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IGenericModule module)
|
||||
{
|
||||
this.Key = module.Key;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for webmodule interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IWebModule module)
|
||||
{
|
||||
this.Key = module.Key;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
/// <summary>
|
||||
/// The module key
|
||||
/// </summary>
|
||||
public string Key { get; private set; }
|
||||
/// <summary>
|
||||
/// The localized module description
|
||||
/// </summary>
|
||||
public string Description { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the localized display name
|
||||
/// </summary>
|
||||
/// <value>The display name.</value>
|
||||
public string DisplayName { get; private set; }
|
||||
/// <summary>
|
||||
/// The options supported by the module
|
||||
/// </summary>
|
||||
public Duplicati.Library.Interface.ICommandLineArgument[] Options { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all supported options
|
||||
/// </summary>
|
||||
public static Duplicati.Library.Interface.ICommandLineArgument[] Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Duplicati.Library.Main.Options(new System.Collections.Generic.Dictionary<string, string>()).SupportedCommands.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The backend modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] BackendModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.BackendLoader.Backends
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The encryption modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] EncryptionModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.EncryptionLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The compression modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] CompressionModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.CompressionLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The generic modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] GenericModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.GenericLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The web modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] WebModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.WebLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The web modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] ConnectionModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.GenericLoader.Modules
|
||||
where n is Library.Interface.IConnectionModule
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The server modules known by the server
|
||||
/// </summary>
|
||||
public static object[] ServerModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.GenericLoader.Modules
|
||||
where n is Library.Interface.IGenericServerModule
|
||||
select n)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The filters that are applied to all backups
|
||||
/// </summary>
|
||||
public static IFilter[] Filters
|
||||
{
|
||||
get { return Program.DataConnection.Filters; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The settings applied to all backups by default
|
||||
/// </summary>
|
||||
public static ISetting[] Settings
|
||||
{
|
||||
get { return Program.DataConnection.Settings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Duplicati.Library.RestAPI;
|
||||
using Duplicati.Server.Serialization.Interface;
|
||||
|
||||
namespace Duplicati.Server.Serializable
|
||||
{
|
||||
/// <summary>
|
||||
/// The server config
|
||||
/// </summary>
|
||||
public static class ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Shared implementation for reporting dynamic modules
|
||||
/// </summary>
|
||||
private class DynamicModule : IDynamicModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for backend interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IBackend backend)
|
||||
{
|
||||
this.Key = backend.ProtocolKey;
|
||||
this.Description = backend.Description;
|
||||
this.DisplayName = backend.DisplayName;
|
||||
if (backend.SupportedCommands != null)
|
||||
this.Options = backend.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for compression module interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.ICompression module)
|
||||
{
|
||||
this.Key = module.FilenameExtension;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for encryption module interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IEncryption module)
|
||||
{
|
||||
this.Key = module.FilenameExtension;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for generic module interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IGenericModule module)
|
||||
{
|
||||
this.Key = module.Key;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for webmodule interface
|
||||
/// </summary>
|
||||
public DynamicModule(Duplicati.Library.Interface.IWebModule module)
|
||||
{
|
||||
this.Key = module.Key;
|
||||
this.Description = module.Description;
|
||||
this.DisplayName = module.DisplayName;
|
||||
if (module.SupportedCommands != null)
|
||||
this.Options = module.SupportedCommands.ToArray();
|
||||
}
|
||||
/// <summary>
|
||||
/// The module key
|
||||
/// </summary>
|
||||
public string Key { get; private set; }
|
||||
/// <summary>
|
||||
/// The localized module description
|
||||
/// </summary>
|
||||
public string Description { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the localized display name
|
||||
/// </summary>
|
||||
/// <value>The display name.</value>
|
||||
public string DisplayName { get; private set; }
|
||||
/// <summary>
|
||||
/// The options supported by the module
|
||||
/// </summary>
|
||||
public Duplicati.Library.Interface.ICommandLineArgument[] Options { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all supported options
|
||||
/// </summary>
|
||||
public static Duplicati.Library.Interface.ICommandLineArgument[] Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Duplicati.Library.Main.Options(new System.Collections.Generic.Dictionary<string, string>()).SupportedCommands.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The backend modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] BackendModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.BackendLoader.Backends
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The encryption modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] EncryptionModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.EncryptionLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The compression modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] CompressionModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.CompressionLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The generic modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] GenericModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.GenericLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The web modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] WebModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.WebLoader.Modules
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The web modules known by the server
|
||||
/// </summary>
|
||||
public static IDynamicModule[] ConnectionModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.GenericLoader.Modules
|
||||
where n is Library.Interface.IConnectionModule
|
||||
select new DynamicModule(n))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The server modules known by the server
|
||||
/// </summary>
|
||||
public static object[] ServerModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
(from n in Library.DynamicLoader.GenericLoader.Modules
|
||||
where n is Library.Interface.IGenericServerModule
|
||||
select n)
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The filters that are applied to all backups
|
||||
/// </summary>
|
||||
public static IFilter[] Filters
|
||||
{
|
||||
get { return FIXMEGlobal.DataConnection.Filters; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The settings applied to all backups by default
|
||||
/// </summary>
|
||||
public static ISetting[] Settings
|
||||
{
|
||||
get { return FIXMEGlobal.DataConnection.Settings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+147
-148
@@ -1,148 +1,147 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Duplicati.Server.Serialization;
|
||||
|
||||
namespace Duplicati.Server.Serializable
|
||||
{
|
||||
/// <summary>
|
||||
/// This class collects all reportable status properties into a single class that can be exported as JSON
|
||||
/// </summary>
|
||||
public class ServerStatus : Duplicati.Server.Serialization.Interface.IServerStatus
|
||||
{
|
||||
public LiveControlState ProgramState
|
||||
{
|
||||
get { return EnumConverter.Convert<LiveControlState>(Program.LiveControl.State); }
|
||||
}
|
||||
|
||||
public string UpdatedVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var u = Program.DataConnection.ApplicationSettings.UpdatedVersion;
|
||||
if (u == null)
|
||||
return null;
|
||||
|
||||
Version v;
|
||||
if (!Version.TryParse(u.Version, out v))
|
||||
return null;
|
||||
|
||||
if (v <= System.Reflection.Assembly.GetExecutingAssembly().GetName().Version)
|
||||
return null;
|
||||
|
||||
return u.Displayname;
|
||||
}
|
||||
}
|
||||
|
||||
public UpdatePollerStates UpdaterState { get { return Program.UpdatePoller.ThreadState; } }
|
||||
|
||||
public bool UpdateReady { get { return Duplicati.Library.AutoUpdater.UpdaterManager.HasUpdateInstalled; } }
|
||||
|
||||
public double UpdateDownloadProgress { get { return Program.UpdatePoller.DownloadProgess; } }
|
||||
|
||||
|
||||
public Tuple<long, string> ActiveTask
|
||||
{
|
||||
get
|
||||
{
|
||||
var t = Program.WorkThread.CurrentTask;
|
||||
if (t == null)
|
||||
return null;
|
||||
else
|
||||
return new Tuple<long, string>(t.TaskID, t.Backup == null ? null : t.Backup.ID);
|
||||
}
|
||||
}
|
||||
|
||||
public IList<Tuple<long, string>> SchedulerQueueIds
|
||||
{
|
||||
get { return (from n in Program.Scheduler.WorkerQueue where n.Backup != null select new Tuple<long, string>(n.TaskID, n.Backup.ID)).ToList(); }
|
||||
}
|
||||
|
||||
public IList<Tuple<string, DateTime>> ProposedSchedule
|
||||
{
|
||||
get
|
||||
{
|
||||
return (
|
||||
from n in Program.Scheduler.Schedule
|
||||
let backupid = (from t in n.Value.Tags
|
||||
where t != null && t.StartsWith("ID=", StringComparison.Ordinal)
|
||||
select t.Substring("ID=".Length)).FirstOrDefault()
|
||||
where !string.IsNullOrWhiteSpace(backupid)
|
||||
select new Tuple<string, DateTime>(backupid, n.Key)
|
||||
).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasWarning { get { return Program.DataConnection.ApplicationSettings.UnackedWarning; } }
|
||||
public bool HasError { get { return Program.DataConnection.ApplicationSettings.UnackedError; } }
|
||||
|
||||
public SuggestedStatusIcon SuggestedStatusIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ActiveTask == null)
|
||||
{
|
||||
if (this.ProgramState == LiveControlState.Paused)
|
||||
return SuggestedStatusIcon.Paused;
|
||||
|
||||
if (this.HasError)
|
||||
return SuggestedStatusIcon.ReadyError;
|
||||
if (this.HasWarning)
|
||||
return SuggestedStatusIcon.ReadyWarning;
|
||||
|
||||
return SuggestedStatusIcon.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.ProgramState == LiveControlState.Running)
|
||||
return SuggestedStatusIcon.Active;
|
||||
else
|
||||
return SuggestedStatusIcon.ActivePaused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime EstimatedPauseEnd
|
||||
{
|
||||
get
|
||||
{
|
||||
return Program.LiveControl.EstimatedPauseEnd;
|
||||
}
|
||||
}
|
||||
|
||||
private long m_lastEventID = Program.StatusEventNotifyer.EventNo;
|
||||
|
||||
public long LastEventID
|
||||
{
|
||||
get { return m_lastEventID; }
|
||||
set { m_lastEventID = value; }
|
||||
}
|
||||
|
||||
public long LastDataUpdateID { get { return Program.LastDataUpdateID; } }
|
||||
|
||||
public long LastNotificationUpdateID { get { return Program.LastNotificationUpdateID; } }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Duplicati.Server.Serialization;
|
||||
using Duplicati.Library.RestAPI;
|
||||
|
||||
namespace Duplicati.Server.Serializable
|
||||
{
|
||||
/// <summary>
|
||||
/// This class collects all reportable status properties into a single class that can be exported as JSON
|
||||
/// </summary>
|
||||
public class ServerStatus(LiveControls liveControls) : Duplicati.Server.Serialization.Interface.IServerStatus
|
||||
{
|
||||
public LiveControlState ProgramState
|
||||
{
|
||||
get { return EnumConverter.Convert<LiveControlState>(liveControls.State); }
|
||||
}
|
||||
|
||||
public string UpdatedVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var u = FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion;
|
||||
if (u == null)
|
||||
return null;
|
||||
|
||||
Version v;
|
||||
if (!Version.TryParse(u.Version, out v))
|
||||
return null;
|
||||
|
||||
if (v <= System.Reflection.Assembly.GetExecutingAssembly().GetName().Version)
|
||||
return null;
|
||||
|
||||
return u.Displayname;
|
||||
}
|
||||
}
|
||||
|
||||
public string UpdateDownloadLink => FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion?.GetUpdateUrls()?.FirstOrDefault();
|
||||
|
||||
public UpdatePollerStates UpdaterState { get { return FIXMEGlobal.UpdatePoller.ThreadState; } }
|
||||
|
||||
public double UpdateDownloadProgress { get { return FIXMEGlobal.UpdatePoller.DownloadProgess; } }
|
||||
|
||||
|
||||
public Tuple<long, string> ActiveTask
|
||||
{
|
||||
get
|
||||
{
|
||||
var t = FIXMEGlobal.WorkThread.CurrentTask;
|
||||
if (t == null)
|
||||
return null;
|
||||
else
|
||||
return new Tuple<long, string>(t.TaskID, t.Backup == null ? null : t.Backup.ID);
|
||||
}
|
||||
}
|
||||
|
||||
public IList<Tuple<long, string>> SchedulerQueueIds
|
||||
{
|
||||
get { return (from n in FIXMEGlobal.Scheduler.WorkerQueue where n.Backup != null select new Tuple<long, string>(n.TaskID, n.Backup.ID)).ToList(); }
|
||||
}
|
||||
|
||||
public IList<Tuple<string, DateTime>> ProposedSchedule
|
||||
{
|
||||
get
|
||||
{
|
||||
return (
|
||||
from n in FIXMEGlobal.Scheduler.Schedule
|
||||
let backupid = (from t in n.Value.Tags
|
||||
where t != null && t.StartsWith("ID=", StringComparison.Ordinal)
|
||||
select t.Substring("ID=".Length)).FirstOrDefault()
|
||||
where !string.IsNullOrWhiteSpace(backupid)
|
||||
select new Tuple<string, DateTime>(backupid, n.Key)
|
||||
).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasWarning { get { return FIXMEGlobal.DataConnection.ApplicationSettings.UnackedWarning; } }
|
||||
public bool HasError { get { return FIXMEGlobal.DataConnection.ApplicationSettings.UnackedError; } }
|
||||
|
||||
public SuggestedStatusIcon SuggestedStatusIcon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ActiveTask == null)
|
||||
{
|
||||
if (this.ProgramState == LiveControlState.Paused)
|
||||
return SuggestedStatusIcon.Paused;
|
||||
|
||||
if (this.HasError)
|
||||
return SuggestedStatusIcon.ReadyError;
|
||||
if (this.HasWarning)
|
||||
return SuggestedStatusIcon.ReadyWarning;
|
||||
|
||||
return SuggestedStatusIcon.Ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.ProgramState == LiveControlState.Running)
|
||||
return SuggestedStatusIcon.Active;
|
||||
else
|
||||
return SuggestedStatusIcon.ActivePaused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime EstimatedPauseEnd
|
||||
{
|
||||
get
|
||||
{
|
||||
return liveControls.EstimatedPauseEnd;
|
||||
}
|
||||
}
|
||||
|
||||
private long m_lastEventID = FIXMEGlobal.StatusEventNotifyer.EventNo;
|
||||
|
||||
public long LastEventID
|
||||
{
|
||||
get { return m_lastEventID; }
|
||||
set { m_lastEventID = value; }
|
||||
}
|
||||
|
||||
public long LastDataUpdateID => FIXMEGlobal.NotificationUpdateService.LastDataUpdateId;
|
||||
|
||||
public long LastNotificationUpdateID => FIXMEGlobal.NotificationUpdateService.LastNotificationUpdateId;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-21
@@ -1,24 +1,4 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -63,9 +43,21 @@ namespace Duplicati.Server.Serializable
|
||||
/// </summary>
|
||||
public bool hidden { get; set; }
|
||||
/// <summary>
|
||||
/// True if the element has the system file attribute
|
||||
/// </summary>
|
||||
public bool systemFile { get; set; }
|
||||
/// <summary>
|
||||
/// True if the element is marked as temporary
|
||||
/// </summary>
|
||||
public bool temporary { get; set; }
|
||||
/// <summary>
|
||||
/// True if the element is a symlink
|
||||
/// </summary>
|
||||
public bool symlink { get; set; }
|
||||
/// <summary>
|
||||
/// Size of the file. -1 if directory or inaccessible
|
||||
/// </summary>
|
||||
public long fileSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new TreeNode
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -35,7 +35,7 @@ namespace Duplicati.Server
|
||||
|
||||
public static string ExpandEnvironmentVariables(string path)
|
||||
{
|
||||
foreach(var n in Nodes)
|
||||
foreach (var n in Nodes)
|
||||
if (path.StartsWith(n.id, StringComparison.Ordinal))
|
||||
path = path.Replace(n.id, n.resolvedpath);
|
||||
return Environment.ExpandEnvironmentVariables(path);
|
||||
@@ -58,21 +58,21 @@ namespace Duplicati.Server
|
||||
});
|
||||
}
|
||||
|
||||
public static string TranslateToPath(string str)
|
||||
public static string TranslateToPath(string str)
|
||||
{
|
||||
string res;
|
||||
if (PathMap.TryGetValue(str, out res))
|
||||
return res;
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string TranslateToDisplayString(string str)
|
||||
public static string TranslateToDisplayString(string str)
|
||||
{
|
||||
string res;
|
||||
if (DisplayMap.TryGetValue(str, out res))
|
||||
return res;
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -113,12 +113,12 @@ namespace Duplicati.Server
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static SpecialFolders()
|
||||
{
|
||||
var lst = new List<Serializable.TreeNode>();
|
||||
|
||||
if (Platform.IsClientWindows)
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
TryAdd(lst, Environment.SpecialFolder.MyDocuments, "%MY_DOCUMENTS%", "My Documents");
|
||||
TryAdd(lst, Environment.SpecialFolder.MyMusic, "%MY_MUSIC%", "My Music");
|
||||
@@ -151,7 +151,7 @@ namespace Duplicati.Server
|
||||
Nodes = lst.ToArray();
|
||||
}
|
||||
|
||||
internal static Dictionary<string, string> GetSourceNames(Serialization.Interface.IBackup backup)
|
||||
public static Dictionary<string, string> GetSourceNames(Serialization.Interface.IBackup backup)
|
||||
{
|
||||
if (backup.Sources == null || backup.Sources.Length == 0)
|
||||
return new Dictionary<string, string>();
|
||||
@@ -185,7 +185,7 @@ namespace Duplicati.Server
|
||||
|
||||
// Handle duplicates
|
||||
var result = new Dictionary<string, string>();
|
||||
foreach(var x in sources)
|
||||
foreach (var x in sources)
|
||||
result[x.Key] = x.Value;
|
||||
|
||||
return result;
|
||||
@@ -1,77 +1,61 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
using System.Collections.Generic;
|
||||
using Duplicati.Library.Localization.Short;
|
||||
using System.Linq;
|
||||
|
||||
namespace Duplicati.Server.Strings {
|
||||
internal static class Program {
|
||||
public static string AnotherInstanceDetected { get { return LC.L(@"Another instance is running, and was notified"); } }
|
||||
public static string DatabaseOpenError(string message) { return LC.L(@"Failed to create, open or upgrade the database.
|
||||
Error message: {0}", message); }
|
||||
public static string HelpCommandDescription { get { return LC.L(@"Displays this help"); } }
|
||||
public static string HelpDisplayDialog { get { return LC.L(@"Supported commandline arguments:
|
||||
|
||||
"); } }
|
||||
public static string HelpDisplayFormat(string optionname, string optiontext) { return LC.L(@"--{0}: {1}", optionname, optiontext); }
|
||||
public static string ParametersFileOptionLong2 { get { return LC.L(@"This option can be used to store some or all of the options given to the commandline client. The file must be a plain text file, UTF-8 encoding is preferred. Each line in the file should be of the format --option=value. The special options --{0} and --{1} can be used to override the localpath and the remote destination uri, respectively. The options in this file take precedence over the options provided on the commandline. You cannot specify filters in both the file and on the commandline. Instead, you can use the special --{2}, --{3}, or --{4} options to specify filters inside the parameter file. Each filter must be prefixed with either a + or a -, and multiple filters must be joined with {5} ", "source", "target", "replace-filter", "append-filter", "prepend-filter", System.IO.Path.PathSeparator); } }
|
||||
public static string ParametersFileOptionShort { get { return LC.L(@"Path to a file with parameters"); } }
|
||||
public static string FiltersCannotBeUsedWithFileError2 { get { return LC.L(@"Filters cannot be specified on the commandline if filters are also present in the parameter file. Use the special --{0}, --{1}, or --{2} options to specify filters inside the parameter file. Each filter must be prefixed with either a + or a -, and multiple filters must be joined with {3}", "replace-filter", "append-filter", "prepend-filter", System.IO.Path.PathSeparator); } }
|
||||
public static string FailedToParseParametersFileError(string path, string message) { return LC.L(@"Unable to read the parameters file ""{0}"", reason: {1}", path, message); }
|
||||
public static string SkippingSourceArgumentsOnNonBackupOperation { get { return @"The --source argument was specified in the parameter file, but the current operation is not a backup operation, so the argument is ignored"; } }
|
||||
public static string LogfileCommandDescription { get { return LC.L(@"Outputs log information to the file given"); } }
|
||||
public static string LoglevelCommandDescription { get { return LC.L(@"Determines the amount of information written in the log file"); } }
|
||||
public static string PortablemodeCommandDescription { get { return LC.L(@"Activates portable mode where the database is placed below the program executable"); } }
|
||||
public static string SeriousError(string message) { return LC.L(@"A serious error occurred in Duplicati: {0}", message); }
|
||||
public static string StartupFailure(System.Exception error) { return LC.L(@"Unable to start up, perhaps another process is already running?
|
||||
Error message: {0}", error); }
|
||||
public static string UnencrypteddatabaseCommandDescription { get { return LC.L(@"Disables database encryption"); } }
|
||||
public static string WrongSQLiteVersion(System.Version actualversion, string expectedversion) { return LC.L(@"Unsupported version of SQLite detected ({0}), must be {1} or higher", actualversion, expectedversion); }
|
||||
public static string WebserverWebrootDescription { get { return LC.L(@"The path to the folder where the static files for the webserver is present. The folder must be located beneath the installation folder"); } }
|
||||
public static string WebserverPortDescription { get { return LC.L(@"The port the webserver listens on. Multiple values may be supplied with a comma in between."); } }
|
||||
public static string WebserverCertificateFileDescription { get { return LC.L(@"The certificate and key file in PKCS #12 format the webserver use for SSL. Only RSA/DSA keys are supported."); } }
|
||||
public static string WebserverCertificatePasswordDescription { get { return LC.L(@"The password for decryption of certificate PKCS #12 file."); } }
|
||||
public static string WebserverInterfaceDescription { get { return LC.L(@"The interface the webserver listens on. The special values ""*"" and ""any"" means any interface. The special value ""loopback"" means the loopback adapter."); } }
|
||||
public static string WebserverPasswordDescription { get { return LC.L(@"The password required to access the webserver. This option is saved so you do not need to set it on each run. Setting an empty value disables the password."); } }
|
||||
public static string WebserverAllowedhostnamesDescription { get { return LC.L(@"The hostnames that are accepted, separated with semicolons. If any of the hostnames are ""*"", all hostnames are allowed and the hostname checking is disabled."); } }
|
||||
public static string PingpongkeepaliveShort { get { return LC.L(@"Enables the ping-pong responder"); } }
|
||||
public static string PingpongkeepaliveLong { get { return LC.L(@"When running as a server, the service daemon must verify that the process is responding. If this option is enabled, the server reads stdin and writes a reply to each line read"); } }
|
||||
public static string LogretentionShort { get { return LC.L(@"Clean up old log data"); } }
|
||||
public static string LogretentionLong { get { return LC.L(@"Set the time after which log data will be purged from the database."); } }
|
||||
public static string ServerdatafolderShort { get { return LC.L(@"Sets the folder where settings are stored"); } }
|
||||
public static string ServerdatafolderLong(string envname) { return LC.L(@"Duplicati needs to store a small database with all settings. Use this option to choose where the settings are stored. This option can also be set with the environment variable {0}.", envname); }
|
||||
public static string ServerencryptionkeyShort { get { return LC.L(@"Sets the database encryption key"); } }
|
||||
public static string ServerencryptionkeyLong(string envname, string decryptionoption) { return LC.L(@"This option sets the encryption key used to scramble the local settings database. This option can also be set with the environment variable {0}. Use the option --{1} to disable the database scrambling.", envname, decryptionoption); }
|
||||
public static string TempdirShort { get { return LC.L(@"Temporary storage folder"); } }
|
||||
public static string TempdirLong { get { return LC.L(@"This option can be used to supply an alternative folder for temporary storage. By default the system default temporary folder is used. Note that also SQLite will put temporary files in this temporary folder."); } }
|
||||
}
|
||||
internal static class Scheduler {
|
||||
public static string InvalidTimeSetupError(System.DateTime startdate, string interval, string alloweddays) { return LC.L(@"Unable to find a valid date, given the start date {0}, the repetition interval {1} and the allowed days {2}", startdate, interval, alloweddays); }
|
||||
}
|
||||
internal static class Server
|
||||
{
|
||||
public static string DefectSSLCertInDatabase { get { return @"Unable to create SSL certificate using data from database. Starting without SSL."; } }
|
||||
public static string StartedServer(string ip, int port) { return LC.L(@"Server has started and is listening on {0}, port {1}", ip, port); }
|
||||
public static string SSLCertificateFailure(string errormessage) { return LC.L(@"Unable to create SSL certificate using provided parameters. Exception detail: {0}", errormessage); }
|
||||
public static string ServerStartFailure(IEnumerable<int> portstried) { return LC.L(@"Unable to open a socket for listening, tried ports: {0}", string.Join(",", from n in (portstried ?? new int[0]) select n.ToString())); }
|
||||
}
|
||||
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using Duplicati.Library.Localization.Short;
|
||||
using System.Linq;
|
||||
|
||||
namespace Duplicati.Server.Strings
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static string AnotherInstanceDetected { get { return LC.L(@"Another instance is running, and was notified"); } }
|
||||
public static string DatabaseOpenError(string message) { return LC.L(@"Failed to create, open or upgrade the database.
|
||||
Error message: {0}", message); }
|
||||
public static string HelpCommandDescription { get { return LC.L(@"Displays this help"); } }
|
||||
public static string HelpDisplayDialog { get { return LC.L(@"Supported commandline arguments:
|
||||
|
||||
"); } }
|
||||
public static string HelpDisplayFormat(string optionname, string optiontext) { return LC.L(@"--{0}: {1}", optionname, optiontext); }
|
||||
public static string ParametersFileOptionLong2 { get { return LC.L(@"This option can be used to store some or all of the options given to the commandline client. The file must be a plain text file, UTF-8 encoding is preferred. Each line in the file should be of the format --option=value. The special options --{0} and --{1} can be used to override the localpath and the remote destination uri, respectively. The options in this file take precedence over the options provided on the commandline. You cannot specify filters in both the file and on the commandline. Instead, you can use the special --{2}, --{3}, or --{4} options to specify filters inside the parameter file. Each filter must be prefixed with either a + or a -, and multiple filters must be joined with {5} ", "source", "target", "replace-filter", "append-filter", "prepend-filter", System.IO.Path.PathSeparator); } }
|
||||
public static string ParametersFileOptionShort { get { return LC.L(@"Path to a file with parameters"); } }
|
||||
public static string FiltersCannotBeUsedWithFileError2 { get { return LC.L(@"Filters cannot be specified on the commandline if filters are also present in the parameter file. Use the special --{0}, --{1}, or --{2} options to specify filters inside the parameter file. Each filter must be prefixed with either a + or a -, and multiple filters must be joined with {3}", "replace-filter", "append-filter", "prepend-filter", System.IO.Path.PathSeparator); } }
|
||||
public static string FailedToParseParametersFileError(string path, string message) { return LC.L(@"Unable to read the parameters file ""{0}"", reason: {1}", path, message); }
|
||||
public static string SkippingSourceArgumentsOnNonBackupOperation { get { return @"The --source argument was specified in the parameter file, but the current operation is not a backup operation, so the argument is ignored"; } }
|
||||
public static string LogfileCommandDescription { get { return LC.L(@"Outputs log information to the file given"); } }
|
||||
public static string LoglevelCommandDescription { get { return LC.L(@"Determines the amount of information written in the log file"); } }
|
||||
public static string PortablemodeCommandDescription { get { return LC.L(@"Activates portable mode where the database is placed below the program executable"); } }
|
||||
public static string SeriousError(string message) { return LC.L(@"A serious error occurred in Duplicati: {0}", message); }
|
||||
public static string StartupFailure(System.Exception error) { return LC.L(@"Unable to start up, perhaps another process is already running?
|
||||
Error message: {0}", error); }
|
||||
public static string UnencrypteddatabaseCommandDescription { get { return LC.L(@"Disables database encryption"); } }
|
||||
public static string WrongSQLiteVersion(System.Version actualversion, string expectedversion) { return LC.L(@"Unsupported version of SQLite detected ({0}), must be {1} or higher", actualversion, expectedversion); }
|
||||
public static string WebserverWebrootDescription { get { return LC.L(@"The path to the folder where the static files for the webserver is present. The folder must be located beneath the installation folder"); } }
|
||||
public static string WebserverPortDescription { get { return LC.L(@"The port the webserver listens on. Multiple values may be supplied with a comma in between."); } }
|
||||
public static string WebserverCertificateFileDescription { get { return LC.L(@"The certificate and key file in PKCS #12 format the webserver use for SSL. Only RSA/DSA keys are supported."); } }
|
||||
public static string WebserverCertificatePasswordDescription { get { return LC.L(@"The password for decryption of certificate PKCS #12 file."); } }
|
||||
public static string WebserverInterfaceDescription { get { return LC.L(@"The interface the webserver listens on. The special values ""*"" and ""any"" means any interface. The special value ""loopback"" means the loopback adapter."); } }
|
||||
public static string WebserverPasswordDescription { get { return LC.L(@"The password required to access the webserver. This option is saved so you do not need to set it on each run. Setting an empty value disables the password."); } }
|
||||
public static string WebserverAllowedhostnamesDescription { get { return LC.L(@"The hostnames that are accepted, separated with semicolons. If any of the hostnames are ""*"", all hostnames are allowed and the hostname checking is disabled."); } }
|
||||
public static string PingpongkeepaliveShort { get { return LC.L(@"Enables the ping-pong responder"); } }
|
||||
public static string PingpongkeepaliveLong { get { return LC.L(@"When running as a server, the service daemon must verify that the process is responding. If this option is enabled, the server reads stdin and writes a reply to each line read"); } }
|
||||
public static string LogretentionShort { get { return LC.L(@"Clean up old log data"); } }
|
||||
public static string LogretentionLong { get { return LC.L(@"Set the time after which log data will be purged from the database."); } }
|
||||
public static string ServerdatafolderShort { get { return LC.L(@"Sets the folder where settings are stored"); } }
|
||||
public static string ServerdatafolderLong(string envname) { return LC.L(@"Duplicati needs to store a small database with all settings. Use this option to choose where the settings are stored. This option can also be set with the environment variable {0}.", envname); }
|
||||
public static string ServerencryptionkeyShort { get { return LC.L(@"Sets the database encryption key"); } }
|
||||
public static string ServerencryptionkeyLong(string envname, string decryptionoption) { return LC.L(@"This option sets the encryption key used to scramble the local settings database. This option can also be set with the environment variable {0}. Use the option --{1} to disable the database scrambling.", envname, decryptionoption); }
|
||||
public static string TempdirShort { get { return LC.L(@"Temporary storage folder"); } }
|
||||
public static string TempdirLong { get { return LC.L(@"This option can be used to supply an alternative folder for temporary storage. By default the system default temporary folder is used. Note that also SQLite will put temporary files in this temporary folder."); } }
|
||||
public static string WebserverResetJwtConfigDescription { get { return LC.L(@"Resets the JWT configuration, invalidating any issued login tokens"); } }
|
||||
}
|
||||
internal static class Scheduler
|
||||
{
|
||||
public static string InvalidTimeSetupError(System.DateTime startdate, string interval, string alloweddays) { return LC.L(@"Unable to find a valid date, given the start date {0}, the repetition interval {1} and the allowed days {2}", startdate, interval, alloweddays); }
|
||||
}
|
||||
public static class Server
|
||||
{
|
||||
public static string DefectSSLCertInDatabase { get { return @"Unable to create SSL certificate using data from database. Starting without SSL."; } }
|
||||
public static string StartedServer(string ip, int port) { return LC.L(@"Server has started and is listening on {0}, port {1}", ip, port); }
|
||||
public static string SSLCertificateFailure(string errormessage) { return LC.L(@"Unable to create SSL certificate using provided parameters. Exception detail: {0}", errormessage); }
|
||||
public static string ServerStartFailure(IEnumerable<int> portstried) { return LC.L(@"Unable to open a socket for listening, tried ports: {0}", string.Join(",", from n in (portstried ?? new int[0]) select n.ToString())); }
|
||||
}
|
||||
|
||||
}
|
||||
+211
-275
@@ -1,275 +1,211 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Duplicati.Server.Serialization;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The thread that checks on the update server if new versions are available
|
||||
/// </summary>
|
||||
public class UpdatePollThread
|
||||
{
|
||||
private readonly Thread m_thread;
|
||||
private volatile bool m_terminated = false;
|
||||
private volatile bool m_download = false;
|
||||
private volatile bool m_forceCheck = false;
|
||||
private readonly object m_lock = new object();
|
||||
private readonly AutoResetEvent m_waitSignal;
|
||||
private double m_downloadProgress;
|
||||
|
||||
public bool IsUpdateRequested { get; private set; } = false;
|
||||
|
||||
public UpdatePollerStates ThreadState { get; private set; }
|
||||
public double DownloadProgess
|
||||
{
|
||||
get { return m_downloadProgress ; }
|
||||
|
||||
private set
|
||||
{
|
||||
var oldv = m_downloadProgress;
|
||||
m_downloadProgress = value;
|
||||
if ((int)(oldv * 100) != (int)(value * 100))
|
||||
Program.StatusEventNotifyer.SignalNewEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public UpdatePollThread()
|
||||
{
|
||||
m_waitSignal = new AutoResetEvent(false);
|
||||
ThreadState = UpdatePollerStates.Waiting;
|
||||
m_thread = new Thread(Run);
|
||||
m_thread.IsBackground = true;
|
||||
m_thread.Name = "UpdatePollThread";
|
||||
m_thread.Start();
|
||||
}
|
||||
|
||||
public void CheckNow()
|
||||
{
|
||||
lock(m_lock)
|
||||
{
|
||||
m_forceCheck = true;
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallUpdate()
|
||||
{
|
||||
lock(m_lock)
|
||||
{
|
||||
m_forceCheck = true;
|
||||
m_download = true;
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void ActivateUpdate()
|
||||
{
|
||||
if (Duplicati.Library.AutoUpdater.UpdaterManager.SetRunUpdate())
|
||||
{
|
||||
IsUpdateRequested = true;
|
||||
Program.ApplicationExitEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
lock(m_lock)
|
||||
{
|
||||
m_terminated = true;
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void Reschedule()
|
||||
{
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
|
||||
private void Run()
|
||||
{
|
||||
// Wait on startup
|
||||
m_waitSignal.WaitOne(TimeSpan.FromMinutes(1), true);
|
||||
|
||||
while (!m_terminated)
|
||||
{
|
||||
var nextCheck = Program.DataConnection.ApplicationSettings.NextUpdateCheck;
|
||||
|
||||
var maxcheck = TimeSpan.FromDays(7);
|
||||
try
|
||||
{
|
||||
maxcheck = Library.Utility.Timeparser.ParseTimeSpan(Program.DataConnection.ApplicationSettings.UpdateCheckInterval);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
// If we have some weirdness, just check now
|
||||
if (nextCheck - DateTime.UtcNow > maxcheck)
|
||||
nextCheck = DateTime.UtcNow - TimeSpan.FromSeconds(1);
|
||||
|
||||
if (nextCheck < DateTime.UtcNow || m_forceCheck)
|
||||
{
|
||||
lock(m_lock)
|
||||
m_forceCheck = false;
|
||||
|
||||
ThreadState = UpdatePollerStates.Checking;
|
||||
Program.StatusEventNotifyer.SignalNewEvent();
|
||||
|
||||
DateTime started = DateTime.UtcNow;
|
||||
Program.DataConnection.ApplicationSettings.LastUpdateCheck = started;
|
||||
nextCheck = Program.DataConnection.ApplicationSettings.NextUpdateCheck;
|
||||
|
||||
Library.AutoUpdater.ReleaseType rt;
|
||||
if (!Enum.TryParse<Library.AutoUpdater.ReleaseType>(Program.DataConnection.ApplicationSettings.UpdateChannel, true, out rt))
|
||||
rt = Duplicati.Library.AutoUpdater.ReleaseType.Unknown;
|
||||
|
||||
// Choose the default channel in case we have unknown
|
||||
rt = rt == Duplicati.Library.AutoUpdater.ReleaseType.Unknown ? Duplicati.Library.AutoUpdater.AutoUpdateSettings.DefaultUpdateChannel : rt;
|
||||
|
||||
try
|
||||
{
|
||||
var update = Duplicati.Library.AutoUpdater.UpdaterManager.CheckForUpdate(rt);
|
||||
if (update != null)
|
||||
Program.DataConnection.ApplicationSettings.UpdatedVersion = update;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
// It could be that we have registered an update from a more unstable channel,
|
||||
// but the user has switched to a more stable channel.
|
||||
// In that case we discard the old update to avoid offering it.
|
||||
if (Program.DataConnection.ApplicationSettings.UpdatedVersion != null)
|
||||
{
|
||||
Library.AutoUpdater.ReleaseType updatert;
|
||||
var updatertstring = Program.DataConnection.ApplicationSettings.UpdatedVersion.ReleaseType;
|
||||
if (string.Equals(updatertstring, "preview", StringComparison.OrdinalIgnoreCase))
|
||||
updatertstring = Library.AutoUpdater.ReleaseType.Experimental.ToString();
|
||||
|
||||
if (!Enum.TryParse<Library.AutoUpdater.ReleaseType>(updatertstring, true, out updatert))
|
||||
updatert = Duplicati.Library.AutoUpdater.ReleaseType.Nightly;
|
||||
|
||||
if (updatert == Duplicati.Library.AutoUpdater.ReleaseType.Unknown)
|
||||
updatert = Duplicati.Library.AutoUpdater.ReleaseType.Nightly;
|
||||
|
||||
if (updatert > rt)
|
||||
Program.DataConnection.ApplicationSettings.UpdatedVersion = null;
|
||||
}
|
||||
|
||||
if (Program.DataConnection.ApplicationSettings.UpdatedVersion != null && Duplicati.Library.AutoUpdater.UpdaterManager.TryParseVersion(Program.DataConnection.ApplicationSettings.UpdatedVersion.Version) > System.Reflection.Assembly.GetExecutingAssembly().GetName().Version)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Program.DataConnection.ApplicationSettings.UpdatedVersion.UpdateFromV1Url))
|
||||
{
|
||||
Program.DataConnection.RegisterNotification(
|
||||
NotificationType.Information,
|
||||
"Found update",
|
||||
Program.DataConnection.ApplicationSettings.UpdatedVersion.Displayname,
|
||||
null,
|
||||
null,
|
||||
"update:new",
|
||||
null,
|
||||
"NewUpdateFound",
|
||||
null,
|
||||
(self, all) => all.FirstOrDefault(x => x.Action == "update:new") ?? self
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.DataConnection.RegisterNotification(
|
||||
NotificationType.Information,
|
||||
"Manual update required",
|
||||
Program.DataConnection.ApplicationSettings.UpdatedVersion.UpdateFromV1Url,
|
||||
null,
|
||||
null,
|
||||
"update:manual",
|
||||
null,
|
||||
"NewUpdateFound",
|
||||
null,
|
||||
(self, all) => all.FirstOrDefault(x => x.Action == "update:manual") ?? self
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_download)
|
||||
{
|
||||
lock (m_lock)
|
||||
m_download = false;
|
||||
|
||||
var v = Program.DataConnection.ApplicationSettings.UpdatedVersion;
|
||||
if (v != null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(v.UpdateFromV1Url))
|
||||
{
|
||||
ThreadState = UpdatePollerStates.Downloading;
|
||||
Program.StatusEventNotifyer.SignalNewEvent();
|
||||
|
||||
if (Duplicati.Library.AutoUpdater.UpdaterManager.DownloadAndUnpackUpdate(v, (pg) => { DownloadProgess = pg; }))
|
||||
Program.StatusEventNotifyer.SignalNewEvent();
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.DataConnection.RegisterNotification(
|
||||
NotificationType.Error,
|
||||
"Manual update required",
|
||||
v.UpdateFromV1Url,
|
||||
null,
|
||||
null,
|
||||
"update:manual",
|
||||
null,
|
||||
"NewUpdateFound",
|
||||
null,
|
||||
(self, all) => all.FirstOrDefault(x => x.Action == "update:manual") ?? self
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DownloadProgess = 0;
|
||||
|
||||
if (ThreadState != UpdatePollerStates.Waiting)
|
||||
{
|
||||
ThreadState = UpdatePollerStates.Waiting;
|
||||
Program.StatusEventNotifyer.SignalNewEvent();
|
||||
}
|
||||
|
||||
var waitTime = nextCheck - DateTime.UtcNow;
|
||||
|
||||
// Guard against spin-loop
|
||||
if (waitTime.TotalSeconds < 5)
|
||||
waitTime = TimeSpan.FromSeconds(5);
|
||||
|
||||
// Guard against year-long waits
|
||||
// A re-check does not cause an update check
|
||||
if (waitTime.TotalDays > 1)
|
||||
waitTime = TimeSpan.FromDays(1);
|
||||
|
||||
m_waitSignal.WaitOne(waitTime, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Duplicati.Server.Database;
|
||||
using Duplicati.Server.Serialization;
|
||||
|
||||
namespace Duplicati.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The thread that checks on the update server if new versions are available
|
||||
/// </summary>
|
||||
public class UpdatePollThread(Connection connection, EventPollNotify eventPollNotify)
|
||||
{
|
||||
private Thread m_thread;
|
||||
private volatile bool m_terminated = false;
|
||||
private volatile bool m_forceCheck = false;
|
||||
private readonly object m_lock = new object();
|
||||
private AutoResetEvent m_waitSignal;
|
||||
private double m_downloadProgress;
|
||||
|
||||
public bool IsUpdateRequested { get; private set; } = false;
|
||||
|
||||
public UpdatePollerStates ThreadState { get; private set; }
|
||||
public double DownloadProgess
|
||||
{
|
||||
get { return m_downloadProgress; }
|
||||
|
||||
private set
|
||||
{
|
||||
var oldv = m_downloadProgress;
|
||||
m_downloadProgress = value;
|
||||
if ((int)(oldv * 100) != (int)(value * 100))
|
||||
eventPollNotify.SignalNewEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
m_waitSignal = new AutoResetEvent(false);
|
||||
ThreadState = UpdatePollerStates.Waiting;
|
||||
m_thread = new Thread(Run)
|
||||
{
|
||||
IsBackground = true,
|
||||
Name = "UpdatePollThread"
|
||||
};
|
||||
m_thread.Start();
|
||||
}
|
||||
|
||||
public void CheckNow()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
m_forceCheck = true;
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
lock (m_lock)
|
||||
{
|
||||
m_terminated = true;
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
}
|
||||
|
||||
public void Reschedule()
|
||||
{
|
||||
m_waitSignal.Set();
|
||||
}
|
||||
|
||||
private void Run()
|
||||
{
|
||||
// Wait on startup
|
||||
m_waitSignal.WaitOne(TimeSpan.FromMinutes(1), true);
|
||||
|
||||
while (!m_terminated)
|
||||
{
|
||||
var nextCheck = connection.ApplicationSettings.NextUpdateCheck;
|
||||
|
||||
var maxcheck = TimeSpan.FromDays(7);
|
||||
try
|
||||
{
|
||||
maxcheck = Library.Utility.Timeparser.ParseTimeSpan(connection.ApplicationSettings.UpdateCheckInterval);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
// If we have some weirdness, just check now
|
||||
if (nextCheck - DateTime.UtcNow > maxcheck)
|
||||
nextCheck = DateTime.UtcNow - TimeSpan.FromSeconds(1);
|
||||
|
||||
if (nextCheck < DateTime.UtcNow || m_forceCheck)
|
||||
{
|
||||
lock (m_lock)
|
||||
m_forceCheck = false;
|
||||
|
||||
ThreadState = UpdatePollerStates.Checking;
|
||||
eventPollNotify.SignalNewEvent();
|
||||
|
||||
DateTime started = DateTime.UtcNow;
|
||||
connection.ApplicationSettings.LastUpdateCheck = started;
|
||||
nextCheck = connection.ApplicationSettings.NextUpdateCheck;
|
||||
|
||||
Library.AutoUpdater.ReleaseType rt;
|
||||
if (!Enum.TryParse<Library.AutoUpdater.ReleaseType>(connection.ApplicationSettings.UpdateChannel, true, out rt))
|
||||
rt = Duplicati.Library.AutoUpdater.ReleaseType.Unknown;
|
||||
|
||||
// Choose the default channel in case we have unknown
|
||||
rt = rt == Duplicati.Library.AutoUpdater.ReleaseType.Unknown ? Duplicati.Library.AutoUpdater.AutoUpdateSettings.DefaultUpdateChannel : rt;
|
||||
|
||||
try
|
||||
{
|
||||
var update = Duplicati.Library.AutoUpdater.UpdaterManager.CheckForUpdate(rt);
|
||||
if (update != null)
|
||||
connection.ApplicationSettings.UpdatedVersion = update;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
// It could be that we have registered an update from a more unstable channel,
|
||||
// but the user has switched to a more stable channel.
|
||||
// In that case we discard the old update to avoid offering it.
|
||||
if (connection.ApplicationSettings.UpdatedVersion != null)
|
||||
{
|
||||
Library.AutoUpdater.ReleaseType updatert;
|
||||
var updatertstring = connection.ApplicationSettings.UpdatedVersion.ReleaseType;
|
||||
if (string.Equals(updatertstring, "preview", StringComparison.OrdinalIgnoreCase))
|
||||
updatertstring = Library.AutoUpdater.ReleaseType.Experimental.ToString();
|
||||
|
||||
if (!Enum.TryParse<Library.AutoUpdater.ReleaseType>(updatertstring, true, out updatert))
|
||||
updatert = Duplicati.Library.AutoUpdater.ReleaseType.Nightly;
|
||||
|
||||
if (updatert == Duplicati.Library.AutoUpdater.ReleaseType.Unknown)
|
||||
updatert = Duplicati.Library.AutoUpdater.ReleaseType.Nightly;
|
||||
|
||||
if (updatert > rt)
|
||||
connection.ApplicationSettings.UpdatedVersion = null;
|
||||
}
|
||||
|
||||
var updatedinfo = connection.ApplicationSettings.UpdatedVersion;
|
||||
if (updatedinfo != null && Duplicati.Library.AutoUpdater.UpdaterManager.TryParseVersion(updatedinfo.Version) > System.Reflection.Assembly.GetExecutingAssembly().GetName().Version)
|
||||
{
|
||||
var package = updatedinfo.FindPackage();
|
||||
|
||||
connection.RegisterNotification(
|
||||
NotificationType.Information,
|
||||
"Found update",
|
||||
updatedinfo.Displayname,
|
||||
null,
|
||||
null,
|
||||
"update:new",
|
||||
null,
|
||||
"NewUpdateFound",
|
||||
null,
|
||||
(self, all) =>
|
||||
{
|
||||
return all.FirstOrDefault(x => x.Action == "update:new") ?? self;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DownloadProgess = 0;
|
||||
|
||||
if (ThreadState != UpdatePollerStates.Waiting)
|
||||
{
|
||||
ThreadState = UpdatePollerStates.Waiting;
|
||||
eventPollNotify.SignalNewEvent();
|
||||
}
|
||||
|
||||
var waitTime = nextCheck - DateTime.UtcNow;
|
||||
|
||||
// Guard against spin-loop
|
||||
if (waitTime.TotalSeconds < 5)
|
||||
waitTime = TimeSpan.FromSeconds(5);
|
||||
|
||||
// Guard against year-long waits
|
||||
// A re-check does not cause an update check
|
||||
if (waitTime.TotalDays > 1)
|
||||
waitTime = TimeSpan.FromDays(1);
|
||||
|
||||
m_waitSignal.WaitOne(waitTime, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"Backup": {
|
||||
"Settings": [
|
||||
{ "Name": "encryption-module", "Value": "aes" },
|
||||
{ "Name": "compression-module", "Value": "zip" },
|
||||
{ "Name": "dblock-size", "Value": "50mb" },
|
||||
{ "Name": "keep-time", "Value": "" }
|
||||
]
|
||||
},
|
||||
"Schedule": {
|
||||
"Repeat": "1D",
|
||||
"Time": "13:00:00",
|
||||
"AllowedDays": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
||||
}
|
||||
}
|
||||
+221
-74
@@ -1,113 +1,156 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31919.166
|
||||
VisualStudioVersion = 17.1.32210.238
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Utility", "Duplicati\Library\Utility\Duplicati.Library.Utility.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Utility", "Duplicati\Library\Utility\Duplicati.Library.Utility.csproj", "{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Main", "Duplicati\Library\Main\Duplicati.Library.Main.csproj", "{10D2D1B7-C664-41D8-9B3A-00040C3D421B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Main", "Duplicati\Library\Main\Duplicati.Library.Main.csproj", "{10D2D1B7-C664-41D8-9B3A-00040C3D421B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.File", "Duplicati\Library\Backend\File\Duplicati.Library.Backend.File.csproj", "{FC9B7611-836F-4127-8B44-A7C31F506807}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.File", "Duplicati\Library\Backend\File\Duplicati.Library.Backend.File.csproj", "{FC9B7611-836F-4127-8B44-A7C31F506807}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.FTP", "Duplicati\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj", "{F61679A9-E5DE-468A-B5A4-05F92D0143D2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.FTP", "Duplicati\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj", "{F61679A9-E5DE-468A-B5A4-05F92D0143D2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Compression", "Duplicati\Library\Compression\Duplicati.Library.Compression.csproj", "{19ECCE09-B5EB-406C-8C57-BAC66997D469}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Compression", "Duplicati\Library\Compression\Duplicati.Library.Compression.csproj", "{19ECCE09-B5EB-406C-8C57-BAC66997D469}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Logging", "Duplicati\Library\Logging\Duplicati.Library.Logging.csproj", "{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Logging", "Duplicati\Library\Logging\Duplicati.Library.Logging.csproj", "{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.S3", "Duplicati\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj", "{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.S3", "Duplicati\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj", "{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine", "Duplicati\CommandLine\Duplicati.CommandLine.csproj", "{81765A64-3661-4E3E-B850-2F6F87A51F74}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine", "Duplicati\CommandLine\CLI\Duplicati.CommandLine.csproj", "{81765A64-3661-4E3E-B850-2F6F87A51F74}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.WEBDAV", "Duplicati\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj", "{BAE27510-8B5D-44B2-B33E-372A98908041}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.WEBDAV", "Duplicati\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj", "{BAE27510-8B5D-44B2-B33E-372A98908041}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.CloudFiles", "Duplicati\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj", "{1BFAE226-8364-4086-825C-BB83F6F3EE4C}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.CloudFiles", "Duplicati\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj", "{1BFAE226-8364-4086-825C-BB83F6F3EE4C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.BackendTester", "Duplicati\CommandLine\BackendTester\Duplicati.CommandLine.BackendTester.csproj", "{E7280DCA-7776-4A73-B9B5-41FD77FC8799}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.BackendTester", "Duplicati\CommandLine\BackendTester\Duplicati.CommandLine.BackendTester.csproj", "{E7280DCA-7776-4A73-B9B5-41FD77FC8799}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Interface", "Duplicati\Library\Interface\Duplicati.Library.Interface.csproj", "{C5899F45-B0FF-483C-9D38-24A9FCAAB237}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Interface", "Duplicati\Library\Interface\Duplicati.Library.Interface.csproj", "{C5899F45-B0FF-483C-9D38-24A9FCAAB237}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.DynamicLoader", "Duplicati\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj", "{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.DynamicLoader", "Duplicati\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj", "{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Snapshots", "Duplicati\Library\Snapshots\Duplicati.Library.Snapshots.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACE}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Snapshots", "Duplicati\Library\Snapshots\Duplicati.Library.Snapshots.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.License", "Duplicati\License\Duplicati.License.csproj", "{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.License", "Duplicati\License\Duplicati.License.csproj", "{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Modules.Builtin", "Duplicati\Library\Modules\Builtin\Duplicati.Library.Modules.Builtin.csproj", "{52826615-7964-47FE-B4B3-1B2DBDF605B9}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Modules.Builtin", "Duplicati\Library\Modules\Builtin\Duplicati.Library.Modules.Builtin.csproj", "{52826615-7964-47FE-B4B3-1B2DBDF605B9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.TahoeLAFS", "Duplicati\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj", "{C0270709-2A40-43B5-8CF1-69581B9FA2A1}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.TahoeLAFS", "Duplicati\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj", "{C0270709-2A40-43B5-8CF1-69581B9FA2A1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.OneDrive", "Duplicati\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj", "{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.OneDrive", "Duplicati\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj", "{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.SSHv2", "Duplicati\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj", "{FF2BF37C-E502-4C98-BEA0-701671DDFA08}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.SSHv2", "Duplicati\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj", "{FF2BF37C-E502-4C98-BEA0-701671DDFA08}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Server", "Duplicati\Server\Duplicati.Server.csproj", "{19E661D2-C5DA-4F35-B3EE-7586E5734B5F}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Server", "Duplicati\Server\Duplicati.Server.csproj", "{19E661D2-C5DA-4F35-B3EE-7586E5734B5F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.GUI.TrayIcon", "Duplicati\GUI\Duplicati.GUI.TrayIcon\Duplicati.GUI.TrayIcon.csproj", "{17566860-3D98-4604-AA5B-47661F75609F}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.GUI.TrayIcon", "Duplicati\GUI\Duplicati.GUI.TrayIcon\Duplicati.GUI.TrayIcon.csproj", "{17566860-3D98-4604-AA5B-47661F75609F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Server.Serialization", "Duplicati\Server\Duplicati.Server.Serialization\Duplicati.Server.Serialization.csproj", "{33FD1D24-C28F-4C71-933F-98F1586EA76C}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Server.Serialization", "Duplicati\Server\Duplicati.Server.Serialization\Duplicati.Server.Serialization.csproj", "{33FD1D24-C28F-4C71-933F-98F1586EA76C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.BackendTool", "Duplicati\CommandLine\BackendTool\Duplicati.CommandLine.BackendTool.csproj", "{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.BackendTool", "Duplicati\CommandLine\BackendTool\Duplicati.CommandLine.BackendTool.csproj", "{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.SQLiteHelper", "Duplicati\Library\SQLiteHelper\Duplicati.Library.SQLiteHelper.csproj", "{2C838169-B187-4B09-8768-1C24C2521C8D}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.SQLiteHelper", "Duplicati\Library\SQLiteHelper\Duplicati.Library.SQLiteHelper.csproj", "{2C838169-B187-4B09-8768-1C24C2521C8D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Localization", "Duplicati\Library\Localization\Duplicati.Library.Localization.csproj", "{B68F2214-951F-4F78-8488-66E1ED3F50BF}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Localization", "Duplicati\Library\Localization\Duplicati.Library.Localization.csproj", "{B68F2214-951F-4F78-8488-66E1ED3F50BF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.AutoUpdater", "Duplicati\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj", "{7E119745-1F62-43F0-936C-F312A1912C0B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.AutoUpdater", "Duplicati\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj", "{7E119745-1F62-43F0-936C-F312A1912C0B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Service", "Duplicati\Service\Duplicati.Service.csproj", "{E93F3DE2-FF3A-4709-96A3-8190AA14FA25}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Service", "Duplicati\Service\Duplicati.Service.csproj", "{E93F3DE2-FF3A-4709-96A3-8190AA14FA25}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.AzureBlob", "Duplicati\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj", "{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.AzureBlob", "Duplicati\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj", "{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.UnitTest", "Duplicati\UnitTest\Duplicati.UnitTest.csproj", "{ECB63D1C-1724-442D-9228-DEABF14F2EA3}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.UnitTest", "Duplicati\UnitTest\Duplicati.UnitTest.csproj", "{ECB63D1C-1724-442D-9228-DEABF14F2EA3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.OAuthHelper", "Duplicati\Library\Backend\OAuthHelper\Duplicati.Library.OAuthHelper.csproj", "{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.OAuthHelper", "Duplicati\Library\Backend\OAuthHelper\Duplicati.Library.OAuthHelper.csproj", "{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.GoogleServices", "Duplicati\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj", "{5489181D-950C-44AF-873C-45EB0A3B6BD2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.GoogleServices", "Duplicati\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj", "{5489181D-950C-44AF-873C-45EB0A3B6BD2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.OpenStack", "Duplicati\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj", "{D9E4E686-423C-48EC-A392-404E7C00860C}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.OpenStack", "Duplicati\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj", "{D9E4E686-423C-48EC-A392-404E7C00860C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.RecoveryTool", "Duplicati\CommandLine\RecoveryTool\Duplicati.CommandLine.RecoveryTool.csproj", "{4A010589-76E6-4F05-A5C4-4598D5DF11F8}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.RecoveryTool", "Duplicati\CommandLine\RecoveryTool\Duplicati.CommandLine.RecoveryTool.csproj", "{4A010589-76E6-4F05-A5C4-4598D5DF11F8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Backblaze", "Duplicati\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj", "{61C43D61-4368-4942-84A3-1EB623F4EF2A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Backblaze", "Duplicati\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj", "{61C43D61-4368-4942-84A3-1EB623F4EF2A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Mega", "Duplicati\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj", "{6643A5AE-AB38-453F-ADCE-408E35A81A83}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Mega", "Duplicati\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj", "{6643A5AE-AB38-453F-ADCE-408E35A81A83}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Box", "Duplicati\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj", "{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Box", "Duplicati\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj", "{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.UsageReporter", "Duplicati\Library\UsageReporter\Duplicati.Library.UsageReporter.csproj", "{BB014EA5-CE2C-4444-8D30-38983A0E8553}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.UsageReporter", "Duplicati\Library\UsageReporter\Duplicati.Library.UsageReporter.csproj", "{BB014EA5-CE2C-4444-8D30-38983A0E8553}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.SharePoint", "Duplicati\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj", "{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.SharePoint", "Duplicati\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj", "{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsService", "Duplicati\WindowsService\WindowsService.csproj", "{BEF7AF9A-3978-4F90-8592-198BF6EA6C6B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.AlternativeFTP", "Duplicati\Library\Backend\AlternativeFTP\Duplicati.Library.Backend.AlternativeFTP.csproj", "{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.AlternativeFTP", "Duplicati\Library\Backend\AlternativeFTP\Duplicati.Library.Backend.AlternativeFTP.csproj", "{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Dropbox", "Duplicati\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj", "{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Dropbox", "Duplicati\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj", "{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Tools", "Duplicati\Tools\Duplicati.Tools.csproj", "{0797AA22-C5DD-4950-BB60-34765AB8C6DD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Tools", "Duplicati\Tools\Duplicati.Tools.csproj", "{0797AA22-C5DD-4950-BB60-34765AB8C6DD}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Jottacloud", "Duplicati\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj", "{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Jottacloud", "Duplicati\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj", "{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Sia", "Duplicati\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj", "{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Sia", "Duplicati\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj", "{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Rclone", "Duplicati\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj", "{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Rclone", "Duplicati\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj", "{851A1CB8-3CEB-41B4-956F-34D760D2A8E5}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Common", "Duplicati\Library\Common\Duplicati.Library.Common.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Common", "Duplicati\Library\Common\Duplicati.Library.Common.csproj", "{D63E53E4-A458-4C2F-914D-92F715F58ACF}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.ConfigurationImporter", "Duplicati\CommandLine\ConfigurationImporter\Duplicati.CommandLine.ConfigurationImporter.csproj", "{B93E3BF0-DAA7-49B7-B07D-0559C5816735}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.ConfigurationImporter", "Duplicati\CommandLine\ConfigurationImporter\Duplicati.CommandLine.ConfigurationImporter.csproj", "{B93E3BF0-DAA7-49B7-B07D-0559C5816735}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Encryption", "Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj", "{2CF2D90E-C25B-47AD-91E0-98451BAB8058}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Encryption", "Duplicati\Library\Encryption\Duplicati.Library.Encryption.csproj", "{2CF2D90E-C25B-47AD-91E0-98451BAB8058}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.AutoUpdater", "Duplicati\CommandLine\AutoUpdater\Duplicati.CommandLine.AutoUpdater.csproj", "{4D1B198B-F773-44F2-872B-2B283053323C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Storj", "Duplicati\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj", "{AE035E01-C917-4F13-A35E-78F21C1A2F17}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Storj", "Duplicati\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj", "{E9AB8491-BD4C-4E4F-84C3-0BD551CC7489}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.TencentCOS", "Duplicati\Library\Backend\TencentCOS\Duplicati.Library.Backend.TencentCOS.csproj", "{545DD6D4-9476-42D6-B51C-A28E000C489E}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.TencentCOS", "Duplicati\Library\Backend\TencentCOS\Duplicati.Library.Backend.TencentCOS.csproj", "{545DD6D4-9476-42D6-B51C-A28E000C489E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Tardigrade", "Duplicati\Library\Backend\Tardigrade\Duplicati.Library.Backend.Tardigrade.csproj", "{9A04CB37-DA72-4008-9703-3AC5191974E9}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Executables", "Executables", "{FA88A246-EF8E-46E3-90AF-539B8C0A6ADE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.Idrivee2", "Duplicati\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj", "{6B594D23-B629-465C-B799-70EE9E56C218}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "net8", "net8", "{6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.Backend.AliyunOSS", "Duplicati\Library\Backend\AliyunOSS\Duplicati.Library.Backend.AliyunOSS.csproj", "{4EB3DABC-D412-4C12-8876-41A1427A389E}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.AutoUpdater", "Executables\net8\Duplicati.CommandLine.AutoUpdater\Duplicati.CommandLine.AutoUpdater.csproj", "{95B7DD83-2C5A-4F1E-8EA7-39654B2B236A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Service", "Executables\net8\Duplicati.Service\Duplicati.Service.csproj", "{34149709-F3ED-4FB5-A087-43EB195C948B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.BackendTester", "Executables\net8\Duplicati.CommandLine.BackendTester\Duplicati.CommandLine.BackendTester.csproj", "{2F1C0C8D-5C15-4BC0-811F-87F2C98D9790}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.BackendTool", "Executables\net8\Duplicati.CommandLine.BackendTool\Duplicati.CommandLine.BackendTool.csproj", "{31FA5B9B-4CD6-4BF3-B7A9-12C1E30DCAF6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.ConfigurationImporter", "Executables\net8\Duplicati.CommandLine.ConfigurationImporter\Duplicati.CommandLine.ConfigurationImporter.csproj", "{156B9B77-C2B7-4169-8FE7-1171D221446C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine.RecoveryTool", "Executables\net8\Duplicati.CommandLine.RecoveryTool\Duplicati.CommandLine.RecoveryTool.csproj", "{0FFC557E-1B84-46A2-B6E8-06064FA7EA58}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.GUI.TrayIcon", "Executables\net8\Duplicati.GUI.TrayIcon\Duplicati.GUI.TrayIcon.csproj", "{AF32C621-30DC-40F5-8CE6-DD69053068E9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Server", "Executables\net8\Duplicati.Server\Duplicati.Server.csproj", "{55EEEBD2-CE45-45D6-9838-958F1C7354E4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsService", "Duplicati\WindowsService\WindowsService.csproj", "{8A651E2D-A7C8-4EC7-B421-7A457654811D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.WindowsService", "Executables\net8\Duplicati.WindowsService\Duplicati.WindowsService.csproj", "{5D20B150-C445-47BE-8CE8-C9F74F19A4F2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.CommandLine", "Executables\net8\Duplicati.CommandLine\Duplicati.CommandLine.csproj", "{0F5A1F4E-25FA-4D02-920D-CA2138498081}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.Idrivee2", "Duplicati\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj", "{6B594D23-B629-465C-B799-70EE9E56C218}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{C03F6DFD-805A-4BE0-9338-64870ADDB4A2} = {C03F6DFD-805A-4BE0-9338-64870ADDB4A2}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Helper Libraries", "Helper Libraries", "{566EBBDA-19A4-4056-A615-D901D57D2439}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Implementation", "Implementation", "{D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backends", "Duplicati\Library\Backends\Duplicati.Library.Backends.csproj", "{5290E237-C2CD-48F2-99D2-817F9C2163C8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.WebserverCore", "Duplicati\WebserverCore\Duplicati.WebserverCore.csproj", "{5A702CEE-DB36-4153-BD94-D8CF867E75A9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.Library.RestAPI", "Duplicati.Library.RestAPI\Duplicati.Library.RestAPI.csproj", "{C1D4D665-23A3-4216-9CD1-D67AE9AAAA4C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Duplicati.Library.Backend.AliyunOSS", "Duplicati\Library\Backend\AliyunOSS\Duplicati.Library.Backend.AliyunOSS.csproj", "{4EB3DABC-D412-4C12-8876-41A1427A389E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.SharpAESCrypt", "Executables\net8\Duplicati.CommandLine.SharpAESCrypt\Duplicati.CommandLine.SharpAESCrypt.csproj", "{FE6FD36C-E171-4599-8D55-62DA579C0864}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Duplicati.CommandLine.Snapshots", "Executables\net8\Duplicati.CommandLine.Snapshots\Duplicati.CommandLine.Snapshots.csproj", "{0364E724-1929-445E-9145-90A70B01DDC0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -267,10 +310,6 @@ Global
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BEF7AF9A-3978-4F90-8592-198BF6EA6C6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BEF7AF9A-3978-4F90-8592-198BF6EA6C6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BEF7AF9A-3978-4F90-8592-198BF6EA6C6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BEF7AF9A-3978-4F90-8592-198BF6EA6C6B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -307,30 +346,142 @@ Global
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2CF2D90E-C25B-47AD-91E0-98451BAB8058}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AE035E01-C917-4F13-A35E-78F21C1A2F17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AE035E01-C917-4F13-A35E-78F21C1A2F17}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AE035E01-C917-4F13-A35E-78F21C1A2F17}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AE035E01-C917-4F13-A35E-78F21C1A2F17}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D1B198B-F773-44F2-872B-2B283053323C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D1B198B-F773-44F2-872B-2B283053323C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D1B198B-F773-44F2-872B-2B283053323C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D1B198B-F773-44F2-872B-2B283053323C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E9AB8491-BD4C-4E4F-84C3-0BD551CC7489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E9AB8491-BD4C-4E4F-84C3-0BD551CC7489}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E9AB8491-BD4C-4E4F-84C3-0BD551CC7489}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E9AB8491-BD4C-4E4F-84C3-0BD551CC7489}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{545DD6D4-9476-42D6-B51C-A28E000C489E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{545DD6D4-9476-42D6-B51C-A28E000C489E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{545DD6D4-9476-42D6-B51C-A28E000C489E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{545DD6D4-9476-42D6-B51C-A28E000C489E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9A04CB37-DA72-4008-9703-3AC5191974E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9A04CB37-DA72-4008-9703-3AC5191974E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9A04CB37-DA72-4008-9703-3AC5191974E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9A04CB37-DA72-4008-9703-3AC5191974E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{95B7DD83-2C5A-4F1E-8EA7-39654B2B236A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{95B7DD83-2C5A-4F1E-8EA7-39654B2B236A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{95B7DD83-2C5A-4F1E-8EA7-39654B2B236A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{95B7DD83-2C5A-4F1E-8EA7-39654B2B236A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{34149709-F3ED-4FB5-A087-43EB195C948B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{34149709-F3ED-4FB5-A087-43EB195C948B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{34149709-F3ED-4FB5-A087-43EB195C948B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{34149709-F3ED-4FB5-A087-43EB195C948B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2F1C0C8D-5C15-4BC0-811F-87F2C98D9790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2F1C0C8D-5C15-4BC0-811F-87F2C98D9790}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2F1C0C8D-5C15-4BC0-811F-87F2C98D9790}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2F1C0C8D-5C15-4BC0-811F-87F2C98D9790}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{31FA5B9B-4CD6-4BF3-B7A9-12C1E30DCAF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{31FA5B9B-4CD6-4BF3-B7A9-12C1E30DCAF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{31FA5B9B-4CD6-4BF3-B7A9-12C1E30DCAF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{31FA5B9B-4CD6-4BF3-B7A9-12C1E30DCAF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{156B9B77-C2B7-4169-8FE7-1171D221446C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{156B9B77-C2B7-4169-8FE7-1171D221446C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{156B9B77-C2B7-4169-8FE7-1171D221446C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{156B9B77-C2B7-4169-8FE7-1171D221446C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0FFC557E-1B84-46A2-B6E8-06064FA7EA58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0FFC557E-1B84-46A2-B6E8-06064FA7EA58}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0FFC557E-1B84-46A2-B6E8-06064FA7EA58}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0FFC557E-1B84-46A2-B6E8-06064FA7EA58}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF32C621-30DC-40F5-8CE6-DD69053068E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF32C621-30DC-40F5-8CE6-DD69053068E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF32C621-30DC-40F5-8CE6-DD69053068E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF32C621-30DC-40F5-8CE6-DD69053068E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55EEEBD2-CE45-45D6-9838-958F1C7354E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55EEEBD2-CE45-45D6-9838-958F1C7354E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55EEEBD2-CE45-45D6-9838-958F1C7354E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55EEEBD2-CE45-45D6-9838-958F1C7354E4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8A651E2D-A7C8-4EC7-B421-7A457654811D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8A651E2D-A7C8-4EC7-B421-7A457654811D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A651E2D-A7C8-4EC7-B421-7A457654811D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A651E2D-A7C8-4EC7-B421-7A457654811D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5D20B150-C445-47BE-8CE8-C9F74F19A4F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5D20B150-C445-47BE-8CE8-C9F74F19A4F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5D20B150-C445-47BE-8CE8-C9F74F19A4F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5D20B150-C445-47BE-8CE8-C9F74F19A4F2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0F5A1F4E-25FA-4D02-920D-CA2138498081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0F5A1F4E-25FA-4D02-920D-CA2138498081}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0F5A1F4E-25FA-4D02-920D-CA2138498081}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0F5A1F4E-25FA-4D02-920D-CA2138498081}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B594D23-B629-465C-B799-70EE9E56C218}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B594D23-B629-465C-B799-70EE9E56C218}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B594D23-B629-465C-B799-70EE9E56C218}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B594D23-B629-465C-B799-70EE9E56C218}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EB3DABC-D412-4C12-8876-41A1427A389E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EB3DABC-D412-4C12-8876-41A1427A389E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EB3DABC-D412-4C12-8876-41A1427A389E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EB3DABC-D412-4C12-8876-41A1427A389E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5290E237-C2CD-48F2-99D2-817F9C2163C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5290E237-C2CD-48F2-99D2-817F9C2163C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5290E237-C2CD-48F2-99D2-817F9C2163C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5290E237-C2CD-48F2-99D2-817F9C2163C8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5A702CEE-DB36-4153-BD94-D8CF867E75A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5A702CEE-DB36-4153-BD94-D8CF867E75A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5A702CEE-DB36-4153-BD94-D8CF867E75A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5A702CEE-DB36-4153-BD94-D8CF867E75A9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C1D4D665-23A3-4216-9CD1-D67AE9AAAA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C1D4D665-23A3-4216-9CD1-D67AE9AAAA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C1D4D665-23A3-4216-9CD1-D67AE9AAAA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C1D4D665-23A3-4216-9CD1-D67AE9AAAA4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FE6FD36C-E171-4599-8D55-62DA579C0864}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FE6FD36C-E171-4599-8D55-62DA579C0864}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FE6FD36C-E171-4599-8D55-62DA579C0864}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FE6FD36C-E171-4599-8D55-62DA579C0864}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0364E724-1929-445E-9145-90A70B01DDC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0364E724-1929-445E-9145-90A70B01DDC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0364E724-1929-445E-9145-90A70B01DDC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0364E724-1929-445E-9145-90A70B01DDC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{FC9B7611-836F-4127-8B44-A7C31F506807} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{F61679A9-E5DE-468A-B5A4-05F92D0143D2} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{19ECCE09-B5EB-406C-8C57-BAC66997D469} = {566EBBDA-19A4-4056-A615-D901D57D2439}
|
||||
{C03F6DFD-805A-4BE0-9338-64870ADDB4A2} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{81765A64-3661-4E3E-B850-2F6F87A51F74} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{BAE27510-8B5D-44B2-B33E-372A98908041} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{1BFAE226-8364-4086-825C-BB83F6F3EE4C} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{E7280DCA-7776-4A73-B9B5-41FD77FC8799} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{0CA86ECF-5BEC-4909-B4F6-110A03B30B92} = {566EBBDA-19A4-4056-A615-D901D57D2439}
|
||||
{C0270709-2A40-43B5-8CF1-69581B9FA2A1} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{CCD76347-7DC7-4B42-B7E1-E500E624CAC3} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{FF2BF37C-E502-4C98-BEA0-701671DDFA08} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{19E661D2-C5DA-4F35-B3EE-7586E5734B5F} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{17566860-3D98-4604-AA5B-47661F75609F} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{2C838169-B187-4B09-8768-1C24C2521C8D} = {566EBBDA-19A4-4056-A615-D901D57D2439}
|
||||
{E93F3DE2-FF3A-4709-96A3-8190AA14FA25} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{8E4CECFB-0413-4B00-AB93-78D1C3902BD5} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{5489181D-950C-44AF-873C-45EB0A3B6BD2} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{D9E4E686-423C-48EC-A392-404E7C00860C} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{4A010589-76E6-4F05-A5C4-4598D5DF11F8} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{61C43D61-4368-4942-84A3-1EB623F4EF2A} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{6643A5AE-AB38-453F-ADCE-408E35A81A83} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{59C8BBC5-6E42-46FB-AB3E-6C183A82459A} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{2CD5DBC3-3DA6-432D-BA97-F0B8D24501C2} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{32A74526-3E5F-413A-8CB4-1EFDAD4C8B91} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{851A1CB8-3CEB-41B4-956F-34D760D2A8E5} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{B93E3BF0-DAA7-49B7-B07D-0559C5816735} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{4D1B198B-F773-44F2-872B-2B283053323C} = {D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B}
|
||||
{E9AB8491-BD4C-4E4F-84C3-0BD551CC7489} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{545DD6D4-9476-42D6-B51C-A28E000C489E} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3} = {FA88A246-EF8E-46E3-90AF-539B8C0A6ADE}
|
||||
{95B7DD83-2C5A-4F1E-8EA7-39654B2B236A} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{34149709-F3ED-4FB5-A087-43EB195C948B} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{2F1C0C8D-5C15-4BC0-811F-87F2C98D9790} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{31FA5B9B-4CD6-4BF3-B7A9-12C1E30DCAF6} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{156B9B77-C2B7-4169-8FE7-1171D221446C} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{0FFC557E-1B84-46A2-B6E8-06064FA7EA58} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{AF32C621-30DC-40F5-8CE6-DD69053068E9} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{55EEEBD2-CE45-45D6-9838-958F1C7354E4} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{8A651E2D-A7C8-4EC7-B421-7A457654811D} = {566EBBDA-19A4-4056-A615-D901D57D2439}
|
||||
{5D20B150-C445-47BE-8CE8-C9F74F19A4F2} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{0F5A1F4E-25FA-4D02-920D-CA2138498081} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{6B594D23-B629-465C-B799-70EE9E56C218} = {E1A9B303-F281-45C5-A4F6-CADD9DE3F3C4}
|
||||
{D19A38DD-68F1-4EF5-BF5F-8966CE0D9A5B} = {FA88A246-EF8E-46E3-90AF-539B8C0A6ADE}
|
||||
{FE6FD36C-E171-4599-8D55-62DA579C0864} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
{0364E724-1929-445E-9145-90A70B01DDC0} = {6B46F6B1-1898-49B8-ADA7-5CAF68EB77E3}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8B40BAFE-D862-4397-9495-8F5EAF5CE80C}
|
||||
EndGlobalSection
|
||||
@@ -346,8 +497,4 @@ Global
|
||||
$5.EolMarker = Windows
|
||||
$5.scope = text/plain
|
||||
EndGlobalSection
|
||||
GlobalSection(SubversionScc) = preSolution
|
||||
Svn-Managed = True
|
||||
Manager = AnkhSVN - Subversion Support for Visual Studio
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AssemblyName>Duplicati.CommandLine.AutoUpdater.Implementation</AssemblyName>
|
||||
<RootNamespace>Duplicati.CommandLine.AutoUpdater</RootNamespace>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Common\Duplicati.Library.Common.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Analyzers.Compatibility" Version="0.2.12-alpha">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,218 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E7280DCA-7776-4A73-B9B5-41FD77FC8799}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Duplicati.CommandLine.BackendTester</RootNamespace>
|
||||
<AssemblyName>Duplicati.CommandLine.BackendTester</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
<AssemblyOriginatorKeyFile>Duplicati.snk</AssemblyOriginatorKeyFile>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<UseMSBuildEngine>false</UseMSBuildEngine>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Commandlineparameters>~/.config/dupl-unittest.txt</Commandlineparameters>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariables>
|
||||
<Variable name="AUTOUPDATER_Duplicati_SKIP_UPDATE" value="1" />
|
||||
</EnvironmentVariables>
|
||||
</EnvironmentVariables>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="NonSeekableStream.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Duplicati.snk" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj">
|
||||
<Project>{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}</Project>
|
||||
<Name>Duplicati.Library.Backend.AzureBlob</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj">
|
||||
<Project>{b20a7cee-9c5b-47b9-8b76-bc85adfe8493}</Project>
|
||||
<Name>Duplicati.Library.Backend.Dropbox</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj">
|
||||
<Project>{6b594d23-b629-465c-b799-70ee9e56c218}</Project>
|
||||
<Name>Duplicati.Library.Backend.Idrivee2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj">
|
||||
<Project>{2cd5dbc3-3da6-432d-ba97-f0b8d24501c2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Jottacloud</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj">
|
||||
<Project>{851a1cb8-3ceb-41b4-956f-34d760d2a8e5}</Project>
|
||||
<Name>Duplicati.Library.Backend.Rclone</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj">
|
||||
<Project>{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}</Project>
|
||||
<Name>Duplicati.Library.Backend.SharePoint</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj">
|
||||
<Project>{32a74526-3e5f-413a-8cb4-1efdad4c8b91}</Project>
|
||||
<Name>Duplicati.Library.Backend.Sia</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj">
|
||||
<Project>{ae035e01-c917-4f13-a35e-78f21c1a2f17}</Project>
|
||||
<Name>Duplicati.Library.Backend.Storj</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Tardigrade\Duplicati.Library.Backend.Tardigrade.csproj">
|
||||
<Project>{9a04cb37-da72-4008-9703-3ac5191974e9}</Project>
|
||||
<Name>Duplicati.Library.Backend.Tardigrade</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\TencentCOS\Duplicati.Library.Backend.TencentCOS.csproj">
|
||||
<Project>{545dd6d4-9476-42d6-b51c-a28e000c489e}</Project>
|
||||
<Name>Duplicati.Library.Backend.TencentCOS</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj">
|
||||
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
|
||||
<Name>Duplicati.Library.DynamicLoader</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Interface\Duplicati.Library.Interface.csproj">
|
||||
<Project>{C5899F45-B0FF-483C-9D38-24A9FCAAB237}</Project>
|
||||
<Name>Duplicati.Library.Interface</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj">
|
||||
<Project>{7E119745-1F62-43F0-936C-F312A1912C0B}</Project>
|
||||
<Name>Duplicati.Library.AutoUpdater</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\License\Duplicati.License.csproj">
|
||||
<Project>{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}</Project>
|
||||
<Name>Duplicati.License</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj">
|
||||
<Project>{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}</Project>
|
||||
<Name>Duplicati.Library.Backend.OneDrive</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj">
|
||||
<Project>{C0270709-2A40-43B5-8CF1-69581B9FA2A1}</Project>
|
||||
<Name>Duplicati.Library.Backend.TahoeLAFS</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj">
|
||||
<Project>{5489181D-950C-44AF-873C-45EB0A3B6BD2}</Project>
|
||||
<Name>Duplicati.Library.Backend.GoogleServices</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj">
|
||||
<Project>{D9E4E686-423C-48EC-A392-404E7C00860C}</Project>
|
||||
<Name>Duplicati.Library.Backend.OpenStack</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj">
|
||||
<Project>{1BFAE226-8364-4086-825C-BB83F6F3EE4C}</Project>
|
||||
<Name>Duplicati.Library.Backend.CloudFiles</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\File\Duplicati.Library.Backend.File.csproj">
|
||||
<Project>{FC9B7611-836F-4127-8B44-A7C31F506807}</Project>
|
||||
<Name>Duplicati.Library.Backend.File</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj">
|
||||
<Project>{F61679A9-E5DE-468A-B5A4-05F92D0143D2}</Project>
|
||||
<Name>Duplicati.Library.Backend.FTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj">
|
||||
<Project>{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}</Project>
|
||||
<Name>Duplicati.Library.Backend.S3</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj">
|
||||
<Project>{FF2BF37C-E502-4C98-BEA0-701671DDFA08}</Project>
|
||||
<Name>Duplicati.Library.Backend.SSHv2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj">
|
||||
<Project>{BAE27510-8B5D-44B2-B33E-372A98908041}</Project>
|
||||
<Name>Duplicati.Library.Backend.WEBDAV</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Modules\Builtin\Duplicati.Library.Modules.Builtin.csproj">
|
||||
<Project>{52826615-7964-47FE-B4B3-1B2DBDF605B9}</Project>
|
||||
<Name>Duplicati.Library.Modules.Builtin</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OAuthHelper\Duplicati.Library.OAuthHelper.csproj">
|
||||
<Project>{D4C37C33-5E73-4B56-B2C3-DC4A6BAA36BB}</Project>
|
||||
<Name>Duplicati.Library.OAuthHelper</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Localization\Duplicati.Library.Localization.csproj">
|
||||
<Project>{B68F2214-951F-4F78-8488-66E1ED3F50BF}</Project>
|
||||
<Name>Duplicati.Library.Localization</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Logging\Duplicati.Library.Logging.csproj">
|
||||
<Project>{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}</Project>
|
||||
<Name>Duplicati.Library.Logging</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj">
|
||||
<Project>{61C43D61-4368-4942-84A3-1EB623F4EF2A}</Project>
|
||||
<Name>Duplicati.Library.Backend.Backblaze</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj">
|
||||
<Project>{6643A5AE-AB38-453F-ADCE-408E35A81A83}</Project>
|
||||
<Name>Duplicati.Library.Backend.Mega</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj">
|
||||
<Project>{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Box</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\AlternativeFTP\Duplicati.Library.Backend.AlternativeFTP.csproj">
|
||||
<Project>{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}</Project>
|
||||
<Name>Duplicati.Library.Backend.AlternativeFTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Common\Duplicati.Library.Common.csproj">
|
||||
<Project>{D63E53E4-A458-4C2F-914D-92F715F58ACF}</Project>
|
||||
<Name>Duplicati.Library.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Compression\Duplicati.Library.Compression.csproj">
|
||||
<Project>{19ECCE09-B5EB-406C-8C57-BAC66997D469}</Project>
|
||||
<Name>Duplicati.Library.Compression</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\SQLiteHelper\Duplicati.Library.SQLiteHelper.csproj">
|
||||
<Project>{2C838169-B187-4B09-8768-1C24C2521C8D}</Project>
|
||||
<Name>Duplicati.Library.SQLiteHelper</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Description>A backend debugging tool for Duplicati</Description>
|
||||
<AssemblyName>Duplicati.CommandLine.BackendTester.Implementation</AssemblyName>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj" />
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj" />
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj" />
|
||||
<ProjectReference Include="..\..\License\Duplicati.License.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Modules\Builtin\Duplicati.Library.Modules.Builtin.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Backend\OAuthHelper\Duplicati.Library.OAuthHelper.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Localization\Duplicati.Library.Localization.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Logging\Duplicati.Library.Logging.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Common\Duplicati.Library.Common.csproj" />
|
||||
<ProjectReference Include="..\..\Library\SQLiteHelper\Duplicati.Library.SQLiteHelper.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Analyzers.Compatibility" Version="0.2.12-alpha">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,23 +1,23 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -29,9 +29,8 @@ using System.Threading;
|
||||
|
||||
namespace Duplicati.CommandLine.BackendTester
|
||||
{
|
||||
class Program
|
||||
public class Program
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Used to maintain a reference to initialized system settings.
|
||||
/// </summary>
|
||||
@@ -63,13 +62,7 @@ namespace Duplicati.CommandLine.BackendTester
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
Duplicati.Library.AutoUpdater.UpdaterManager.IgnoreWebrootFolder = true;
|
||||
return Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent(typeof(Program).GetMethod("RealMain"), args);
|
||||
}
|
||||
|
||||
public static void RealMain(string[] _args)
|
||||
public static int Main(string[] _args)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -107,7 +100,7 @@ namespace Duplicati.CommandLine.BackendTester
|
||||
foreach (string s in lines)
|
||||
Console.WriteLine(s);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options.ContainsKey("tempdir") && !string.IsNullOrEmpty(options["tempdir"]))
|
||||
@@ -129,14 +122,17 @@ namespace Duplicati.CommandLine.BackendTester
|
||||
{
|
||||
Console.WriteLine("Starting run no {0}", i);
|
||||
if (!Run(args, options, i == 0))
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
Console.WriteLine("Unittest complete!");
|
||||
return 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Unittest failed: " + ex);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool Run(List<string> args, Dictionary<string, string> options, bool first)
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CommandLine.BackendTester")]
|
||||
[assembly: AssemblyDescription("A backend debugging tool for Duplicati")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Duplicati Team")]
|
||||
[assembly: AssemblyProduct("CommandLine.BackendTester")]
|
||||
[assembly: AssemblyCopyright("Copyright © Duplicati Team 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("53df9eb0-a6e8-49a2-838d-b2a2c4a8d41f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("2.0.0.7")]
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
[assembly: AssemblyFileVersion("2.0.0.7")]
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Azure.KeyVault.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.4.0" newVersion="3.0.4.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.2.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -1,171 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<RootNamespace>Duplicati.CommandLine.BackendTool</RootNamespace>
|
||||
<AssemblyName>Duplicati.CommandLine.BackendTool</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>..\Duplicati.snk</AssemblyOriginatorKeyFile>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<UseMSBuildEngine>false</UseMSBuildEngine>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariables>
|
||||
<Variable name="AUTOUPDATER_Duplicati_SKIP_UPDATE" value="1" />
|
||||
</EnvironmentVariables>
|
||||
</EnvironmentVariables>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj">
|
||||
<Project>{1BFAE226-8364-4086-825C-BB83F6F3EE4C}</Project>
|
||||
<Name>Duplicati.Library.Backend.CloudFiles</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj">
|
||||
<Project>{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}</Project>
|
||||
<Name>Duplicati.Library.Backend.AzureBlob</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\File\Duplicati.Library.Backend.File.csproj">
|
||||
<Project>{FC9B7611-836F-4127-8B44-A7C31F506807}</Project>
|
||||
<Name>Duplicati.Library.Backend.File</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj">
|
||||
<Project>{F61679A9-E5DE-468A-B5A4-05F92D0143D2}</Project>
|
||||
<Name>Duplicati.Library.Backend.FTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj">
|
||||
<Project>{6b594d23-b629-465c-b799-70ee9e56c218}</Project>
|
||||
<Name>Duplicati.Library.Backend.Idrivee2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj">
|
||||
<Project>{2cd5dbc3-3da6-432d-ba97-f0b8d24501c2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Jottacloud</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj">
|
||||
<Project>{851a1cb8-3ceb-41b4-956f-34d760d2a8e5}</Project>
|
||||
<Name>Duplicati.Library.Backend.Rclone</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj">
|
||||
<Project>{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}</Project>
|
||||
<Name>Duplicati.Library.Backend.S3</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj">
|
||||
<Project>{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}</Project>
|
||||
<Name>Duplicati.Library.Backend.SharePoint</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj">
|
||||
<Project>{32a74526-3e5f-413a-8cb4-1efdad4c8b91}</Project>
|
||||
<Name>Duplicati.Library.Backend.Sia</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj">
|
||||
<Project>{FF2BF37C-E502-4C98-BEA0-701671DDFA08}</Project>
|
||||
<Name>Duplicati.Library.Backend.SSHv2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj">
|
||||
<Project>{C0270709-2A40-43B5-8CF1-69581B9FA2A1}</Project>
|
||||
<Name>Duplicati.Library.Backend.TahoeLAFS</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj">
|
||||
<Project>{ae035e01-c917-4f13-a35e-78f21c1a2f17}</Project>
|
||||
<Name>Duplicati.Library.Backend.Storj</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Tardigrade\Duplicati.Library.Backend.Tardigrade.csproj">
|
||||
<Project>{9a04cb37-da72-4008-9703-3ac5191974e9}</Project>
|
||||
<Name>Duplicati.Library.Backend.Tardigrade</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\TencentCOS\Duplicati.Library.Backend.TencentCOS.csproj">
|
||||
<Project>{545dd6d4-9476-42d6-b51c-a28e000c489e}</Project>
|
||||
<Name>Duplicati.Library.Backend.TencentCOS</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj">
|
||||
<Project>{BAE27510-8B5D-44B2-B33E-372A98908041}</Project>
|
||||
<Name>Duplicati.Library.Backend.WEBDAV</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj">
|
||||
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
|
||||
<Name>Duplicati.Library.DynamicLoader</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Interface\Duplicati.Library.Interface.csproj">
|
||||
<Project>{C5899F45-B0FF-483C-9D38-24A9FCAAB237}</Project>
|
||||
<Name>Duplicati.Library.Interface</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj">
|
||||
<Project>{7E119745-1F62-43F0-936C-F312A1912C0B}</Project>
|
||||
<Name>Duplicati.Library.AutoUpdater</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\License\Duplicati.License.csproj">
|
||||
<Project>{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}</Project>
|
||||
<Name>Duplicati.License</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj">
|
||||
<Project>{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}</Project>
|
||||
<Name>Duplicati.Library.Backend.OneDrive</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj">
|
||||
<Project>{5489181D-950C-44AF-873C-45EB0A3B6BD2}</Project>
|
||||
<Name>Duplicati.Library.Backend.GoogleServices</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj">
|
||||
<Project>{D9E4E686-423C-48EC-A392-404E7C00860C}</Project>
|
||||
<Name>Duplicati.Library.Backend.OpenStack</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj">
|
||||
<Project>{61C43D61-4368-4942-84A3-1EB623F4EF2A}</Project>
|
||||
<Name>Duplicati.Library.Backend.Backblaze</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj">
|
||||
<Project>{6643A5AE-AB38-453F-ADCE-408E35A81A83}</Project>
|
||||
<Name>Duplicati.Library.Backend.Mega</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj">
|
||||
<Project>{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Box</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\AlternativeFTP\Duplicati.Library.Backend.AlternativeFTP.csproj">
|
||||
<Project>{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}</Project>
|
||||
<Name>Duplicati.Library.Backend.AlternativeFTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj">
|
||||
<Project>{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}</Project>
|
||||
<Name>Duplicati.Library.Backend.Dropbox</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<AssemblyName>Duplicati.CommandLine.BackendTool.Implementation</AssemblyName>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj" />
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj" />
|
||||
<ProjectReference Include="..\..\License\Duplicati.License.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Analyzers.Compatibility" Version="0.2.12-alpha">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
||||
@@ -34,13 +34,7 @@ namespace Duplicati.CommandLine.BackendTool
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
Duplicati.Library.AutoUpdater.UpdaterManager.IgnoreWebrootFolder = true;
|
||||
return Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent(typeof(Program).GetMethod("RealMain"), args);
|
||||
}
|
||||
|
||||
public static int RealMain(string[] _args)
|
||||
public static int Main(string[] _args)
|
||||
{
|
||||
bool debugoutput = false;
|
||||
try
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// Information about this assembly is defined by the following attributes.
|
||||
// Change them to the values specific to your project.
|
||||
|
||||
[assembly: AssemblyTitle("Duplicati.CommandLine.BackendTool")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
|
||||
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
|
||||
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
|
||||
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
|
||||
// The following attributes are used to specify the signing key for the assembly,
|
||||
// if desired. See the Mono documentation for more information about signing.
|
||||
|
||||
//[assembly: AssemblyDelaySign(false)]
|
||||
//[assembly: AssemblyKeyFile("")]
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.2.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Azure.KeyVault.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.4.0" newVersion="3.0.4.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -24,6 +24,8 @@ using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Duplicati.Library.Common.IO;
|
||||
using Duplicati.Library.Utility;
|
||||
|
||||
@@ -38,8 +40,9 @@ namespace Duplicati.CommandLine
|
||||
private readonly System.Threading.ManualResetEvent m_readyEvent;
|
||||
private readonly System.Threading.ManualResetEvent m_finishEvent;
|
||||
private readonly ConsoleOutput m_output;
|
||||
private System.Threading.Thread m_thread;
|
||||
private readonly TimeSpan m_updateFrequency;
|
||||
private Task m_task;
|
||||
private readonly CancellationTokenSource m_cancellationTokenSource;
|
||||
|
||||
public PeriodicOutput(ConsoleOutput messageSink, TimeSpan updateFrequency)
|
||||
{
|
||||
@@ -47,10 +50,8 @@ namespace Duplicati.CommandLine
|
||||
m_readyEvent = new System.Threading.ManualResetEvent(false);
|
||||
m_finishEvent = new System.Threading.ManualResetEvent(false);
|
||||
m_updateFrequency = updateFrequency;
|
||||
m_thread = new System.Threading.Thread(this.ThreadMain);
|
||||
m_thread.IsBackground = true;
|
||||
m_thread.Name = "Periodic console writer";
|
||||
m_thread.Start();
|
||||
m_cancellationTokenSource = new CancellationTokenSource();
|
||||
m_task = Task.Run(() => this.ThreadMain(m_cancellationTokenSource.Token), m_cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
public void SetReady() { m_readyEvent.Set(); }
|
||||
@@ -58,13 +59,13 @@ namespace Duplicati.CommandLine
|
||||
|
||||
public bool Join(TimeSpan wait)
|
||||
{
|
||||
if (m_thread != null)
|
||||
return m_thread.Join(wait);
|
||||
if (m_task != null)
|
||||
return this.m_task.Wait(wait);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ThreadMain()
|
||||
private void ThreadMain(CancellationToken cancellationToken)
|
||||
{
|
||||
m_readyEvent.WaitOne();
|
||||
if (m_finishEvent.WaitOne(TimeSpan.FromMilliseconds(10), true))
|
||||
@@ -73,7 +74,7 @@ namespace Duplicati.CommandLine
|
||||
var last_count = -1L;
|
||||
var finished = false;
|
||||
|
||||
while (true)
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
float progress;
|
||||
long filesprocessed;
|
||||
@@ -110,22 +111,22 @@ namespace Duplicati.CommandLine
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (m_thread != null)
|
||||
if (m_task != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_finishEvent.Set();
|
||||
m_readyEvent.Set();
|
||||
|
||||
if (m_thread != null && m_thread.IsAlive)
|
||||
if (m_task != null)
|
||||
{
|
||||
m_thread.Abort();
|
||||
m_thread.Join(500);
|
||||
m_cancellationTokenSource.Cancel();
|
||||
m_task.Wait(500);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_thread = null;
|
||||
m_task = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,13 +134,15 @@ namespace Duplicati.CommandLine
|
||||
|
||||
public static int Examples(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
|
||||
{
|
||||
Duplicati.CommandLine.Help.PrintUsage(outwriter, "example", options);
|
||||
using (new Duplicati.Library.Main.LocaleChange(options))
|
||||
Duplicati.CommandLine.Help.PrintUsage(outwriter, "example", options);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int Help(TextWriter outwriter, Action<Duplicati.Library.Main.Controller> setup, List<string> args, Dictionary<string, string> options, Library.Utility.IFilter filter)
|
||||
{
|
||||
Duplicati.CommandLine.Help.PrintUsage(outwriter, args.Count > 1? args[1] : "help", options);
|
||||
using (new Duplicati.Library.Main.LocaleChange(options))
|
||||
Duplicati.CommandLine.Help.PrintUsage(outwriter, args.Count > 1 ? args[1] : "help", options);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,8 +177,8 @@ namespace Duplicati.CommandLine
|
||||
options["no-encryption"] = "true";
|
||||
}
|
||||
|
||||
using(var console = new ConsoleOutput(outwriter, options))
|
||||
using(var i = new Library.Main.Controller(backend, options, console))
|
||||
using (var console = new ConsoleOutput(outwriter, options))
|
||||
using (var i = new Library.Main.Controller(backend, options, console))
|
||||
{
|
||||
setup(i);
|
||||
i.ListAffected(args, res =>
|
||||
@@ -258,7 +261,7 @@ namespace Duplicati.CommandLine
|
||||
if (!containsSeparators && arg.StartsWith("@", StringComparison.Ordinal))
|
||||
{
|
||||
// Convert to Regexp filter and prefix with ".*/"
|
||||
return $"[.*{Utility.ConvertLiteralToRegExp(Util.DirectorySeparatorString + arg.Substring(1))}]";
|
||||
return $"[.*{Library.Utility.Utility.ConvertLiteralToRegExp(Util.DirectorySeparatorString + arg.Substring(1))}]";
|
||||
}
|
||||
else if (!containsSeparators && !containsWildcards && !arg.StartsWith("[", StringComparison.Ordinal))
|
||||
{
|
||||
@@ -289,7 +292,7 @@ namespace Duplicati.CommandLine
|
||||
if (endsWithSeparator && arg.StartsWith("@", StringComparison.Ordinal))
|
||||
{
|
||||
// Convert to Regexp filter and suffix with ".*"
|
||||
return $"[{Utility.ConvertLiteralToRegExp(arg.Substring(1))}.*]";
|
||||
return $"[{Library.Utility.Utility.ConvertLiteralToRegExp(arg.Substring(1))}.*]";
|
||||
}
|
||||
else if (endsWithSeparator && !containsWildcards && !arg.StartsWith("[", StringComparison.Ordinal))
|
||||
{
|
||||
@@ -323,7 +326,7 @@ namespace Duplicati.CommandLine
|
||||
filter = new Duplicati.Library.Utility.FilterExpression();
|
||||
|
||||
using (var console = new ConsoleOutput(outwriter, options))
|
||||
using(var i = new Library.Main.Controller(args[0], options, console))
|
||||
using (var i = new Library.Main.Controller(args[0], options, console))
|
||||
{
|
||||
setup(i);
|
||||
var backend = args[0];
|
||||
@@ -411,7 +414,7 @@ namespace Duplicati.CommandLine
|
||||
{
|
||||
outwriter.WriteLine("Listing filesets:");
|
||||
|
||||
foreach(var e in res.Filesets)
|
||||
foreach (var e in res.Filesets)
|
||||
{
|
||||
if (e.FileCount >= 0)
|
||||
outwriter.WriteLine("{0}\t: {1} ({2} files, {3})", e.Version, e.Time, e.FileCount, Library.Utility.Utility.FormatSizeString(e.FileSizes));
|
||||
@@ -443,10 +446,10 @@ namespace Duplicati.CommandLine
|
||||
else
|
||||
{
|
||||
outwriter.WriteLine("Listing files and versions:");
|
||||
foreach(var e in res.Files)
|
||||
foreach (var e in res.Files)
|
||||
{
|
||||
outwriter.WriteLine(e.Path);
|
||||
foreach(var nx in res.Filesets.Zip(e.Sizes, (a, b) => new { Index = a.Version, Time = a.Time, Size = b } ))
|
||||
foreach (var nx in res.Filesets.Zip(e.Sizes, (a, b) => new { Index = a.Version, Time = a.Time, Size = b }))
|
||||
outwriter.WriteLine("{0}\t: {1} {2}", nx.Index, nx.Time, nx.Size < 0 ? " - " : Library.Utility.Utility.FormatSizeString(nx.Size));
|
||||
|
||||
outwriter.WriteLine();
|
||||
@@ -470,7 +473,7 @@ namespace Duplicati.CommandLine
|
||||
}
|
||||
|
||||
using (var console = new ConsoleOutput(outwriter, options))
|
||||
using(var i = new Library.Main.Controller(args[0], options, console))
|
||||
using (var i = new Library.Main.Controller(args[0], options, console))
|
||||
{
|
||||
setup(i);
|
||||
args.RemoveAt(0);
|
||||
@@ -487,7 +490,7 @@ namespace Duplicati.CommandLine
|
||||
else
|
||||
outwriter.WriteLine(Strings.Program.DeletedBackups);
|
||||
|
||||
foreach(var f in res.DeletedSets)
|
||||
foreach (var f in res.DeletedSets)
|
||||
outwriter.WriteLine("{0}: {1}", f.Item1, f.Item2);
|
||||
}
|
||||
}
|
||||
@@ -524,7 +527,7 @@ namespace Duplicati.CommandLine
|
||||
|
||||
args = SuffixArgsWithAsterisk(PrefixArgsWithAsterisk(args)).ToList();
|
||||
|
||||
using(var output = new ConsoleOutput(outwriter, options))
|
||||
using (var output = new ConsoleOutput(outwriter, options))
|
||||
using (var i = new Library.Main.Controller(backend, options, output))
|
||||
{
|
||||
output.MessageEvent(string.Format("Restore started at {0}", DateTime.Now));
|
||||
@@ -716,7 +719,7 @@ namespace Duplicati.CommandLine
|
||||
if (args.Count != 1)
|
||||
return PrintWrongNumberOfArguments(outwriter, args, 1);
|
||||
|
||||
using(var console = new ConsoleOutput(outwriter, options))
|
||||
using (var console = new ConsoleOutput(outwriter, options))
|
||||
using (var i = new Library.Main.Controller(args[0], options, console))
|
||||
{
|
||||
setup(i);
|
||||
@@ -765,7 +768,7 @@ namespace Duplicati.CommandLine
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(var n in result.Verifications)
|
||||
foreach (var n in result.Verifications)
|
||||
{
|
||||
var changecount = n.Value.Count();
|
||||
if (changecount == 0)
|
||||
@@ -1000,7 +1003,7 @@ namespace Duplicati.CommandLine
|
||||
}
|
||||
|
||||
using (var console = new ConsoleOutput(outwriter, options))
|
||||
using(var i = new Library.Main.Controller("dummy://", options, console))
|
||||
using (var i = new Library.Main.Controller("dummy://", options, console))
|
||||
{
|
||||
setup(i);
|
||||
var result = i.TestFilter(args.ToArray(), filter);
|
||||
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Description>A commandline version of Duplicati</Description>
|
||||
<AssemblyName>Duplicati.CommandLine.Implementation</AssemblyName>
|
||||
<ApplicationIcon>TrayWarning.ico</ApplicationIcon>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Common\Duplicati.Library.Common.csproj" />
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Logging\Duplicati.Library.Logging.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Main\Duplicati.Library.Main.csproj" />
|
||||
<ProjectReference Include="..\..\License\Duplicati.License.csproj" />
|
||||
<ProjectReference Include="..\BackendTool\Duplicati.CommandLine.BackendTool.csproj" />
|
||||
<ProjectReference Include="..\BackendTester\Duplicati.CommandLine.BackendTester.csproj" />
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Localization\Duplicati.Library.Localization.csproj" />
|
||||
<ProjectReference Include="..\RecoveryTool\Duplicati.CommandLine.RecoveryTool.csproj" />
|
||||
<ProjectReference Include="..\..\Library\UsageReporter\Duplicati.Library.UsageReporter.csproj" />
|
||||
<ProjectReference Include="..\..\Tools\Duplicati.Tools.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="help.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Analyzers.Compatibility" Version="0.2.12-alpha">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -24,6 +24,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Duplicati.Library.AutoUpdater;
|
||||
using Duplicati.Library.Common;
|
||||
using FilterGroup = Duplicati.Library.Utility.FilterGroup;
|
||||
|
||||
@@ -32,18 +33,17 @@ namespace Duplicati.CommandLine
|
||||
public static class Help
|
||||
{
|
||||
private static readonly Dictionary<string, string> _document;
|
||||
private const string RESOURCE_NAME = "Duplicati.CommandLine.help.txt";
|
||||
private const string RESOURCE_NAME = "help.txt";
|
||||
private static readonly System.Text.RegularExpressions.Regex NAMEDOPTION_REGEX = new System.Text.RegularExpressions.Regex("\\%OPTION\\:(?<name>[^\\%]+)\\%");
|
||||
|
||||
static Help()
|
||||
{
|
||||
_document = new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
using (System.IO.StreamReader sr = new System.IO.StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(RESOURCE_NAME)))
|
||||
_document = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
using (var sr = new StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(Help), RESOURCE_NAME)))
|
||||
{
|
||||
List<string> keywords = new List<string>();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach(var line in sr.ReadToEnd().Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None))
|
||||
foreach (var line in sr.ReadToEnd().Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None))
|
||||
{
|
||||
if (line.Trim().StartsWith("#", StringComparison.Ordinal))
|
||||
continue;
|
||||
@@ -53,14 +53,14 @@ namespace Duplicati.CommandLine
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
string s = sb.ToString();
|
||||
foreach(var k in keywords)
|
||||
foreach (var k in keywords)
|
||||
_document[k] = s;
|
||||
|
||||
keywords.Clear();
|
||||
sb.Clear();
|
||||
}
|
||||
|
||||
string[] elems = line.Split(new string[] {" ", "\t"}, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] elems = line.Split(new string[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (elems.Length >= 2 && string.Equals(elems[elems.Length - 2], "help", StringComparison.OrdinalIgnoreCase))
|
||||
keywords.Add(elems[elems.Length - 1]);
|
||||
else if (elems.Length == 3 && string.Equals(elems[elems.Length - 1], "help", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -75,7 +75,7 @@ namespace Duplicati.CommandLine
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
string s = sb.ToString();
|
||||
foreach(var k in keywords)
|
||||
foreach (var k in keywords)
|
||||
_document[k] = s;
|
||||
}
|
||||
}
|
||||
@@ -115,14 +115,14 @@ namespace Duplicati.CommandLine
|
||||
string tp = _document[topic];
|
||||
Library.Main.Options opts = new Library.Main.Options(new Dictionary<string, string>());
|
||||
|
||||
tp = tp.Replace("%CLI_EXE%", PackageHelper.GetExecutableName(PackageHelper.NamedExecutable.CommandLine));
|
||||
tp = tp.Replace("%VERSION%", License.VersionNumbers.Version);
|
||||
tp = tp.Replace("%BACKENDS%", string.Join(", ", Library.DynamicLoader.BackendLoader.Keys));
|
||||
tp = tp.Replace("%MONO%", Library.Utility.Utility.IsMono ? "mono " : "");
|
||||
tp = tp.Replace("%APP_PATH%", System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location));
|
||||
tp = tp.Replace("%APP_PATH%", Path.Combine(UpdaterManager.INSTALLATIONDIR, PackageHelper.GetExecutableName(PackageHelper.NamedExecutable.CommandLine)));
|
||||
tp = tp.Replace("%PATH_SEPARATOR%", System.IO.Path.PathSeparator.ToString());
|
||||
tp = tp.Replace("%EXAMPLE_SOURCE_PATH%", Platform.IsClientPosix ? "/source" : @"D:\source");
|
||||
tp = tp.Replace("%EXAMPLE_SOURCE_FILE%", Platform.IsClientPosix ? "/source/myfile.txt" : @"D:\source\file.txt");
|
||||
tp = tp.Replace("%EXAMPLE_RESTORE_PATH%", Platform.IsClientPosix ? "/restore" : @"D:\restore");
|
||||
tp = tp.Replace("%EXAMPLE_SOURCE_PATH%", !OperatingSystem.IsWindows() ? "/source" : @"D:\source");
|
||||
tp = tp.Replace("%EXAMPLE_SOURCE_FILE%", !OperatingSystem.IsWindows() ? "/source/myfile.txt" : @"D:\source\file.txt");
|
||||
tp = tp.Replace("%EXAMPLE_RESTORE_PATH%", !OperatingSystem.IsWindows() ? "/restore" : @"D:\restore");
|
||||
tp = tp.Replace("%ENCRYPTIONMODULES%", string.Join(", ", Library.DynamicLoader.EncryptionLoader.Keys));
|
||||
tp = tp.Replace("%COMPRESSIONMODULES%", string.Join(", ", Library.DynamicLoader.CompressionLoader.Keys));
|
||||
tp = tp.Replace("%DEFAULTENCRYPTIONMODULE%", opts.EncryptionModule);
|
||||
@@ -132,7 +132,7 @@ namespace Duplicati.CommandLine
|
||||
tp = tp.Replace("%FILTER_GROUPS_SHORT%", string.Join(Environment.NewLine + " ", metaGroupNames.Concat(Enum.GetNames(typeof(FilterGroup)).Except(metaGroupNames, StringComparer.OrdinalIgnoreCase).OrderBy(x => x, StringComparer.OrdinalIgnoreCase)).Select(group => "{" + group + "}")));
|
||||
tp = tp.Replace("%FILTER_GROUPS_LONG%", Library.Utility.FilterGroups.GetOptionDescriptions(4, true));
|
||||
|
||||
if (Platform.IsClientWindows)
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
// These properties are only valid for Windows
|
||||
tp = tp.Replace("%EXAMPLE_WILDCARD_DRIVE_SOURCE_PATH%", @"*:\source");
|
||||
@@ -205,7 +205,7 @@ namespace Duplicati.CommandLine
|
||||
|
||||
tp = tp.Replace("%ALLOPTIONS%", string.Join(Environment.NewLine, lines.ToArray()));
|
||||
}
|
||||
|
||||
|
||||
if (tp.Contains("%MODULEOPTIONS%"))
|
||||
{
|
||||
//Figure out which module we are in
|
||||
@@ -261,7 +261,7 @@ namespace Duplicati.CommandLine
|
||||
}
|
||||
|
||||
if (NAMEDOPTION_REGEX.IsMatch(tp))
|
||||
tp = NAMEDOPTION_REGEX.Replace(tp, new Matcher().MathEvaluator);
|
||||
tp = NAMEDOPTION_REGEX.Replace(tp, new Matcher().MathEvaluator);
|
||||
|
||||
PrintFormatted(outwriter, tp.Split(new string[] { Environment.NewLine }, StringSplitOptions.None));
|
||||
}
|
||||
@@ -398,15 +398,15 @@ namespace Duplicati.CommandLine
|
||||
private static void PrintFormatted(TextWriter outwriter, IEnumerable<string> lines)
|
||||
{
|
||||
int windowWidth = 80;
|
||||
|
||||
try
|
||||
|
||||
try
|
||||
{
|
||||
// This can go wrong if we have no attached console
|
||||
if (outwriter == Console.Out)
|
||||
windowWidth = Math.Max(12, Console.WindowWidth == 0 ? 80 : Console.WindowWidth);
|
||||
windowWidth = Math.Max(12, Console.WindowWidth == 0 ? 80 : Console.WindowWidth);
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
||||
foreach (string s in lines)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s) || s.Trim().Length == 0)
|
||||
@@ -472,7 +472,7 @@ namespace Duplicati.CommandLine
|
||||
foreach (Duplicati.Library.Interface.IGenericModule mod in Library.DynamicLoader.GenericLoader.Modules)
|
||||
if (mod.SupportedCommands != null)
|
||||
foundArgs.Add(mod.SupportedCommands);
|
||||
|
||||
|
||||
foreach (IEnumerable<Library.Interface.ICommandLineArgument> arglst in foundArgs)
|
||||
if (arglst != null)
|
||||
{
|
||||
@@ -510,7 +510,7 @@ namespace Duplicati.CommandLine
|
||||
return "";
|
||||
|
||||
List<string> lines = new List<string>();
|
||||
foreach(Duplicati.Library.Interface.ICommandLineArgument arg in args)
|
||||
foreach (Duplicati.Library.Interface.ICommandLineArgument arg in args)
|
||||
if (!arg.Deprecated)
|
||||
lines.Add(PrintArgSimple(arg, arg.Name));
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// Copyright (C) 2024, The Duplicati Team
|
||||
// https://duplicati.com, hello@duplicati.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -25,7 +25,7 @@ using System.Linq;
|
||||
using Duplicati.Library.Localization.Short;
|
||||
using System.IO;
|
||||
using Duplicati.Library.Interface;
|
||||
using Duplicati.Library.Logging;
|
||||
using Duplicati.Library.AutoUpdater;
|
||||
|
||||
namespace Duplicati.CommandLine
|
||||
{
|
||||
@@ -38,14 +38,7 @@ namespace Duplicati.CommandLine
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
Duplicati.Library.AutoUpdater.UpdaterManager.IgnoreWebrootFolder = true;
|
||||
return Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent(typeof(Program).GetMethod("RealMain"), args);
|
||||
}
|
||||
|
||||
public static int RealMain(string[] args)
|
||||
{
|
||||
Library.UsageReporter.Reporter.Initialize();
|
||||
FROM_COMMANDLINE = true;
|
||||
@@ -101,7 +94,7 @@ namespace Duplicati.CommandLine
|
||||
|
||||
private static int ShowChangeLog(TextWriter outwriter)
|
||||
{
|
||||
var path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "changelog.txt");
|
||||
var path = System.IO.Path.Combine(UpdaterManager.INSTALLATIONDIR, "changelog.txt");
|
||||
outwriter.WriteLine(System.IO.File.ReadAllText(path));
|
||||
return 0;
|
||||
}
|
||||
@@ -114,18 +107,28 @@ namespace Duplicati.CommandLine
|
||||
|
||||
if (update != null && update.Version != Library.AutoUpdater.UpdaterManager.SelfVersion.Version)
|
||||
{
|
||||
outwriter.WriteLine("Found update \"{0}\", downloading ...", update.Displayname);
|
||||
long lastpg = 0;
|
||||
Library.AutoUpdater.UpdaterManager.DownloadAndUnpackUpdate(update, f =>
|
||||
var package = update.FindPackage();
|
||||
if (package == null)
|
||||
{
|
||||
var npg = (long)(f * 100);
|
||||
if (Math.Abs(npg - lastpg) >= 5 || (npg == 100 && lastpg != 100))
|
||||
outwriter.WriteLine($"Failed to locate a matching package for this machine, please visit this link and select the correct package: {update.GetGenericUpdatePageUrl()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var filename = Path.GetFullPath(package.GetFilename());
|
||||
outwriter.WriteLine("Downloading update \"{0}\" to {1} ...", update.Displayname, filename);
|
||||
|
||||
long lastpg = 0;
|
||||
Library.AutoUpdater.UpdaterManager.DownloadUpdate(update, package, filename, f =>
|
||||
{
|
||||
lastpg = npg;
|
||||
outwriter.WriteLine("Downloading {0}% ...", npg);
|
||||
}
|
||||
});
|
||||
outwriter.WriteLine("Update \"{0}\" ({1}) installed, using on next launch", update.Displayname, update.Version);
|
||||
var npg = (long)(f * 100);
|
||||
if (Math.Abs(npg - lastpg) >= 5 || (npg == 100 && lastpg != 100))
|
||||
{
|
||||
lastpg = npg;
|
||||
outwriter.WriteLine("Downloading {0}% ...", npg);
|
||||
}
|
||||
});
|
||||
outwriter.WriteLine("Update \"{0}\" ({1}) downloaded", update.Displayname, update.Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using Duplicati.Library.Localization.Short;
|
||||
namespace Duplicati.CommandLine.Strings {
|
||||
internal static class Program {
|
||||
namespace Duplicati.CommandLine.Strings
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
public static string DeleteCommandNeedsOptions(string commandname, string[] options) { return LC.L(@"The command {0} needs at least one of the following options set: {1}", commandname, string.Join(", ", options)); }
|
||||
public static string WrongNumberOfCommandsError_v2(int actualcommands, int expectedcommands, string[] commands) { return LC.L(@"Found {0} commands but expected {1}, commands:
|
||||
{2}", actualcommands, expectedcommands, string.Join(System.Environment.NewLine, commands ?? new string[0])); }
|
||||
@@ -47,13 +49,12 @@ namespace Duplicati.CommandLine.Strings {
|
||||
public static string IncludeShort { get { return LC.L(@"Include files"); } }
|
||||
public static string ExcludeLong { get { return LC.L(@"Exclude files that match this filter. The special character * means any number of character, and the special character ? means any single character, use *.txt to exclude all files with a txt extension. Regular expressions are also supported and can be supplied by using hard braces, i.e. [.*\.txt]. Filter groups (which encapsulate a built-in set of well-known files and folders) can be specified by using curly braces, i.e. {{TemporaryFiles}}."); } }
|
||||
public static string ExcludeShort { get { return LC.L(@"Exclude files"); } }
|
||||
public static string ControlFilesOptionShort { get { return LC.L(@"If this option is used with a backup operation, it is interpreted as a list of files to add to the filesets. When used with list or restore, it will list or restore the control files instead of the normal files."); } }
|
||||
public static string ControlFilesOptionLong { get { return LC.L(@"Use control files"); } }
|
||||
public static string ControlFilesOptionShort { get { return LC.L(@"Use control files"); } }
|
||||
public static string ControlFilesOptionLong { get { return LC.L(@"If this option is used with a backup operation, it is interpreted as a list of files to add to the filesets. When used with list or restore, it will list or restore the control files instead of the normal files."); } }
|
||||
public static string QuietConsoleOptionLong { get { return LC.L(@"If this option is set, progress reports and other messages that would normally go to the console will be redirected to the log."); } }
|
||||
public static string QuietConsoleOptionShort { get { return LC.L(@"Disable console output"); } }
|
||||
public static string SkippingSourceArgumentsOnNonBackupOperation { get { return @"The --source argument was specified in the parameter file, but the current operation is not a backup operation, so the argument is ignored"; } }
|
||||
|
||||
|
||||
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
// This is a placeholder message that is intended to be used with the code
|
||||
// for each error and log message. The idea is that the commandline will
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -9,17 +9,17 @@
|
||||
> duplicati.commandline.exe
|
||||
> duplicati.commandline.exe help
|
||||
|
||||
See duplicati.commandline.exe help <topic> for more information.
|
||||
See %CLI_EXE% help <topic> for more information.
|
||||
General: example, changelog
|
||||
Commands: backup, find, restore, delete, compact, test, compare, purge, vacuum
|
||||
Repair: repair, affected, list-broken-files, purge-broken-files
|
||||
Debug: debug, logging, create-report, test-filters, system-info, send-mail
|
||||
Targets: %BACKENDS%
|
||||
Modules: %ENCRYPTIONMODULES%, %COMPRESSIONMODULES%, %GENERICMODULES%
|
||||
Formats: date, time, size, encryption, compression
|
||||
Formats: date, time, size, decimal, encryption, compression
|
||||
Advanced: mail, advanced, returncodes, filter, filter-groups, <option>
|
||||
|
||||
http://www.duplicati.com/ Version: %VERSION%
|
||||
https://duplicati.com/ Version: %VERSION%
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Show the last changes to Duplicati
|
||||
==================================
|
||||
Duplicati updates automatically when a newer version is available. The following command will show a list of versions and changes.
|
||||
|
||||
%MONO%"%APP_PATH%" changelog
|
||||
"%APP_PATH%" changelog
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help system-info
|
||||
@@ -40,7 +40,7 @@ Show system information as seen by Duplicati
|
||||
============================================
|
||||
Issue the following command to see a variety of system information relevant to Duplicati.
|
||||
|
||||
%MONO%"%APP_PATH%" system-info
|
||||
"%APP_PATH%" system-info
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help example
|
||||
@@ -50,25 +50,25 @@ Make an encrypted backup
|
||||
========================
|
||||
The following command will make an encrypted backup and store it on an FTP server. As no passphrase is specified, the user is prompted for a password. The upload speed is throttled to 500kB/s. Backups older than one month are considered old. Old backups are deleted automatically. The maximum file size is limited to 50MB (default).
|
||||
|
||||
%MONO%"%APP_PATH%" backup ftp://me:example.com@ftp.example.com/target "%EXAMPLE_SOURCE_PATH%" --throttle=500kB
|
||||
"%APP_PATH%" backup ftp://me:example.com@ftp.example.com/target "%EXAMPLE_SOURCE_PATH%" --throttle=500kB
|
||||
|
||||
Search for files in a backup
|
||||
============================
|
||||
The backup can be searched for specific files. The following command returns all files "%EXAMPLE_SOURCE_FILE%" of the last backup. File names can also contain the wildcards * and ?.
|
||||
|
||||
%MONO%"%APP_PATH%" find ftp://me:example.com@ftp.example.com/target "%EXAMPLE_SOURCE_FILE%"
|
||||
"%APP_PATH%" find ftp://me:example.com@ftp.example.com/target "%EXAMPLE_SOURCE_FILE%"
|
||||
|
||||
Restore a specific file
|
||||
=======================
|
||||
The following command will restore "%EXAMPLE_SOURCE_FILE%" from the backup in the latest version to its original destination and overwrite an existing file.
|
||||
|
||||
%MONO%"%APP_PATH%" restore ftp://me:example.com@ftp.example.com/target "%EXAMPLE_SOURCE_FILE%" --overwrite
|
||||
"%APP_PATH%" restore ftp://me:example.com@ftp.example.com/target "%EXAMPLE_SOURCE_FILE%" --overwrite
|
||||
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help backup
|
||||
|
||||
Usage: backup <storage-URL> "<source-path>" [<options>]
|
||||
Usage: %CLI_EXE% backup <storage-URL> "<source-path>" [<options>]
|
||||
|
||||
Makes a backup of <source-path> and stores it in <storage-URL>. The format for <storage-URL> is
|
||||
protocol://username:password@hostname:port/path?backend_option1=value1&backend_option2=value2.
|
||||
@@ -97,7 +97,7 @@ Usage: backup <storage-URL> "<source-path>" [<options>]
|
||||
> duplicati.commandline.exe help find
|
||||
> duplicati.commandline.exe help list
|
||||
|
||||
Usage: find <storage-URL> ["<filename>"] [<options>]
|
||||
Usage: %CLI_EXE% find <storage-URL> ["<filename>"] [<options>]
|
||||
|
||||
Finds specific files in specific backups. If <filename> is specified, all occurrences of <filename> in the backup are listed. <filename> can contain * and ? as wildcards. File names in [brackets] are interpreted as regular expression. Latest backup is searched by default. If entire path is specified, all available versions of the file are listed. If no <filename> is specified, a list of all available backups is shown.
|
||||
|
||||
@@ -116,7 +116,7 @@ Usage: find <storage-URL> ["<filename>"] [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help restore
|
||||
|
||||
Usage: restore <storage-URL> ["<filename>"] [<options>]
|
||||
Usage: %CLI_EXE% restore <storage-URL> ["<filename>"] [<options>]
|
||||
|
||||
Restores <filename> to its original destination. If <filename> exists already, <filename> is changed to <filename-timestamp.extension>. To restore all files use "*" or leave empty.
|
||||
|
||||
@@ -134,7 +134,7 @@ Usage: restore <storage-URL> ["<filename>"] [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help delete
|
||||
|
||||
Usage: delete <storage-URL> [<options>]
|
||||
Usage: %CLI_EXE% delete <storage-URL> [<options>]
|
||||
|
||||
Marks old data deleted and removes outdated dlist files. A backup is deleted when it is older than <keep-time> or when there are more newer versions than <keep-versions>. Data is considered old, when it is not required from any existing backup anymore.
|
||||
|
||||
@@ -154,7 +154,7 @@ Usage: delete <storage-URL> [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help compact
|
||||
|
||||
Usage: compact <storage-URL> [<options>]
|
||||
Usage: %CLI_EXE% compact <storage-URL> [<options>]
|
||||
|
||||
Old data is not deleted immediately as in most cases only small parts of a dblock file are old data. When the amount of old data in a dblock file grows it might be worth to replace it. This is especially the case when the number of dblock files and thus the required storage space can be reduced. When backups are frequently made and only few files have changed, the uploaded dblock files are small. At some point it might make sense to replace a large number of small files with one large file. This is what compacting does.
|
||||
|
||||
@@ -171,7 +171,7 @@ Usage: compact <storage-URL> [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help compare
|
||||
|
||||
Usage: compare <storage-URL> [<base-version>] [<compare-to>] [<options>]
|
||||
Usage: %CLI_EXE% compare <storage-URL> [<base-version>] [<compare-to>] [<options>]
|
||||
|
||||
Compares two backups and shows differences. If no versions are given, changes are shown between the two latest backups. The versions can either be timestamps or backup version numbers. If only one version is given, the most recent backup is compared to that version.
|
||||
|
||||
@@ -187,7 +187,7 @@ Usage: compare <storage-URL> [<base-version>] [<compare-to>] [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help create-report
|
||||
|
||||
Usage: create-report <storage-URL> <output-file> [<options>]
|
||||
Usage: %CLI_EXE% create-report <storage-URL> <output-file> [<options>]
|
||||
|
||||
Analyses the backup and prepares a report with anonymous information. This report can be sent to the developers for a better analysis in case something went wrong.
|
||||
|
||||
@@ -197,7 +197,7 @@ Usage: create-report <storage-URL> <output-file> [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help repair
|
||||
|
||||
Usage: repair <storage-URL> [<options>]
|
||||
Usage: %CLI_EXE% repair <storage-URL> [<options>]
|
||||
|
||||
Tries to repair the backup. If no local db is found or the db is empty, the db is re-created with data from the storage. If the db is in place but the remote storage is corrupt, the remote storage gets repaired with local data (if available).
|
||||
|
||||
@@ -206,7 +206,7 @@ Usage: repair <storage-URL> [<options>]
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help purge
|
||||
|
||||
Usage: purge <storage-URL> <filenames> [<options>]
|
||||
Usage: %CLI_EXE% purge <storage-URL> <filenames> [<options>]
|
||||
|
||||
Purges (removes) files from remote backup data. This command can either take a list of filenames or use the filters to choose which files to purge. The purge process creates new filesets on the remote destination with the purged files removed, and will start the compacting process after a purge. By default, the matching files are purged in all versions, but this can be limited by choosing one or more versions. To test what will happen, use the --dry-run flag.
|
||||
|
||||
@@ -228,11 +228,11 @@ Usage: purge <storage-URL> <filenames> [<options>]
|
||||
> duplicati.commandline.exe help list-broken-files
|
||||
> duplicati.commandline.exe help purge-broken-files
|
||||
|
||||
Usage: list-broken-files <storage-URL> [<options>]
|
||||
Usage: %CLI_EXE% list-broken-files <storage-URL> [<options>]
|
||||
|
||||
Checks the database for missing data that cause files not not be restoreable. Files can become unrestoreable if remote data files are defect or missing. Use the list-broken-files command to see what the purge-broken-files command will remove.
|
||||
|
||||
Usage: purge-broken-files <storage-URL> [<options>]
|
||||
Usage: %CLI_EXE% purge-broken-files <storage-URL> [<options>]
|
||||
|
||||
Removes all files from the database and remote storage that are no longer restoreable. Use this operation with caution, and only if you cannot recover the missing remote files, but want to continue a backup. Even with missing remote files, it may be possible to restore parts of the files that will be removed with this command.
|
||||
|
||||
@@ -244,7 +244,7 @@ Usage: purge-broken-files <storage-URL> [<options>]
|
||||
> duplicati.commandline.exe help test
|
||||
> duplicati.commandline.exe help verify
|
||||
|
||||
Usage: test <storage-URL> <samples> [<options>]
|
||||
Usage: %CLI_EXE% test <storage-URL> <samples> [<options>]
|
||||
|
||||
Verifies integrity of a backup. A random sample of dlist, dindex, dblock files is downloaded, decrypted and the content is checked against recorded size values and data hashes. <samples> specifies the number of samples to be tested. If "all” is specified, all files in the backup will be tested. This is a rolling check, i.e. when executed another time different samples are verified than in the first run. A sample consists of 1 dlist, 1 dindex, 1 dblock.
|
||||
|
||||
@@ -262,21 +262,21 @@ Usage: test <storage-URL> <samples> [<options>]
|
||||
> duplicati.commandline.exe help test-filters
|
||||
> duplicati.commandline.exe help test-filter
|
||||
|
||||
Usage: test-filters <source-path> [<options>]
|
||||
Usage: %CLI_EXE% test-filters <source-path> [<options>]
|
||||
|
||||
Scans the source files and tests against the filters specified, the console output shows which files and folders are examined and the result.
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help affected
|
||||
|
||||
Usage: affected <storage-URL> <remote-filename> [<remote-filenames>] [<options>]
|
||||
Usage: %CLI_EXE% affected <storage-URL> <remote-filename> [<remote-filenames>] [<options>]
|
||||
|
||||
Returns a report explaining what backup sets and files are affected by a remote file. You can use this option to see what source files are affected if one or more remote files are damaged or deleted. Notes that this command requires a local database to be present, if the database is not found automatically, you can set --dbpath to point to the database to use.
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help vacuum
|
||||
|
||||
Usage: vacuum <storage-URL> [<options>]
|
||||
Usage: %CLI_EXE% vacuum <storage-URL> [<options>]
|
||||
|
||||
Rebuilds the local database, repacking it into a minimal amount of disk space.
|
||||
|
||||
@@ -434,6 +434,15 @@ Whenever a size is required, you can use any of the following suffixes:
|
||||
|
||||
For speed limits, use the same format. If you enter 1MB this will be 1MB/sec.
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help decimal
|
||||
|
||||
For entering decimal values you must use the English notation, with a period as decimal separator:
|
||||
|
||||
0.1
|
||||
12.34
|
||||
|
||||
|
||||
# =============================================================================
|
||||
> duplicati.commandline.exe help filter
|
||||
> duplicati.commandline.exe help filters
|
||||
@@ -469,7 +478,7 @@ Duplicati has several built-in groups of filters, which include commonly exclude
|
||||
|
||||
Duplicati can send email notifications after each operation. Use the send-mail command to test this:
|
||||
|
||||
%MONO%"%APP_PATH%" send-mail --send-mail-to=<email-address>
|
||||
"%APP_PATH%" send-mail --send-mail-to=<email-address>
|
||||
|
||||
|
||||
--send-mail-to=<email-address>
|
||||
Regular → Executable
+15
-62
@@ -1,69 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{B93E3BF0-DAA7-49B7-B07D-0559C5816735}</ProjectGuid>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Duplicati.CommandLine.ConfigurationImporter</RootNamespace>
|
||||
<AssemblyName>Duplicati.CommandLine.ConfigurationImporter</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<AssemblyName>Duplicati.CommandLine.ConfigurationImporter.Implementation</AssemblyName>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj" />
|
||||
<ProjectReference Include="..\..\Server\Duplicati.Server.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<PackageReference Include="Microsoft.DotNet.Analyzers.Compatibility" Version="0.2.12-alpha">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{de3e5d4c-51ab-4e5e-bee8-e636cebfba65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Server\Duplicati.Server.csproj">
|
||||
<Project>{19e661d2-c5da-4f35-b3ee-7586e5734b5f}</Project>
|
||||
<Name>Duplicati.Server</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using Duplicati.Library.AutoUpdater;
|
||||
using Duplicati.Library.RestAPI;
|
||||
using Duplicati.Server.Serializable;
|
||||
using Duplicati.Server.WebServer.RESTMethods;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -29,26 +30,32 @@ namespace Duplicati.CommandLine.ConfigurationImporter
|
||||
{
|
||||
public static class ConfigurationImporter
|
||||
{
|
||||
private static readonly string usageString = $"Usage: {nameof(ConfigurationImporter)}.exe <configuration-file> --import-metadata=(true | false) --server-datafolder=<folder containing Duplicati-server.sqlite>";
|
||||
private static readonly string UsageString = $"Usage: {PackageHelper.GetExecutableName(PackageHelper.NamedExecutable.ConfigurationImporter)} <configuration-file> --import-metadata=(true | false) --server-datafolder=<folder containing Duplicati-server.sqlite>";
|
||||
|
||||
public static void Main(string[] args)
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
if (args.Length != 3)
|
||||
{
|
||||
throw new ArgumentException($"Incorrect number of input arguments. {ConfigurationImporter.usageString}");
|
||||
Console.WriteLine($"Incorrect number of input arguments.");
|
||||
Console.WriteLine(UsageString);
|
||||
return 1;
|
||||
}
|
||||
|
||||
string configurationFile = args[0];
|
||||
Dictionary<string, string> importOptions = Duplicati.Library.Utility.CommandLineParser.ExtractOptions(args.Skip(1).ToList());
|
||||
if (!importOptions.TryGetValue("import-metadata", out string importMetadataString))
|
||||
{
|
||||
throw new ArgumentException($"Invalid import-metadata argument. {ConfigurationImporter.usageString}");
|
||||
Console.WriteLine($"Missing import-metadata argument.");
|
||||
Console.WriteLine(UsageString);
|
||||
return 1;
|
||||
}
|
||||
bool importMetadata = Duplicati.Library.Utility.Utility.ParseBool(importMetadataString, false);
|
||||
|
||||
if (!importOptions.TryGetValue("server-datafolder", out string serverDatafolder))
|
||||
{
|
||||
throw new ArgumentException($"Invalid server-datafolder argument. {ConfigurationImporter.usageString}");
|
||||
Console.WriteLine($"Missing server-datafolder argument.");
|
||||
Console.WriteLine(UsageString);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Dictionary<string, string> advancedOptions = new Dictionary<string, string>
|
||||
@@ -56,8 +63,10 @@ namespace Duplicati.CommandLine.ConfigurationImporter
|
||||
{ "server-datafolder", serverDatafolder }
|
||||
};
|
||||
|
||||
ImportExportStructure importedStructure = Backups.ImportBackup(configurationFile, importMetadata, () => ConfigurationImporter.ReadPassword($"Password for {configurationFile}: "), advancedOptions);
|
||||
ImportExportStructure importedStructure = BackupImportExportHandler.ImportBackup(configurationFile, importMetadata, () => ConfigurationImporter.ReadPassword($"Password for {configurationFile}: "), advancedOptions);
|
||||
Console.WriteLine($"Imported \"{importedStructure.Backup.Name}\" with ID {importedStructure.Backup.ID} and local database at {importedStructure.Backup.DBPath}.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static string ReadPassword(string prompt)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Duplicati.CommandLine.ConfigurationImporter")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Duplicati.CommandLine.ConfigurationImporter")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("B93E3BF0-DAA7-49B7-B07D-0559C5816735")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("2.0.0.7")]
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
[assembly: AssemblyFileVersion("2.0.0.7")]
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.1.3" newVersion="4.2.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Azure.KeyVault.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.4.0" newVersion="3.0.4.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
@@ -1,263 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{81765A64-3661-4E3E-B850-2F6F87A51F74}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Duplicati.CommandLine</RootNamespace>
|
||||
<AssemblyName>Duplicati.CommandLine</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>Duplicati.snk</AssemblyOriginatorKeyFile>
|
||||
<ApplicationIcon>TrayWarning.ico</ApplicationIcon>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<UseMSBuildEngine>false</UseMSBuildEngine>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariables>
|
||||
<Variable name="AUTOUPDATER_Duplicati_SKIP_UPDATE" value="1" />
|
||||
</EnvironmentVariables>
|
||||
</EnvironmentVariables>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Azure.KeyVault.Core, Version=3.0.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Azure.KeyVault.Core.3.0.4\lib\net461\Microsoft.Azure.KeyVault.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.Edm, Version=5.8.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.OData, Version=5.8.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Data.Services.Client, Version=5.8.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.2.3.24\lib\net461\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Rest.ClientRuntime.Azure.3.3.19\lib\net461\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Runtime" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Spatial, Version=5.8.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Help.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Commands.cs" />
|
||||
<Compile Include="ConsoleOutput.cs" />
|
||||
<Compile Include="Strings.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj">
|
||||
<Project>{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}</Project>
|
||||
<Name>Duplicati.Library.Backend.AzureBlob</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\File\Duplicati.Library.Backend.File.csproj">
|
||||
<Project>{FC9B7611-836F-4127-8B44-A7C31F506807}</Project>
|
||||
<Name>Duplicati.Library.Backend.File</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj">
|
||||
<Project>{6b594d23-b629-465c-b799-70ee9e56c218}</Project>
|
||||
<Name>Duplicati.Library.Backend.Idrivee2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj">
|
||||
<Project>{2cd5dbc3-3da6-432d-ba97-f0b8d24501c2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Jottacloud</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj">
|
||||
<Project>{851a1cb8-3ceb-41b4-956f-34d760d2a8e5}</Project>
|
||||
<Name>Duplicati.Library.Backend.Rclone</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj">
|
||||
<Project>{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}</Project>
|
||||
<Name>Duplicati.Library.Backend.SharePoint</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj">
|
||||
<Project>{32a74526-3e5f-413a-8cb4-1efdad4c8b91}</Project>
|
||||
<Name>Duplicati.Library.Backend.Sia</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Tardigrade\Duplicati.Library.Backend.Tardigrade.csproj">
|
||||
<Project>{9a04cb37-da72-4008-9703-3ac5191974e9}</Project>
|
||||
<Name>Duplicati.Library.Backend.Tardigrade</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Compression\Duplicati.Library.Compression.csproj">
|
||||
<Project>{19ECCE09-B5EB-406C-8C57-BAC66997D469}</Project>
|
||||
<Name>Duplicati.Library.Compression</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj">
|
||||
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
|
||||
<Name>Duplicati.Library.DynamicLoader</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Interface\Duplicati.Library.Interface.csproj">
|
||||
<Project>{C5899F45-B0FF-483C-9D38-24A9FCAAB237}</Project>
|
||||
<Name>Duplicati.Library.Interface</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Logging\Duplicati.Library.Logging.csproj">
|
||||
<Project>{D10A5FC0-11B4-4E70-86AA-8AEA52BD9798}</Project>
|
||||
<Name>Duplicati.Library.Logging</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Main\Duplicati.Library.Main.csproj">
|
||||
<Project>{10D2D1B7-C664-41D8-9B3A-00040C3D421B}</Project>
|
||||
<Name>Duplicati.Library.Main</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Modules\Builtin\Duplicati.Library.Modules.Builtin.csproj">
|
||||
<Project>{52826615-7964-47FE-B4B3-1B2DBDF605B9}</Project>
|
||||
<Name>Duplicati.Library.Modules.Builtin</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\License\Duplicati.License.csproj">
|
||||
<Project>{4D012CB1-4B92-47F4-89B7-BF80A73A2E99}</Project>
|
||||
<Name>Duplicati.License</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj">
|
||||
<Project>{F61679A9-E5DE-468A-B5A4-05F92D0143D2}</Project>
|
||||
<Name>Duplicati.Library.Backend.FTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj">
|
||||
<Project>{1BFAE226-8364-4086-825C-BB83F6F3EE4C}</Project>
|
||||
<Name>Duplicati.Library.Backend.CloudFiles</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj">
|
||||
<Project>{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}</Project>
|
||||
<Name>Duplicati.Library.Backend.S3</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj">
|
||||
<Project>{FF2BF37C-E502-4C98-BEA0-701671DDFA08}</Project>
|
||||
<Name>Duplicati.Library.Backend.SSHv2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj">
|
||||
<Project>{C0270709-2A40-43B5-8CF1-69581B9FA2A1}</Project>
|
||||
<Name>Duplicati.Library.Backend.TahoeLAFS</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj">
|
||||
<Project>{BAE27510-8B5D-44B2-B33E-372A98908041}</Project>
|
||||
<Name>Duplicati.Library.Backend.WEBDAV</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="BackendTool\Duplicati.CommandLine.BackendTool.csproj">
|
||||
<Project>{2AF960C0-357D-4D44-A3D5-8B6E89DB0F11}</Project>
|
||||
<Name>Duplicati.CommandLine.BackendTool</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="BackendTester\Duplicati.CommandLine.BackendTester.csproj">
|
||||
<Project>{E7280DCA-7776-4A73-B9B5-41FD77FC8799}</Project>
|
||||
<Name>Duplicati.CommandLine.BackendTester</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj">
|
||||
<Project>{7E119745-1F62-43F0-936C-F312A1912C0B}</Project>
|
||||
<Name>Duplicati.Library.AutoUpdater</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj">
|
||||
<Project>{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}</Project>
|
||||
<Name>Duplicati.Library.Backend.OneDrive</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Localization\Duplicati.Library.Localization.csproj">
|
||||
<Project>{B68F2214-951F-4F78-8488-66E1ED3F50BF}</Project>
|
||||
<Name>Duplicati.Library.Localization</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj">
|
||||
<Project>{5489181D-950C-44AF-873C-45EB0A3B6BD2}</Project>
|
||||
<Name>Duplicati.Library.Backend.GoogleServices</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj">
|
||||
<Project>{D9E4E686-423C-48EC-A392-404E7C00860C}</Project>
|
||||
<Name>Duplicati.Library.Backend.OpenStack</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="RecoveryTool\Duplicati.CommandLine.RecoveryTool.csproj">
|
||||
<Project>{4A010589-76E6-4F05-A5C4-4598D5DF11F8}</Project>
|
||||
<Name>Duplicati.CommandLine.RecoveryTool</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj">
|
||||
<Project>{61C43D61-4368-4942-84A3-1EB623F4EF2A}</Project>
|
||||
<Name>Duplicati.Library.Backend.Backblaze</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj">
|
||||
<Project>{6643A5AE-AB38-453F-ADCE-408E35A81A83}</Project>
|
||||
<Name>Duplicati.Library.Backend.Mega</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj">
|
||||
<Project>{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Box</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\UsageReporter\Duplicati.Library.UsageReporter.csproj">
|
||||
<Project>{BB014EA5-CE2C-4444-8D30-38983A0E8553}</Project>
|
||||
<Name>Duplicati.Library.UsageReporter</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj">
|
||||
<Project>{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}</Project>
|
||||
<Name>Duplicati.Library.Backend.Dropbox</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Tools\Duplicati.Tools.csproj">
|
||||
<Project>{0797AA22-C5DD-4950-BB60-34765AB8C6DD}</Project>
|
||||
<Name>Duplicati.Tools</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Common\Duplicati.Library.Common.csproj">
|
||||
<Project>{D63E53E4-A458-4C2F-914D-92F715F58ACF}</Project>
|
||||
<Name>Duplicati.Library.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj">
|
||||
<Project>{AE035E01-C917-4F13-A35E-78F21C1A2F17}</Project>
|
||||
<Name>Duplicati.Library.Backend.Storj</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.manifest">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Duplicati.snk" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<EmbeddedResource Include="help.txt" />
|
||||
<Content Include="TrayWarning.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Duplicati.CommandLine")]
|
||||
[assembly: AssemblyDescription("A commandline version of Duplicati")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Duplicati Team")]
|
||||
[assembly: AssemblyProduct("Duplicati.CommandLine")]
|
||||
[assembly: AssemblyCopyright("MIT license, Copyright © Duplicati Team 2024")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bfc1d214-8825-417d-8e2c-be4bb0d6524d")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("2.0.0.7")]
|
||||
[assembly: AssemblyFileVersion("2.0.0.7")]
|
||||
@@ -1,201 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4A010589-76E6-4F05-A5C4-4598D5DF11F8}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Prefer32Bit>False</Prefer32Bit>
|
||||
<RootNamespace>Duplicati.CommandLine.RecoveryTool</RootNamespace>
|
||||
<AssemblyName>Duplicati.CommandLine.RecoveryTool</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>Duplicati.snk</AssemblyOriginatorKeyFile>
|
||||
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
|
||||
<UseMSBuildEngine>false</UseMSBuildEngine>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug</OutputPath>
|
||||
<DefineConstants>DEBUG;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<ConsolePause>false</ConsolePause>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariables>
|
||||
<Variable name="AUTOUPDATER_Duplicati_SKIP_UPDATE" value="1" />
|
||||
</EnvironmentVariables>
|
||||
</EnvironmentVariables>
|
||||
<Commandlineparameters>index /Users/kenneth/testdata/recovery --targetpath=/Users/kenneth/testdata/recovery-restored</Commandlineparameters>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Externalconsole>true</Externalconsole>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Azure.KeyVault.Core, Version=3.0.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Azure.KeyVault.Core.3.0.4\lib\net461\Microsoft.Azure.KeyVault.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Rest.ClientRuntime.2.3.24\lib\net461\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Microsoft.Rest.ClientRuntime.Azure.3.3.19\lib\net461\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\..\packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Runtime" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FileIndex.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Download.cs" />
|
||||
<Compile Include="Help.cs" />
|
||||
<Compile Include="Index.cs" />
|
||||
<Compile Include="List.cs" />
|
||||
<Compile Include="Recompress.cs" />
|
||||
<Compile Include="Restore.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj">
|
||||
<Project>{7E119745-1F62-43F0-936C-F312A1912C0B}</Project>
|
||||
<Name>Duplicati.Library.AutoUpdater</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\AzureBlob\Duplicati.Library.Backend.AzureBlob.csproj">
|
||||
<Project>{8E4CECFB-0413-4B00-AB93-78D1C3902BD5}</Project>
|
||||
<Name>Duplicati.Library.Backend.AzureBlob</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\CloudFiles\Duplicati.Library.Backend.CloudFiles.csproj">
|
||||
<Project>{1BFAE226-8364-4086-825C-BB83F6F3EE4C}</Project>
|
||||
<Name>Duplicati.Library.Backend.CloudFiles</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\File\Duplicati.Library.Backend.File.csproj">
|
||||
<Project>{FC9B7611-836F-4127-8B44-A7C31F506807}</Project>
|
||||
<Name>Duplicati.Library.Backend.File</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\FTP\Duplicati.Library.Backend.FTP.csproj">
|
||||
<Project>{F61679A9-E5DE-468A-B5A4-05F92D0143D2}</Project>
|
||||
<Name>Duplicati.Library.Backend.FTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\GoogleServices\Duplicati.Library.Backend.GoogleServices.csproj">
|
||||
<Project>{5489181D-950C-44AF-873C-45EB0A3B6BD2}</Project>
|
||||
<Name>Duplicati.Library.Backend.GoogleServices</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Idrivee2\Duplicati.Library.Backend.Idrivee2.csproj">
|
||||
<Project>{6b594d23-b629-465c-b799-70ee9e56c218}</Project>
|
||||
<Name>Duplicati.Library.Backend.Idrivee2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Jottacloud\Duplicati.Library.Backend.Jottacloud.csproj">
|
||||
<Project>{2cd5dbc3-3da6-432d-ba97-f0b8d24501c2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Jottacloud</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OneDrive\Duplicati.Library.Backend.OneDrive.csproj">
|
||||
<Project>{CCD76347-7DC7-4B42-B7E1-E500E624CAC3}</Project>
|
||||
<Name>Duplicati.Library.Backend.OneDrive</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\OpenStack\Duplicati.Library.Backend.OpenStack.csproj">
|
||||
<Project>{D9E4E686-423C-48EC-A392-404E7C00860C}</Project>
|
||||
<Name>Duplicati.Library.Backend.OpenStack</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Rclone\Duplicati.Library.Backend.Rclone.csproj">
|
||||
<Project>{851a1cb8-3ceb-41b4-956f-34d760d2a8e5}</Project>
|
||||
<Name>Duplicati.Library.Backend.Rclone</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\S3\Duplicati.Library.Backend.S3.csproj">
|
||||
<Project>{C03F6DFD-805A-4BE0-9338-64870ADDB4A2}</Project>
|
||||
<Name>Duplicati.Library.Backend.S3</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\SharePoint\Duplicati.Library.Backend.SharePoint.csproj">
|
||||
<Project>{59C8BBC5-6E42-46FB-AB3E-6C183A82459A}</Project>
|
||||
<Name>Duplicati.Library.Backend.SharePoint</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Sia\Duplicati.Library.Backend.Sia.csproj">
|
||||
<Project>{32a74526-3e5f-413a-8cb4-1efdad4c8b91}</Project>
|
||||
<Name>Duplicati.Library.Backend.Sia</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\SSHv2\Duplicati.Library.Backend.SSHv2.csproj">
|
||||
<Project>{FF2BF37C-E502-4C98-BEA0-701671DDFA08}</Project>
|
||||
<Name>Duplicati.Library.Backend.SSHv2</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\TahoeLAFS\Duplicati.Library.Backend.TahoeLAFS.csproj">
|
||||
<Project>{C0270709-2A40-43B5-8CF1-69581B9FA2A1}</Project>
|
||||
<Name>Duplicati.Library.Backend.TahoeLAFS</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Tardigrade\Duplicati.Library.Backend.Tardigrade.csproj">
|
||||
<Project>{9a04cb37-da72-4008-9703-3ac5191974e9}</Project>
|
||||
<Name>Duplicati.Library.Backend.Tardigrade</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\WEBDAV\Duplicati.Library.Backend.WEBDAV.csproj">
|
||||
<Project>{BAE27510-8B5D-44B2-B33E-372A98908041}</Project>
|
||||
<Name>Duplicati.Library.Backend.WEBDAV</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Compression\Duplicati.Library.Compression.csproj">
|
||||
<Project>{19ECCE09-B5EB-406C-8C57-BAC66997D469}</Project>
|
||||
<Name>Duplicati.Library.Compression</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj">
|
||||
<Project>{0CA86ECF-5BEC-4909-B4F6-110A03B30B92}</Project>
|
||||
<Name>Duplicati.Library.DynamicLoader</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Interface\Duplicati.Library.Interface.csproj">
|
||||
<Project>{C5899F45-B0FF-483C-9D38-24A9FCAAB237}</Project>
|
||||
<Name>Duplicati.Library.Interface</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Library.Utility</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Main\Duplicati.Library.Main.csproj">
|
||||
<Project>{10D2D1B7-C664-41D8-9B3A-00040C3D421B}</Project>
|
||||
<Name>Duplicati.Library.Main</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Backblaze\Duplicati.Library.Backend.Backblaze.csproj">
|
||||
<Project>{61C43D61-4368-4942-84A3-1EB623F4EF2A}</Project>
|
||||
<Name>Duplicati.Library.Backend.Backblaze</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Mega\Duplicati.Library.Backend.Mega.csproj">
|
||||
<Project>{6643A5AE-AB38-453F-ADCE-408E35A81A83}</Project>
|
||||
<Name>Duplicati.Library.Backend.Mega</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Box\Duplicati.Library.Backend.Box.csproj">
|
||||
<Project>{3FF7DD0B-5284-4BF9-97D9-1E4417FDABB2}</Project>
|
||||
<Name>Duplicati.Library.Backend.Box</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\AlternativeFTP\Duplicati.Library.Backend.AlternativeFTP.csproj">
|
||||
<Project>{3F47CB0C-CEE1-447F-9C26-7F8E419E3E3F}</Project>
|
||||
<Name>Duplicati.Library.Backend.AlternativeFTP</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Dropbox\Duplicati.Library.Backend.Dropbox.csproj">
|
||||
<Project>{B20A7CEE-9C5B-47B9-8B76-BC85ADFE8493}</Project>
|
||||
<Name>Duplicati.Library.Backend.Dropbox</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Common\Duplicati.Library.Common.csproj">
|
||||
<Project>{D63E53E4-A458-4C2F-914D-92F715F58ACF}</Project>
|
||||
<Name>Duplicati.Library.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\Library\Backend\Storj\Duplicati.Library.Backend.Storj.csproj">
|
||||
<Project>{AE035E01-C917-4F13-A35E-78F21C1A2F17}</Project>
|
||||
<Name>Duplicati.Library.Backend.Storj</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="help.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Description>RecoveryTool for Duplicati</Description>
|
||||
<AssemblyName>Duplicati.CommandLine.RecoveryTool.Implementation</AssemblyName>
|
||||
<Copyright>Copyright © 2024 Team Duplicati, MIT license</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Library\AutoUpdater\Duplicati.Library.AutoUpdater.csproj" />
|
||||
<ProjectReference Include="..\..\Library\DynamicLoader\Duplicati.Library.DynamicLoader.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Utility\Duplicati.Library.Utility.csproj" />
|
||||
<ProjectReference Include="..\..\Library\Main\Duplicati.Library.Main.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="help.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DotNet.Analyzers.Compatibility" Version="0.2.12-alpha">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user