Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
122dbd953c | ||
|
|
a0c7666e4e | ||
|
|
4185b0b19a | ||
|
|
a9478b95cc | ||
|
|
c68933f445 | ||
|
|
e7dd60c036 | ||
|
|
17ca161e55 | ||
|
|
e66f627407 | ||
|
|
c39312356e | ||
|
|
ac8afdd98f | ||
|
|
21e067937a | ||
|
|
12e54ccda9 | ||
|
|
e658a7b293 | ||
|
|
49478e873d | ||
|
|
30efcb2a68 | ||
|
|
7866fde20d | ||
|
|
30e903eec0 | ||
|
|
d9dedd37ee | ||
|
|
61d4ea742f | ||
|
|
02594f4dea | ||
|
|
a61e33cad9 | ||
|
|
347edc4b62 | ||
|
|
728f29152f | ||
|
|
fdde4da323 | ||
|
|
31bcd3609b | ||
|
|
ef4b8cd27b | ||
|
|
dcfc524ad7 | ||
|
|
5c161325bb | ||
|
|
cd02e61710 | ||
|
|
1ee2e7cd9d | ||
|
|
a92edc9fa7 | ||
|
|
3eb03362a4 | ||
|
|
aaf9794491 | ||
|
|
ffe519248f | ||
|
|
ecdc0164ee | ||
|
|
2dd7dccaca | ||
|
|
d5780a018a | ||
|
|
7a8b4413fc | ||
|
|
b598062db6 | ||
|
|
78187f9d6d | ||
|
|
e6c070d469 | ||
|
|
750fd9d500 | ||
|
|
9f5e755037 | ||
|
|
f43e7e3665 | ||
|
|
fc35ae44dd | ||
|
|
805842ae96 | ||
|
|
fc925444d8 | ||
|
|
6163b7f7e3 | ||
|
|
2dcbc0f5e9 | ||
|
|
3c05095538 | ||
|
|
27c2bddc5c | ||
|
|
2303d8a547 | ||
|
|
03a125e02d | ||
|
|
04f4fb4281 | ||
|
|
fd66b3561c | ||
|
|
cb4514e72c | ||
|
|
27a4ec14c7 | ||
|
|
aa3ebd1f7f | ||
|
|
f459a4aacb | ||
|
|
418b47ba3c | ||
|
|
393d09df0d | ||
|
|
115d4b582a | ||
|
|
1c5663dd83 | ||
|
|
8050e638a9 | ||
|
|
eb58b93173 | ||
|
|
99486802ef | ||
|
|
6c52d4df9b | ||
|
|
269e47a249 | ||
|
|
5753989b79 | ||
|
|
466be55df4 | ||
|
|
74f30b87ad | ||
|
|
63d70483aa | ||
|
|
6b0eaecdf1 | ||
|
|
9049457543 | ||
|
|
f6ac157993 | ||
|
|
e7cd0b65d6 | ||
|
|
8b8b0a1b8c | ||
|
|
8dae0b7973 | ||
|
|
d1d54c50d7 | ||
|
|
4f82013a55 | ||
|
|
3a5159b060 | ||
|
|
617f2d5669 | ||
|
|
3d02aa687e | ||
|
|
3bcd0a8509 | ||
|
|
c240ab4e8e | ||
|
|
8e2d47f793 | ||
|
|
3c993deedf | ||
|
|
82d7116664 | ||
|
|
015cea9c07 | ||
|
|
359c5b3c81 | ||
|
|
5c3312179c | ||
|
|
70d5c19a43 | ||
|
|
9f62c44460 | ||
|
|
542fd12343 | ||
|
|
0763be425c | ||
|
|
6b3c983e67 | ||
|
|
638c7b2fbe | ||
|
|
a55b7c8069 | ||
|
|
318fc6d676 | ||
|
|
705a55e49f | ||
|
|
39aba89186 | ||
|
|
f7bbbee464 | ||
|
|
48dbd9f7d9 | ||
|
|
1b8ed947f3 | ||
|
|
cb3ff65d05 | ||
|
|
d32581084d | ||
|
|
950b25236c | ||
|
|
fecdbc8658 | ||
|
|
1e8932b390 | ||
|
|
28ae1d81a8 | ||
|
|
d7ad941d1e | ||
|
|
0ebbf9ab33 | ||
|
|
7c4282688a | ||
|
|
e892601440 | ||
|
|
dbda800374 | ||
|
|
ba0f5edfea | ||
|
|
5953c9cccb | ||
|
|
ba95dddf12 | ||
|
|
10371accfb | ||
|
|
815d6c1286 | ||
|
|
c00c0cb387 | ||
|
|
c8433a884b | ||
|
|
7f2aad3593 | ||
|
|
cfedd020b9 | ||
|
|
116f5b5c54 | ||
|
|
5b3b3fdf84 | ||
|
|
84bc19f71f | ||
|
|
a8ddba48b7 | ||
|
|
fac8d9dcab | ||
|
|
f561dc7191 | ||
|
|
116014918b | ||
|
|
0d9543a0d8 | ||
|
|
f75f210675 | ||
|
|
cbc3c93fae | ||
|
|
f2f91d23a9 | ||
|
|
a976a59ce2 | ||
|
|
87f07c6509 | ||
|
|
04c369cdf8 | ||
|
|
9c1d4ac2fc | ||
|
|
391b45fba1 | ||
|
|
7184e02207 | ||
|
|
96693edb8b | ||
|
|
6eb2f24bb1 | ||
|
|
1dc8f1b30a | ||
|
|
8d20980aa9 | ||
|
|
a01868c49c | ||
|
|
0764d25df4 | ||
|
|
44906870e4 | ||
|
|
6ec34a9936 | ||
|
|
2b72077225 | ||
|
|
0d1627d243 | ||
|
|
63d288d85f | ||
|
|
fb4aaa54ad | ||
|
|
7419c4060e | ||
|
|
be89b5c12a | ||
|
|
e34f24e183 | ||
|
|
0a98ba0487 | ||
|
|
5a70800a31 | ||
|
|
bbc0eb8d6f | ||
|
|
8a1cca4198 | ||
|
|
3f2ef3b8b5 | ||
|
|
2e31e70881 | ||
|
|
8e8d655e66 | ||
|
|
d138308fce | ||
|
|
7ed61ccbb6 | ||
|
|
29a91f4730 | ||
|
|
8f00817927 | ||
|
|
0696b8d073 | ||
|
|
de247b3b5b | ||
|
|
0dfe32f594 | ||
|
|
5d3f2cd6fa | ||
|
|
8c48d6a90f | ||
|
|
a58c15aee3 | ||
|
|
f27efd7af0 | ||
|
|
6882dff4fc | ||
|
|
230eb927a0 | ||
|
|
365a067755 | ||
|
|
b2751af4e3 | ||
|
|
f83772efb9 | ||
|
|
23b23e0e86 | ||
|
|
98d6871300 | ||
|
|
21978735a1 | ||
|
|
d3a3d8b6ef | ||
|
|
97af0e28fc | ||
|
|
7c68547dfa | ||
|
|
7d30c12fb7 | ||
|
|
0f551b6d25 | ||
|
|
198803dee0 | ||
|
|
1d9d6941ec | ||
|
|
3deba89063 | ||
|
|
4d93a94ef6 | ||
|
|
8b34c228e7 | ||
|
|
7d2bfd702c | ||
|
|
09d42500e6 | ||
|
|
51f0f94a37 | ||
|
|
293564be75 | ||
|
|
4917f8df79 | ||
|
|
0def5df6c8 | ||
|
|
83696b3a99 | ||
|
|
7a2c7f83aa | ||
|
|
2547311ef4 | ||
|
|
5eea6e491a | ||
|
|
57984545ab | ||
|
|
d19c51c517 | ||
|
|
94860b6995 | ||
|
|
43c1cea1d2 | ||
|
|
3b188a9970 | ||
|
|
e1066e203f | ||
|
|
e74d67db3a | ||
|
|
e759173e46 | ||
|
|
f1875f09aa | ||
|
|
fbf2506f86 | ||
|
|
315db7e8fa | ||
|
|
75a89b8859 | ||
|
|
6d151f33ad | ||
|
|
bd801281db | ||
|
|
eba49439ac | ||
|
|
bc64d09a8f | ||
|
|
68bfc679df | ||
|
|
82f090f517 | ||
|
|
d58043149b | ||
|
|
690586b655 | ||
|
|
f6d37904d5 | ||
|
|
b50677ac11 | ||
|
|
509062e478 | ||
|
|
fa930c94ed | ||
|
|
545331f8e6 | ||
|
|
15c5868274 | ||
|
|
eca6cc16cc | ||
|
|
2340149f25 | ||
|
|
d9abb535fa | ||
|
|
6682ddce52 | ||
|
|
49207c04ff | ||
|
|
735ca6e1d5 | ||
|
|
071bec0924 | ||
|
|
1ae1466cad | ||
|
|
270d8f7035 | ||
|
|
b162d24b86 | ||
|
|
650277f8f6 | ||
|
|
a1d230ba9c | ||
|
|
8d8169d5b6 | ||
|
|
696aa2d67f | ||
|
|
12c94c9908 | ||
|
|
25c1fdc365 | ||
|
|
cb48b0bfa6 | ||
|
|
27f825527e | ||
|
|
1cec948022 | ||
|
|
7a0fd3f165 | ||
|
|
4071a83ab9 | ||
|
|
8078ccc8db | ||
|
|
47bb0619b6 | ||
|
|
8e06a1e78d | ||
|
|
b296874fc4 | ||
|
|
c7ef849905 | ||
|
|
ec917a651b | ||
|
|
a403b33eae | ||
|
|
359cb93566 | ||
|
|
367cc8dd08 | ||
|
|
6d647c9985 | ||
|
|
15e95777f2 | ||
|
|
5dd5019f57 | ||
|
|
f56ff4f5f2 | ||
|
|
b13951e2a3 | ||
|
|
eb1e895c0c | ||
|
|
9caacc088b | ||
|
|
7543f5ea09 | ||
|
|
2e371d2d12 | ||
|
|
290b73d981 | ||
|
|
92ac5d97e5 | ||
|
|
ac84129ef8 | ||
|
|
3e50a6500c | ||
|
|
c90f3250bf | ||
|
|
e29c577104 | ||
|
|
d08643b0c0 | ||
|
|
94535d7e38 | ||
|
|
3ed6f17f28 | ||
|
|
e593403f2e | ||
|
|
bf94b75960 | ||
|
|
b263bd476a | ||
|
|
1fbbde21be | ||
|
|
e4ed721fd0 | ||
|
|
62d7bda1e2 | ||
|
|
dcd1d96b28 | ||
|
|
229cdc8c4e | ||
|
|
79cbc8784d | ||
|
|
36295161f5 | ||
|
|
1e2987500d | ||
|
|
8bc0b134d2 | ||
|
|
1c64d27da9 | ||
|
|
ceb7e2fbe6 | ||
|
|
657e1bfd54 | ||
|
|
b3c07a05a3 | ||
|
|
44574cd14f | ||
|
|
b48dc0b907 | ||
|
|
8a15ca9a66 | ||
|
|
95d1b3f49a | ||
|
|
67cd8a2a33 | ||
|
|
3d2f8b8fd1 | ||
|
|
2fc8a2a921 | ||
|
|
e77b16d0fe | ||
|
|
c83bd6e1dd | ||
|
|
3c93f1fcaa | ||
|
|
4f425b9604 | ||
|
|
e2bc0ad7b3 | ||
|
|
d399bcc6cd | ||
|
|
5167c65ae3 | ||
|
|
e13d41cabe | ||
|
|
da526f9d8e | ||
|
|
facaec61d9 | ||
|
|
993e6898f3 | ||
|
|
f48cffdb2c | ||
|
|
74ce2ea6f8 | ||
|
|
2d358bfb9e | ||
|
|
a826e5ad2f | ||
|
|
1a75ff2746 | ||
|
|
5b3b3fca48 | ||
|
|
4011f621eb | ||
|
|
35d7cd00cf | ||
|
|
9074e23b18 | ||
|
|
03fbda9043 | ||
|
|
eee5edf45d | ||
|
|
1e7df0abca | ||
|
|
e690a54b06 | ||
|
|
bcf510df3d | ||
|
|
a85a1feba0 | ||
|
|
b8a4da7efc | ||
|
|
02c156e41e | ||
|
|
ea77f76415 | ||
|
|
c93c6b0276 | ||
|
|
36dbc07baf | ||
|
|
ff5d70590b | ||
|
|
388075378f | ||
|
|
82612e5cd4 | ||
|
|
b03527a7ad | ||
|
|
01633ee08e | ||
|
|
b9b454be9c | ||
|
|
2d021c80d3 | ||
|
|
0a1819eec2 | ||
|
|
90f6794e7d | ||
|
|
92d2e9e031 | ||
|
|
c5d88c244d | ||
|
|
0fcc30e22b | ||
|
|
e31414b610 | ||
|
|
744d693d90 | ||
|
|
d62d1f46e4 | ||
|
|
615c370e51 | ||
|
|
bc8bb0b03a | ||
|
|
700967baca | ||
|
|
70ad4a7035 | ||
|
|
4f29fd3790 | ||
|
|
5785ee2bc2 | ||
|
|
0584da0611 | ||
|
|
164fdeeb92 | ||
|
|
5d97f9db15 | ||
|
|
968a4fe04b | ||
|
|
e2c5b44408 | ||
|
|
5bcb75019a | ||
|
|
1733a525e0 | ||
|
|
fba5585f77 | ||
|
|
e1227bf0f8 | ||
|
|
5349d34513 | ||
|
|
465599701c | ||
|
|
e91c13cbf8 | ||
|
|
604d89c2c6 | ||
|
|
19f42ecfd1 | ||
|
|
0d55c20c26 | ||
|
|
26d4b91251 | ||
|
|
6836254234 | ||
|
|
5162291f9d | ||
|
|
44e3e0f3d6 | ||
|
|
5ae9f76629 | ||
|
|
a9ec2c1b6d | ||
|
|
4ccbbced54 | ||
|
|
da62ca474b | ||
|
|
e02696d47d | ||
|
|
6dc29b910c | ||
|
|
7e76d29ddf | ||
|
|
0bad62dfd4 | ||
|
|
98807b0487 | ||
|
|
78deee7ca2 | ||
|
|
a5ccfebff5 | ||
|
|
b39b945a6e | ||
|
|
18951047eb | ||
|
|
1124ec22c6 | ||
|
|
ab367fc890 | ||
|
|
22c632794f | ||
|
|
0fefd6d443 | ||
|
|
89f24ea07c | ||
|
|
d2a11bc0f2 | ||
|
|
575455b10e | ||
|
|
e858c68fa6 | ||
|
|
2df26740c6 | ||
|
|
39209ee2b8 | ||
|
|
3e9cd11aa3 | ||
|
|
f91b2c4a2f | ||
|
|
a2b1a07a4f | ||
|
|
82b5f434f9 | ||
|
|
a55b7398da | ||
|
|
d9b37b2094 | ||
|
|
230c5f37bc | ||
|
|
561bdbf2b4 | ||
|
|
0bafec7ce5 | ||
|
|
34dca72a09 | ||
|
|
428b576acf | ||
|
|
f26a08d9bc | ||
|
|
92ae9affd6 | ||
|
|
d52cd2e0c0 | ||
|
|
e11cbd1a26 | ||
|
|
4e58a6a6b4 | ||
|
|
e01de676fa | ||
|
|
9e43802e2a | ||
|
|
f02f4f6116 | ||
|
|
306689f30d | ||
|
|
43bf28968b | ||
|
|
df6e9a57d8 | ||
|
|
cbcafd28c9 | ||
|
|
4f181ec460 | ||
|
|
a72583df76 | ||
|
|
8f508e5e0f | ||
|
|
536f75fdb4 | ||
|
|
f37a070eda | ||
|
|
51c1267bf4 | ||
|
|
6a0b972aac | ||
|
|
94168f02ca | ||
|
|
88c8dfa26e | ||
|
|
c8050f0edd | ||
|
|
e3d90e63e8 | ||
|
|
ec20a3e4c9 | ||
|
|
83bac6b8aa | ||
|
|
34025743a1 | ||
|
|
ff02a303c7 | ||
|
|
4552576fa3 | ||
|
|
cc2c834359 | ||
|
|
b746aeb729 | ||
|
|
686fc08cef | ||
|
|
9d74aae3f5 | ||
|
|
b3fd99eb1b | ||
|
|
bf111c97f1 | ||
|
|
ac8d4cf899 | ||
|
|
04bd7fbffa | ||
|
|
8167e8d944 | ||
|
|
6c3174599a | ||
|
|
76aca637e8 | ||
|
|
832d843ea1 | ||
|
|
9aa702efcd | ||
|
|
cde6d9eaae | ||
|
|
91db033e3a | ||
|
|
7d6c0af7e7 | ||
|
|
d0c2345044 | ||
|
|
51c4b93bc7 | ||
|
|
242acbcd9d | ||
|
|
3079801e0f | ||
|
|
fdc02400b9 | ||
|
|
499b0da006 | ||
|
|
a7caf02ec6 | ||
|
|
70b819700d | ||
|
|
b1aca90888 | ||
|
|
73ccc5d3ad | ||
|
|
47d3fd7db9 | ||
|
|
56d2d7cb12 | ||
|
|
ac3c078141 | ||
|
|
0110a0df8d | ||
|
|
c1d6b51075 | ||
|
|
bc6c6a36da | ||
|
|
806d76d9a2 | ||
|
|
a0a476b57d | ||
|
|
d5dd24fa51 | ||
|
|
42561be37e | ||
|
|
c2fdee9cf8 | ||
|
|
9972ee4113 | ||
|
|
846b0ce9fd | ||
|
|
fe78fe4416 | ||
|
|
54d03ae788 | ||
|
|
55f895a7f5 | ||
|
|
22b557605b | ||
|
|
16ed6e844a | ||
|
|
d96b3de97a | ||
|
|
bd0436ffa0 | ||
|
|
496f5c256f | ||
|
|
6617d07e1e | ||
|
|
99837f0b8f | ||
|
|
6ed27b7b83 | ||
|
|
3247fd77d6 | ||
|
|
f9b9679b5e | ||
|
|
685d264ab7 | ||
|
|
2355f0cb54 | ||
|
|
68674fb1c2 | ||
|
|
0e1a942ecd | ||
|
|
d01ce11e47 | ||
|
|
eee9e1cbd4 | ||
|
|
54e2da3dc4 | ||
|
|
6887850eae | ||
|
|
ab16885112 | ||
|
|
5f3ff06403 | ||
|
|
81f872fdaf | ||
|
|
0ec739a2b7 | ||
|
|
752bc51452 | ||
|
|
3a23c62070 | ||
|
|
4512b4c998 | ||
|
|
684d2abcdc | ||
|
|
db3eb8872c | ||
|
|
885f388201 | ||
|
|
9431f7f2a8 | ||
|
|
f7752fd2b7 | ||
|
|
e4b2c2262e | ||
|
|
9a31b6259d | ||
|
|
995abe9401 | ||
|
|
a13b39907b | ||
|
|
c64fec22ee | ||
|
|
dd1d835dfe | ||
|
|
5a78becc6f | ||
|
|
f598e62d1c | ||
|
|
b8ae4d0fc5 | ||
|
|
5403c16f48 | ||
|
|
3d162032f4 | ||
|
|
c591a7a91e | ||
|
|
fd2c476ae5 | ||
|
|
42bf58a0b5 | ||
|
|
4d09e1b5a5 | ||
|
|
d825b065f2 | ||
|
|
13428b5ed6 | ||
|
|
521d1789bc | ||
|
|
f64257ae86 | ||
|
|
d228ca1c4b | ||
|
|
690f21e9ae | ||
|
|
743710a9f0 | ||
|
|
ba29971e20 | ||
|
|
f49e492a92 | ||
|
|
1c62abaec0 | ||
|
|
1940a03a61 | ||
|
|
9bee2f443f | ||
|
|
1cf331f83c | ||
|
|
685b835886 | ||
|
|
ab2494a6ba | ||
|
|
3ae0d61bd5 | ||
|
|
f4e11b623f | ||
|
|
938479e43f | ||
|
|
31ec650659 | ||
|
|
87c13ff74a | ||
|
|
2c820daae4 | ||
|
|
3b0cdc0caa | ||
|
|
85570dd61d | ||
|
|
400d3670be | ||
|
|
45c93a7f3e | ||
|
|
6ca3f492fe | ||
|
|
dee3768d34 | ||
|
|
d2570f9c44 | ||
|
|
a630fa9f98 | ||
|
|
875d4248f5 | ||
|
|
9523ff2472 | ||
|
|
cf92bda8db | ||
|
|
c73b5ed7dc | ||
|
|
ceb32f63ad | ||
|
|
4065193dd8 | ||
|
|
b4d7ae2d3e | ||
|
|
140dce8dd2 | ||
|
|
e80fd77299 | ||
|
|
7e552a4db0 | ||
|
|
7d28eec8d0 | ||
|
|
c29f8bf2f4 | ||
|
|
f76433729c | ||
|
|
db630fc549 | ||
|
|
4eb13e84cc | ||
|
|
16b8c8efea | ||
|
|
9b2c72e4a2 | ||
|
|
b3b9c52144 | ||
|
|
4bc319e0bb | ||
|
|
50071a2980 | ||
|
|
2036ce4ba1 | ||
|
|
f2624fea03 | ||
|
|
950bc3daaa | ||
|
|
39b6779a8c | ||
|
|
743486d88b | ||
|
|
50b0e90495 | ||
|
|
a8b049686a | ||
|
|
23f133dbbe | ||
|
|
b033375491 | ||
|
|
ca4060473d | ||
|
|
472b6a8c46 | ||
|
|
0947bac63c | ||
|
|
1a414a2723 | ||
|
|
d7bbf37cbb | ||
|
|
6063ff90eb | ||
|
|
20dd2eb564 | ||
|
|
4a80853be6 | ||
|
|
b6cd30e22d | ||
|
|
ea59ca59d3 | ||
|
|
c67d8a942b | ||
|
|
244d94b17d | ||
|
|
b05b348198 | ||
|
|
38a8595d15 | ||
|
|
f2226c92b3 | ||
|
|
466709df23 | ||
|
|
702459918b | ||
|
|
4efbd8b90a | ||
|
|
655bfcba0a | ||
|
|
041356ebac | ||
|
|
32e9ceb741 | ||
|
|
1aeb0e42dc | ||
|
|
9c419b1f2e | ||
|
|
0786489924 | ||
|
|
2835aa1685 | ||
|
|
9cc34df185 | ||
|
|
d5adcdf988 | ||
|
|
837c0e1a17 | ||
|
|
d458f43b63 | ||
|
|
1cfb1b6287 | ||
|
|
6f5124616a | ||
|
|
3ba2f8ae93 | ||
|
|
b6d87141f2 | ||
|
|
993e9355bb | ||
|
|
be655902b4 | ||
|
|
f9332befb3 | ||
|
|
66728df978 | ||
|
|
60dc85c2fc | ||
|
|
4b4eb623b9 | ||
|
|
d2c98bf559 | ||
|
|
9a31503996 | ||
|
|
cb4622f61f | ||
|
|
1ce1091eca | ||
|
|
4546eef1e3 | ||
|
|
1d8f24ced2 | ||
|
|
19a61ba517 | ||
|
|
2b377e35f1 | ||
|
|
f5011630a3 | ||
|
|
8967a84f12 | ||
|
|
38bed5e4eb | ||
|
|
5370ecedd8 | ||
|
|
0e8cd5cefc | ||
|
|
e3c3649b0f | ||
|
|
19f953fa54 | ||
|
|
ad1b5e35c7 | ||
|
|
ff2eb0fef6 | ||
|
|
d356c14f87 | ||
|
|
829cbf890b | ||
|
|
5ae52d4b4f | ||
|
|
4608c6b7ee | ||
|
|
7c7a818ca0 | ||
|
|
08c6d44185 | ||
|
|
dc8495b147 | ||
|
|
e2f5765a87 | ||
|
|
7ebc059430 | ||
|
|
0d3fda185f | ||
|
|
38df06261b | ||
|
|
0086df54f0 | ||
|
|
ddc0c910c8 | ||
|
|
31f74baef7 | ||
|
|
8cd4f50304 | ||
|
|
48f6abb361 | ||
|
|
27626665a1 | ||
|
|
47039d8685 | ||
|
|
bc9aded3b7 | ||
|
|
f919544d1e | ||
|
|
ea49d0508a | ||
|
|
894f508f6c | ||
|
|
2f2d3d584e | ||
|
|
67ae8a614d | ||
|
|
cbba0e639d | ||
|
|
8f3fdf3d1d | ||
|
|
650fdd60cc | ||
|
|
8b114b5122 | ||
|
|
bc96addce5 | ||
|
|
bac2c9d5ec | ||
|
|
94e0c37cf8 | ||
|
|
42d6181724 | ||
|
|
4c5f2e99cb | ||
|
|
95e2fef4a6 | ||
|
|
4d8e3e61a1 | ||
|
|
c227798a4b | ||
|
|
fc5a6b9ac6 | ||
|
|
b820f17b3c | ||
|
|
079ec51dac | ||
|
|
88dee956f2 | ||
|
|
53945eb095 | ||
|
|
578447ecc3 | ||
|
|
0cecad49b3 | ||
|
|
652df93690 | ||
|
|
efa81c11c5 | ||
|
|
4af070b5b8 | ||
|
|
95faf9332e | ||
|
|
7e87befd3d | ||
|
|
d6155f4c35 | ||
|
|
33c89eac63 | ||
|
|
335adc6bdb | ||
|
|
a107084745 | ||
|
|
67f60b19ea | ||
|
|
734b17d0e7 | ||
|
|
7739c92064 | ||
|
|
0ae5f12024 | ||
|
|
e05dd9d1e9 | ||
|
|
ecbbeaeeca | ||
|
|
ea164e82a7 | ||
|
|
bfa1e68ce0 | ||
|
|
dc010092ab | ||
|
|
82c6bd6452 | ||
|
|
49a1251091 | ||
|
|
97ffad1178 | ||
|
|
592883af29 | ||
|
|
51a38c5607 | ||
|
|
5a645015a2 | ||
|
|
064094489f | ||
|
|
218310c23c | ||
|
|
7c48a9e28d | ||
|
|
8ecffcbddb | ||
|
|
c31f8d8275 | ||
|
|
6db3fe11b9 | ||
|
|
ae7735f6bd | ||
|
|
22dc364f7e | ||
|
|
f11f22f6bb | ||
|
|
2e07f1a9cb | ||
|
|
62bc7e5ff7 | ||
|
|
6b9dd95b26 | ||
|
|
0f3fd3ace1 | ||
|
|
10b9e91c8e | ||
|
|
f813bc42ed | ||
|
|
1c713c0e7e | ||
|
|
6b36671ad7 | ||
|
|
720ee7981b | ||
|
|
dbed9b88a4 | ||
|
|
d5afee08af | ||
|
|
5ae70fcf29 | ||
|
|
16621d9ce1 | ||
|
|
32bfb590a8 | ||
|
|
0e2f9b427f | ||
|
|
1f8abd1be7 | ||
|
|
f7e24ba46c | ||
|
|
d3b993d67e | ||
|
|
eddd6269e7 | ||
|
|
ad14cf6a94 | ||
|
|
53f92d91e7 | ||
|
|
58e8c708c4 | ||
|
|
3b7f1f9cce | ||
|
|
d921975e9f | ||
|
|
9db35b6597 | ||
|
|
c6c5bd179b | ||
|
|
dd1d3ebdc4 | ||
|
|
d5110c4ac8 | ||
|
|
e08775f18a | ||
|
|
a1e273a147 | ||
|
|
79a7d163c4 | ||
|
|
4fd1a633e7 | ||
|
|
ce126b0f1d | ||
|
|
1ccde63c31 | ||
|
|
713972aed0 | ||
|
|
a1abb11ec4 | ||
|
|
2f86b628f9 | ||
|
|
23994758dd | ||
|
|
1c5b6a722a | ||
|
|
a62d826005 | ||
|
|
c98d72f0cd | ||
|
|
55d59c1944 | ||
|
|
064b0b5ee1 | ||
|
|
ebf03afa75 | ||
|
|
116b2efd5f | ||
|
|
dfa66b8113 | ||
|
|
620b0ff59a | ||
|
|
bc01acfef0 | ||
|
|
f8199eaa79 | ||
|
|
bb7408979a | ||
|
|
93a42e752b | ||
|
|
8959bcb912 | ||
|
|
d533e3bf8e | ||
|
|
fbdd73ec58 | ||
|
|
3c5e570e04 | ||
|
|
263c02eaab | ||
|
|
44ad01b3ad | ||
|
|
a37736eed6 | ||
|
|
a3c09047e6 | ||
|
|
dc30c28c02 | ||
|
|
d17f2e6eb9 | ||
|
|
fdabd03924 | ||
|
|
a8a04186ed | ||
|
|
164dd1d7a5 | ||
|
|
4fc487348a | ||
|
|
0bb566869e | ||
|
|
9fb495d785 | ||
|
|
df86e7c8ec | ||
|
|
1e6f4d8052 | ||
|
|
bd470b1330 | ||
|
|
60b3494207 | ||
|
|
475a7fc44c | ||
|
|
f19c5a0dc0 | ||
|
|
3e35f1dea3 | ||
|
|
d8197dd00e | ||
|
|
3205248519 | ||
|
|
224801dcd9 | ||
|
|
e8c0de07de | ||
|
|
cf7e061c7a | ||
|
|
a75becd6c5 | ||
|
|
e411bbe3c4 | ||
|
|
c8ca4bc945 | ||
|
|
ffd9d13d79 | ||
|
|
4addeb5835 | ||
|
|
c086c9ab83 | ||
|
|
44e30e4520 | ||
|
|
8f93cd7dd6 | ||
|
|
a4390d348b | ||
|
|
bd72766414 | ||
|
|
866828c1ba | ||
|
|
8cedcc5d55 | ||
|
|
860cee5f12 | ||
|
|
a75972cf3b | ||
|
|
03e3592443 | ||
|
|
c113244319 | ||
|
|
3a64e1310b | ||
|
|
306b759b74 | ||
|
|
5976884b0f | ||
|
|
ee907c3321 | ||
|
|
86307a724f | ||
|
|
997aa44654 | ||
|
|
feb1d277e9 | ||
|
|
7e1dac26f1 | ||
|
|
a7b95d4caf | ||
|
|
bb042fe70b | ||
|
|
e50ee8fbee | ||
|
|
55d8a6ff76 | ||
|
|
576fc07b5b | ||
|
|
b4978269a5 | ||
|
|
24e9a74a6c | ||
|
|
61e79155b4 | ||
|
|
d23d9a2e7a | ||
|
|
ae13e30494 | ||
|
|
292c664941 | ||
|
|
c78845571e | ||
|
|
a0d5c67e48 | ||
|
|
059a3dcc37 | ||
|
|
d543bb4539 | ||
|
|
3e8f800682 | ||
|
|
368f2abe0d | ||
|
|
1e8af399e7 | ||
|
|
72f669e189 | ||
|
|
c787b54e7c | ||
|
|
3512be30cf | ||
|
|
0bb279eec8 | ||
|
|
75331d9025 | ||
|
|
99a46eafc8 | ||
|
|
ac9300f5be | ||
|
|
4e4e5154f4 | ||
|
|
b54c096762 | ||
|
|
5d409ec1de |
@@ -96,3 +96,5 @@ Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
.vscode/settings.json
|
||||
.vs/
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
os:
|
||||
- linux
|
||||
# - osx
|
||||
# - windows
|
||||
|
||||
dist: xenial
|
||||
sudo: require
|
||||
language: cpp
|
||||
|
||||
script:
|
||||
- bash bin/clean
|
||||
- bash bin/configure
|
||||
# - bash bin/build
|
||||
# - bash bin/run-unit-tests
|
||||
|
||||
# end of file
|
||||
@@ -1,30 +1,262 @@
|
||||
0.9.0-RC6 / February 13, 2016
|
||||
|
||||
Download latest version:
|
||||
https://robomongo.org/download
|
||||
|
||||
Robo 3T 1.4.0 (Aug, 2020)
|
||||
blog.robomongo.org/robo-3t-1-4/
|
||||
|
||||
New Features:
|
||||
- Mongo shell 4.2 upgrade
|
||||
- Support for Ubuntu 20.04 and macOS 10.15 (Catalina)
|
||||
- SSH: ECDSA and Ed25519 keys support on Windows & macOS (#1719, #1530, #1590)
|
||||
- Manually specify visible databases (#1696, #1368, #389)
|
||||
|
||||
Improvements:
|
||||
- Qt Upgrade (v5.12.8 - Apr/2020, Windows & macOS only)
|
||||
- OpenSSL upgrade (v1.1.1f - Mar/2020, Windows & macOS only)
|
||||
- libssh2 upgrade (v1.9.0 - Jun/2019, Windows & macOS only)
|
||||
|
||||
Fixes:
|
||||
- Authentication database option isn't used properly (#1696)
|
||||
- Add/Edit index ops fixed (re-written) (#1692)
|
||||
- Crash when expanding admin users (#1728)
|
||||
- Unable to run query after shell timeout reached (#1529)
|
||||
|
||||
Robo 3T 1.3.1 (Apr, 2019)
|
||||
http://blog.robomongo.org/robo-3t-1-3
|
||||
|
||||
New Features:
|
||||
- Biggest change in this version is Mongo Shell version upgrade from 3.4 to 4.0.5.
|
||||
- Support for importing from DNS SRV based MongoDB connection strings
|
||||
- Query results windows now supports tabbed output #1591 #1403
|
||||
- Adding support for SCRAM-SHA-256 auth mechanism #1569
|
||||
- Support for Ubuntu 18.04 and Mac 10.14.
|
||||
- Support for creating version 4 UUID #1554
|
||||
|
||||
Improvements:
|
||||
- Encrypted passwords are used in config. file instead of clear text passwords
|
||||
- Showing much better error reason string from Mongo drivers for connection failures
|
||||
|
||||
Fixes:
|
||||
- Broken create/edit/view user features fixed and updated #638 #1041
|
||||
- Attempt to fix #1547: Crash when right click on existing results plus a new long running query
|
||||
- Fix for application crash when adding index with invalid JSON
|
||||
- 'Repair Database' in Robo3T needs a confirm dialog box #1568
|
||||
- Robo 3T the input space causes connection failure #1551
|
||||
- Crash when loading results + right click #1547
|
||||
- Attempt to fix major connection problems seen with the second edit/add/remove document operation after MongoDB 4.0 upgrade #1603
|
||||
- Attempt to fix #1581: For CRUD ops showing progress bar and disabling context menu while waiting for edit op to finish
|
||||
- Fixing UI issue where Functions folder freezing with "Functions..." when fails to refresh
|
||||
- Fix for #1529: Pagination does not work when the aggregation queries have dotted fields
|
||||
|
||||
Robo 3T 1.3.0 Beta (16 Feb, 2019)
|
||||
Details: https://github.com/Studio3T/robomongo/releases/tag/v1.3.0-beta
|
||||
|
||||
Robo 3T 1.2.1 (19 Feb, 2018)
|
||||
http://blog.robomongo.org/robo-3t-1-2
|
||||
|
||||
Fixes:
|
||||
- Aggregate query results are not pagaeble
|
||||
- Big double numbers are showing incorrectly #1447
|
||||
- Editing a document from a projection causes data loss (override) (#881)
|
||||
- Error: Resources temporarily unavailable. Error when starting up SSH session: -8 #1426
|
||||
- robo3t 1.1 failed to start on Ubuntu 17.04 #1385
|
||||
- Robo 3T is not opening on MacOS High Sierra (#1412)
|
||||
- Cannot load list of indexes #1454
|
||||
- Robo 3T is not buildable on latest MacOS High Sierra
|
||||
|
||||
Improvements
|
||||
- Qt version upgraded from Qt 5.7.0 to Qt 5.9.3
|
||||
- Auto switch to HTTP from HTTPS if the program crashes due to HTTPS related operations
|
||||
- Improvements for Robo 3T is crashing constantly on High Sierra #1412
|
||||
- PR: Improved query time formatting (#1358) #1455
|
||||
|
||||
Robo 3T 1.2.0 Beta (18 Dec, 2017)
|
||||
https://github.com/Studio3T/robomongo/releases/tag/v1.2.0-beta
|
||||
|
||||
Improvements & Fixes:
|
||||
- Qt version upgraded from Qt 5.7.0 to Qt 5.9.3
|
||||
- Fix for "Cannot load list of indexes #1454"
|
||||
- Improvements for Robo 3T is crashing constantly on High Sierra #1412
|
||||
- PR: Improved query time formatting (#1358) #1455
|
||||
- Fix for "Robo 3T is not buildable on latest MacOS vesion High Sierra"
|
||||
- Fix attempt for "Error: Resources temporarily unavailable. Error when starting up SSH session: -8 #1426"
|
||||
- Fix for "robo3t 1.1 failed to start on Ubuntu 17.04 #1385"
|
||||
|
||||
Robo 3T 1.1 (13 June, 2017)
|
||||
http://blog.robomongo.org/robomongo-1-1/
|
||||
|
||||
New Features:
|
||||
- MongoDB 3.4 support
|
||||
- New NumberDecimal (Decimal128) data type support
|
||||
- ECMAScript 2015 aka ES6 Support (Modernized JavaScript Implementation)
|
||||
- Re-naming from Robomongo to Robo 3T
|
||||
|
||||
Improvements & Fixes:
|
||||
- Stability Improvements: Fix included to prevent a crash on MACOS Sierra
|
||||
- Shell timeout is configurable on UI now 'Options->Change Shell Timeout'
|
||||
- Fix for Robomongo Shell Timeout Issue (silently, prematurely finishing long lasting scripts)
|
||||
- Security Improvements: OpenSSL version upgrade to openssl-1.0.1u (22-Sep-2016)
|
||||
- Tool chain upgrades: Modern C++14 features are enabled and usable for developers
|
||||
|
||||
Robomongo 1.1 Beta (12 May, 2017)
|
||||
https://github.com/Studio3T/robomongo/releases/tag/v1.1.0-beta
|
||||
|
||||
New Features:
|
||||
- MongoDB 3.4 Support
|
||||
- New NumberDecimal (Decimal128) data type support
|
||||
- ECMAScript 2015 (Modernized JavaScript Implementation aka ES6) Support
|
||||
|
||||
Improvements:
|
||||
- Security Improvements: OpenSSL version upgrade to openssl-1.0.1u (22-Sep-2016)
|
||||
- Tool Chain Improvements: Modern C++14 features are enabled
|
||||
|
||||
Robomongo 1.0 (21 Apr, 2017)
|
||||
http://blog.robomongo.org/robomongo-1-0
|
||||
|
||||
New Features:
|
||||
- Update Notifications Bar
|
||||
- Welcome Tab
|
||||
- Welcome Wizard
|
||||
|
||||
Improvements:
|
||||
- Replica set name configurable on UI
|
||||
- Configuration file system location change
|
||||
- "About Robomongo" dialog changes
|
||||
|
||||
Fixes:
|
||||
- Fix to avoid the same set name problem (https://github.com/Studio3T/robomongo/issues/1302)
|
||||
- Timestamp value is represented incorrectly (https://github.com/Studio3T/robomongo/issues/1159)
|
||||
- Local Timezone shows wrong date (https://github.com/Studio3T/robomongo/issues/501)
|
||||
- Time zone shown as "000:00" when UTC +00:00 is used as local timezone(https://github.com/Studio3T/robomongo/issues/1309)
|
||||
|
||||
Robomongo 1.0-RC1 (1 Feb, 2017)
|
||||
http://blog.robomongo.org/robomongo-1-rc1/
|
||||
|
||||
New Features:
|
||||
- Replica set support.
|
||||
- New 'Attributes' column in connections list window showing connection properties such as 'Replica Set', 'SSL' and 'SSH'.
|
||||
- New operation logging for almost all operations.
|
||||
|
||||
Improvements:
|
||||
- Improved error handling (no double error windows) for all fail and success conditions for the following operations:
|
||||
. Create, Drop Database
|
||||
. Create, Edit User
|
||||
. Create, Drop, Duplicate, Rename Collection
|
||||
. Insert Document
|
||||
. Remove document, Delete document, Remove all documents (triggered both from explorer and from result widget)
|
||||
. Refresh Users
|
||||
. Refresh Functions
|
||||
. Refresh Collections
|
||||
. Connection establish & refresh server fail and success cases.
|
||||
- Windows size is saved and restored for Edit, View and Insert Document dialogs.
|
||||
- Connections are automatically imported from the latest Robomongo version.
|
||||
- Better error reporting/handling and logging have been added for the operations below:
|
||||
. Create, Drop Function
|
||||
. Drop User
|
||||
- More informative and adjusted log level prefix strings haven added for log window. (Error, Warn, Info etc..).
|
||||
- After a new connection is created, now the focus goes to the newly created connection (end of list) instead of the
|
||||
beginning of connections list. And when Robomongo is opened, the focus goes to the end of the connection list instead
|
||||
of beginning.
|
||||
- Error messages added and error handling for 'remove document', 'remove all documents' operations triggered explorer
|
||||
and single or multi 'delete document' from results window have been re-implemented and improved.
|
||||
- Relevant errors are shown for the following cases now:
|
||||
. Drop attempt of non-existing collection.
|
||||
. Duplicating a collection with a collection name which already exists finishes silently.
|
||||
|
||||
Fixes:
|
||||
- Fix for the problem where the connections list comes empty if the Robomongo config file or it's directory do not exist.
|
||||
- Fix for the problem where 'in-progress bar' widget was not centered on main window for "Update Documents/Remove Documents"
|
||||
operations. https://github.com/paralect/robomongo/issues/1256
|
||||
- Fix for two problems where the operations 'insert or update documents' in one tab was causing auto reloading of other
|
||||
unrelated tabs and also multiple error windows to popup. https://github.com/paralect/robomongo/issues/1236
|
||||
- Fix for the problem where the operations 'remove document', 'remove all documents' triggered explorer and single or
|
||||
multi 'delete document' from results window were causing auto reloading of other unrelated tabs.
|
||||
|
||||
|
||||
Robomongo 0.9:
|
||||
Major Features:
|
||||
- Support for MongoDB 3.x and WiredTiger engine. Robomongo now embeds MongoDB 3.2 shell.
|
||||
(Ability to use the latest shell functionality)
|
||||
- SSH tunnel support for connections
|
||||
- SSL support
|
||||
- MongoDB Atlas (Cloud MongoDB) support
|
||||
- Both MONGODB-CR and SCRAM-SHA-1 authentication mechanisms are supported.
|
||||
- Allow direct connections to Replica Set members and support IPv6 protocol.
|
||||
- Loading of huge list of collections is now faster.
|
||||
- Create Collection dialog is now expandable to support all advanced options.
|
||||
(Supporting all major mongoDB versions 3.2, 3.0, 2.6 and all storage engine types (WiredTiger
|
||||
and MMAPV1) is added.)
|
||||
- Windows High DPI support.
|
||||
- Full size editor with dockable output window.
|
||||
|
||||
Fixed:
|
||||
- Incorrect representation of floating-point numbers (fixed since RC3). This bug was a reason of a big number of issues:
|
||||
#910, #748, #697, #699, #760, #815, #870, #892,
|
||||
#894, #905, #945, #974, #978, #990, #831, #842
|
||||
- SSH connection failure to servers on Ubuntu and OS X with the following error:
|
||||
"Resource temporarily unavailable. Error when starting up SSH session: -8" (#1090)
|
||||
|
||||
What's new in 0.9.0 Final (30 Sep, 2016)
|
||||
http://blog.robomongo.org/robomongo-0-9-0-final/
|
||||
|
||||
New Features:
|
||||
- Full size editor with dockable output window.
|
||||
- New JSON object context menu items: "Copy Name" and "Copy Path" are added.
|
||||
- New database context menu items: "Current Operations" and "Kill Operation" are added.
|
||||
- Minimize to Tray Icon for Windows.
|
||||
|
||||
Other Changes
|
||||
- Cloud platforms Compose, mLab and Amazon EC2 were tested and added as supported platforms.
|
||||
- Maximize/Restore result button behavior and icon have been improved.
|
||||
- For better code quality and code reviews, Robomongo Code Quality and Robomongo Code Review pages have been created.
|
||||
https://github.com/paralect/robomongo/wiki/Robomongo-Code-Review
|
||||
https://github.com/paralect/robomongo/wiki/Robomongo-Code-Quality
|
||||
|
||||
Most important changes: support for MongoDB 3.x and WiredTiger engine. Robomongo
|
||||
now embeds MongoDB 3.2 shell. It means that you can now use the latest
|
||||
shell functionality. Both MONGODB-CR and SCRAM-SHA-1 authentication mechanisms are
|
||||
supprted. Also, we now allow direct connections to Replica Set members and
|
||||
support IPv6 protocol. Loading of huge list of collections is now faster.
|
||||
What's new in RC10 (Aug 8, 2016)
|
||||
http://blog.robomongo.org/robomongo-rc10/
|
||||
|
||||
New Features:
|
||||
- SSL connections with advanced options are now supported.
|
||||
- MongoDB Atlas (Cloud MongoDB) is supported.
|
||||
- Cross Platform High DPI enhancements.
|
||||
|
||||
Enhancements:
|
||||
- For better security, OpenSSL has been upgraded to OpenSSL 1.0.1p.
|
||||
- Qt has been updated from Qt 5.5 to latest Qt 5.7. With this update there are many
|
||||
enhancements including cross platform High DPI support.
|
||||
|
||||
Fixed incorrect representation of floating-point numbers (fixed since RC3).
|
||||
This bug was a reason of a big number of issues:
|
||||
|
||||
#910, #748, #697, #699, #760, #815, #870, #892,
|
||||
#894, #905, #945, #974, #978, #990, #831, #842
|
||||
|
||||
What's new in RC7 (March 4, 2016 )
|
||||
What's new in RC9 (May 30, 2016)
|
||||
http://blog.robomongo.org/robomongo-rc9/
|
||||
|
||||
New Features:
|
||||
- Create Collection dialog with advanced options.
|
||||
- New feature has been added to save/restore window sizes. (#1102)
|
||||
- Connection settings from previous versions of Robomongo are
|
||||
now automatically imported starting from Robomongo 0.9.0 RC9. (#1086)
|
||||
- Support for querying documents by UUIDs is added, both in legacy and new encoding. (#432)
|
||||
|
||||
Fixed:
|
||||
- SSH connection failure to servers on Ubuntu and OS X with the following error:
|
||||
"Resource temporarily unavailable. Error when starting up SSH session: -8" (#1090)
|
||||
- Correct handling of create/drop of databases and collections. (#1083)
|
||||
|
||||
What's new in RC8 (April 14, 2016)
|
||||
http://blog.robomongo.org/robomongo-rc8/
|
||||
|
||||
What's new in RC7 (March 4, 2016)
|
||||
http://blog.robomongo.org/robomongo-rc7
|
||||
|
||||
What's new in RC6 (February 13, 2016 )
|
||||
What's new in RC6 (February 13, 2016)
|
||||
http://blog.robomongo.org/ipv6-protocol
|
||||
|
||||
What's new in RC5 (February 8, 2016 )
|
||||
What's new in RC5 (February 8, 2016)
|
||||
http://blog.robomongo.org/campaign-is-over-robomongo-is-not/
|
||||
|
||||
What's new in RC4 (February 1, 2016 )
|
||||
What's new in RC4 (February 1, 2016)
|
||||
http://blog.robomongo.org/robomongo-rc4
|
||||
|
||||
What's new in RC3 (January 29, 2016 )
|
||||
What's new in RC3 (January 29, 2016)
|
||||
http://blog.robomongo.org/robomongo-0-9-0-rc3-released
|
||||
|
||||
What's new in RC2 (January 26, 2016)
|
||||
@@ -86,7 +318,7 @@
|
||||
* [Andres Kievsky]
|
||||
- Added new app icon in a variety of png and iDraw formats (#693)
|
||||
* [Michael Steinacher]
|
||||
- Retina text display support (#724)
|
||||
- Retina text display support (#724)
|
||||
|
||||
0.8.4 / November 27, 2013
|
||||
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
cmake_minimum_required(VERSION 3.0.0)
|
||||
cmake_minimum_required(VERSION 3.8.0)
|
||||
project(Robomongo)
|
||||
|
||||
# Where to look first for CMake modules, before "${CMAKE_ROOT}/Modules" is checked
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
|
||||
# Project version
|
||||
set(PROJECT_VERSION_MAJOR "0")
|
||||
set(PROJECT_VERSION_MINOR "9")
|
||||
set(PROJECT_VERSION_PATCH "0")
|
||||
set(PROJECT_VERSION_BUILD "-RC7")
|
||||
set(PROJECT_VERSION_MAJOR "1")
|
||||
set(PROJECT_VERSION_MINOR "4")
|
||||
set(PROJECT_VERSION_PATCH "1")
|
||||
set(PROJECT_VERSION_BUILD "")
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${PROJECT_VERSION_BUILD}")
|
||||
|
||||
# Enable C++17 features
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Modules
|
||||
include(RobomongoPrintUtils)
|
||||
include(RobomongoCMakeDefaults)
|
||||
@@ -27,20 +31,39 @@ find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Gui REQUIRED)
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5PrintSupport REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5Xml REQUIRED)
|
||||
find_package(MongoDB REQUIRED)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
|
||||
if (SYSTEM_MACOSX)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.13)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
endif()
|
||||
|
||||
# Projects
|
||||
add_subdirectory(src/third-party/openssl)
|
||||
add_subdirectory(src/third-party/libssh2)
|
||||
set(LIBSSH2_VERSION 1.9.0)
|
||||
if(SYSTEM_LINUX)
|
||||
set(LIBSSH2_VERSION 1.7.0)
|
||||
endif()
|
||||
set(LIBSSH2_DIR src/third-party/libssh2-${LIBSSH2_VERSION})
|
||||
set(QJSON_VERSION 0.8.1)
|
||||
set(QJSON_DIR src/third-party/qjson-${QJSON_VERSION})
|
||||
set(QSCINTILLA_VERSION 2.8.4)
|
||||
set(QSCINTILLA_DIR src/third-party/qscintilla-${QSCINTILLA_VERSION})
|
||||
set(ESPRIMA_VERSION 2.7.3)
|
||||
set(ESPRIMA_DIR src/third-party/esprima-${ESPRIMA_VERSION})
|
||||
# todo: Use equivalent vars from googletest cmake files. Currently they are somehow not working.
|
||||
set(GOOGLE_TEST_VERSION 1.8.1)
|
||||
set(GOOGLE_TEST_DIR src/third-party/googletest-${GOOGLE_TEST_VERSION})
|
||||
add_subdirectory(${LIBSSH2_DIR})
|
||||
add_subdirectory(src/robomongo/ssh)
|
||||
add_subdirectory(src/third-party/qjson)
|
||||
add_subdirectory(src/third-party/qscintilla)
|
||||
add_subdirectory(${QJSON_DIR})
|
||||
add_subdirectory(${QSCINTILLA_DIR})
|
||||
add_subdirectory(${GOOGLE_TEST_DIR})
|
||||
add_subdirectory(src/robomongo)
|
||||
# todo: Enable unit tests
|
||||
# add_subdirectory(src/robomongo-unit-tests) # Disabled in Robo 1.4 due to too many link errors
|
||||
|
||||
# Show configuration summary
|
||||
include(RobomongoConfigurationSummary)
|
||||
|
||||
include(RobomongoConfigurationSummary)
|
||||
@@ -1,11 +1,11 @@
|
||||
Robomongo, shell-centric cross-platform MongoDB management tool.
|
||||
Robo 3T, shell-centric cross-platform MongoDB management tool.
|
||||
|
||||
Copyright 2013, Paralect.
|
||||
Copyright 2014-2017 3T Software Labs Ltd.
|
||||
|
||||
The Robomongo is released under the terms of the GNU General Public
|
||||
The Robo 3T is released under the terms of the GNU General Public
|
||||
License, version 3.
|
||||
|
||||
The Robomongo Project includes files written by third parties
|
||||
The Robo 3T Project includes files written by third parties
|
||||
and used with permission or subject to their respective license
|
||||
agreements.
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Robomongo is a shell-centric cross-platform open source MongoDB management
|
||||
Robo 3T is a shell-centric cross-platform open source MongoDB management
|
||||
tool (i.e. Admin GUI). Robomongo embeds the same JavaScript engine that
|
||||
powers MongoDB's mongo shell.
|
||||
|
||||
@@ -1,67 +1,102 @@
|
||||
About Robomongo
|
||||
About Robo 3T
|
||||
===============
|
||||
|
||||
[Robomongo](http://www.robomongo.org) is a shell-centric cross-platform MongoDB management tool. Unlike most other MongoDB admin UI tools, Robomongo embeds the actual `mongo` shell in a tabbed interface with access to a shell command line as well as GUI interaction.
|
||||
[Robo 3T](http://www.robomongo.org) (formerly Robomongo *) is a shell-centric cross-platform MongoDB management tool. Unlike most other MongoDB admin UI tools, Robo 3T embeds the actual `mongo` shell in a tabbed interface with access to a shell command line as well as GUI interaction.
|
||||
|
||||
Starting from version 0.9, Robomongo is compatibile with MongoDB 3.x (including SCRAM-SHA-1 auth and support for WiredTiger storage engine). Robomongo 0.9 embeds the **MongoDB 3.2** shell.
|
||||
The latest stable release **Robo 3T 1.4** embeds **MongoDB 4.2** shell.
|
||||
|
||||
Robomongo 0.8.x embeds the **MongoDB 2.4.0** shell.
|
||||
Blog: http://blog.robomongo.org/robo-3t-1-4/
|
||||
Download: https://robomongo.org/download
|
||||
Older Releases: https://github.com/Studio3T/robomongo/releases
|
||||
Watch: [Robo 3T Youtube channel](https://www.youtube.com/channel/UCM_7WAseRWeeiBikExppstA)
|
||||
Follow: https://twitter.com/Robomongo
|
||||
|
||||
**MongoDB shell history:**
|
||||
Robo 3T 1.3: MongoDB 4.0
|
||||
Robo 3T 1.1: MongoDB 3.4
|
||||
Robo 3T 0.9: MongoDB 3.2
|
||||
Robo 3T 0.8.x: MongoDB 2.4.0
|
||||
|
||||
\* [Robomongo has been acquired by 3T](https://studio3t.com/press/3t-software-labs-acquires-robomongo-the-most-widely-used-mongodb-tool/)
|
||||
|
||||
What's new in latest Robo 3T 1.4?
|
||||
====================================
|
||||
|
||||
New Features:
|
||||
- Mongo shell 4.2 upgrade
|
||||
- Support for Ubuntu 20.04 and macOS 10.15 (Catalina)
|
||||
- SSH: ECDSA and Ed25519 keys support on Windows & macOS (issues #1719, #1530, #1590)
|
||||
- Manually specify visible databases (issues #1696, #1368, #389)
|
||||
|
||||
Improvements:
|
||||
- Qt Upgrade (v5.12.8 - Apr/2020, Windows & macOS only)
|
||||
- OpenSSL upgrade (v1.1.1f - Mar/2020, Windows & macOS only)
|
||||
- libssh2 upgrade (v1.9.0 - Jun/2019, Windows & macOS only)
|
||||
|
||||
Fixes:
|
||||
- Authentication database option isn't used properly (#1696)
|
||||
- Add/Edit index ops fixed (re-written) (#1692)
|
||||
- Crash when expanding admin users (#1728)
|
||||
- IPv6 support (previously broken) restored
|
||||
- Unable to run query after shell timeout reached (#1529)
|
||||
|
||||
Supported Platforms
|
||||
===============
|
||||
|
||||
Note: This sections is for Robo 3T and it directly depends on what MongoDB suppports
|
||||
(See: https://docs.mongodb.com/manual/administration/production-notes/#prod-notes-supported-platforms)
|
||||
|
||||
| MongoDB Versions | MongoDB Cloud Platforms |
|
||||
| :-------------------- | :-------------------- |
|
||||
| 4.2 | Mongo Atlas |
|
||||
| 4.0 |
|
||||
| 3.6 |
|
||||
|
||||
| Windows | Mac | Linux |
|
||||
|:---------------------- | :--------------------------------| :---------------------------|
|
||||
| Windows 64-bit 10 | Mac OS X 10.15 (Catalina) | Linux Ubuntu 20.04 64-bit* |
|
||||
Windows 64-bit 8.1 | Mac OS X 10.14 (Mojave) | Linux Ubuntu 18.04 64-bit* |
|
||||
| Windows 64-bit 7 | Mac OS X 10.13 (High Sierra) | Linux CentOS 7 64-bit* ** |
|
||||
| | | Linux CentOS 6 64-bit* ** |
|
||||
|
||||
\* Latest stable build
|
||||
\** Support for CentOS temporarily dropped starting from version 1.1
|
||||
|
||||
Download
|
||||
========
|
||||
|
||||
You can download tested install packages for OS X, Windows, and Linux from our site: [www.robomongo.org](http://www.robomongo.org).
|
||||
|
||||
The latest stable release is currently **Robomongo 0.8.5**.
|
||||
You can download tested installer packages for macOS, Windows, and Linux from our site: [www.robomongo.org](http://www.robomongo.org).
|
||||
|
||||
Support
|
||||
=======
|
||||
|
||||
Robomongo is an open source project driven by volunteers. We'll try to get to your questions as soon as we can, but please be patient :).
|
||||
Robo 3T is an open source project driven by volunteers. We'll try to get to your questions as soon as we can, but please be patient :).
|
||||
|
||||
You can:
|
||||
|
||||
- [Create a new issue in the Github issue queue](https://github.com/paralect/robomongo/issues)
|
||||
|
||||
- [Join developer discussion on Gitter](https://gitter.im/paralect/robomongo) [](https://gitter.im/paralect/robomongo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Build
|
||||
=====
|
||||
|
||||
The wiki contains prerequisites and instructions to [Build Robomongo](https://github.com/paralect/robomongo/wiki/Build-Robomongo).
|
||||
|
||||
If you want to compile from source yourself, you should be able to do so cleanly from a [release branch](https://github.com/paralect/robomongo/releases).
|
||||
|
||||
What's Planned for the Next Release?
|
||||
====================================
|
||||
|
||||
We are currently working toward a [0.9.0 release milestone](https://github.com/paralect/robomongo/milestones/Robomongo%200.9.0)
|
||||
with some major features targeted including compatibility with MongoDB 3.0
|
||||
(updated shell, SCRAM-SHA-1 auth, support for WiredTiger storage engine)
|
||||
and full support for replica sets.
|
||||
- [Join developer discussion on Gitter](https://gitter.im/paralect/robomongo)
|
||||
|
||||
Contribute!
|
||||
===========
|
||||
|
||||
### Vote for Features
|
||||
|
||||
Please view our [Magic Backlog](http://app.robomongo.org/backlog) to see features prioritised by donation. The small amount of donations we currently receive are put toward hosting costs.
|
||||
|
||||
### Suggest Features
|
||||
|
||||
New feature suggestions or UI improvements are always welcome.
|
||||
[Create a new feature request on github](https://github.com/paralect/robomongo/issues/new)
|
||||
|
||||
This project is powered by open source volunteers, so we have a limited amount of development resource to address all requests. We will certainly make best efforts to progress (particularly for those with strong community upvotes).
|
||||
|
||||
### Code Contributions
|
||||
|
||||
Code contributions are always welcome! Just try to follow our coding style: [Robomongo Coding Style](https://github.com/paralect/robomongo/wiki/Robomongo-Coding-Style).
|
||||
Code contributions are always welcome! Just try to follow our pre-commit checks and coding style:
|
||||
- [Robo 3T Code Quality](https://github.com/paralect/robomongo/wiki/Robomongo-Code-Quality)
|
||||
- [Robo 3T C++11/14 Transition Guide](https://github.com/Studio3T/robomongo/wiki/Robomongo-Cplusplus-11,-14-Transition-Guide)
|
||||
- [Robo 3T Coding Style](https://github.com/paralect/robomongo/wiki/Robomongo-Coding-Style)
|
||||
|
||||
If you plan to contribute, please create a Github issue (or comment on the relevant existing issue) so we can help coordinate with upcoming release plans.
|
||||
|
||||
For a general workflow, see Github's guide to [Fork a Repo](https://help.github.com/articles/fork-a-repo/).
|
||||
|
||||
Pull requests (PRs) should generally be for discrete issues (i.e. one issue per PR please) and be clean to merge against the current master branch. It would also be helpful if you can confirm what testing has been done (specific O/S targets and MongoDB versions if applicable).
|
||||
|
||||
A usual naming approach for feature branches is `issue-###`. Include the issue number in your commit message / pull request description to link the PR to the original issue.
|
||||
@@ -81,7 +116,7 @@ There are a number of issues we could use help with reproducing. They are marked
|
||||
License
|
||||
=======
|
||||
|
||||
Copyright (C) 2013-2015 [Paralect, Inc](http://www.paralect.com)
|
||||
Copyright 2014-2020 [3T Software Labs Ltd](https://studio3t.com/). All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 3 as
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
source $BIN_DIR/common/setup $1
|
||||
source $BIN_DIR/common/setup $1 # $1: release or debug
|
||||
|
||||
cd $BUILD_DIR
|
||||
cmake --build . "${@:2}" -- -j8
|
||||
cmake --build . "${@:2}" -- -j8
|
||||
@@ -13,3 +13,8 @@ if %ERRORLEVEL% neq 0 (exit /b 1)
|
||||
rem Run build
|
||||
cd "%BUILD_DIR%"
|
||||
cmake --build . --config %BUILD_TYPE%
|
||||
|
||||
rem Install debug *.dll files
|
||||
if "%BUILD_TYPE%" == "Debug" (
|
||||
call "%BIN_DIR%\install_debug_dlls.bat" %*
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
rem Path to bin and project folder
|
||||
set BIN_DIR_WITH_BACKSLASH=%~dp0%
|
||||
set BIN_DIR=%BIN_DIR_WITH_BACKSLASH:~0,-1%
|
||||
set PROJECT_DIR=%BIN_DIR%\..
|
||||
|
||||
rem Run common setup code
|
||||
call "%BIN_DIR%\common\setup.bat" %*
|
||||
if %ERRORLEVEL% neq 0 (exit /b 1)
|
||||
|
||||
rem Run build with Visual Studio with RunCodeAnalysis
|
||||
cd "%BUILD_DIR%"
|
||||
cmake --build . --config %BUILD_TYPE% -- "/p:RunCodeAnalysis=true" "/p:CodeAnalysisRuleSet=NativeRecommendedRules.ruleset"
|
||||
|
||||
rem Install debug *.dll files
|
||||
if "%BUILD_TYPE%" == "Debug" (
|
||||
call "%BIN_DIR%\install_debug_dlls.bat" %*
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
|
||||
source $BIN_DIR/build || exit $?
|
||||
source $BIN_DIR/run_tests $1
|
||||
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
rem Path to bin and project folder
|
||||
set BIN_DIR_WITH_BACKSLASH=%~dp0%
|
||||
set BIN_DIR=%BIN_DIR_WITH_BACKSLASH:~0,-1%
|
||||
set PROJECT_DIR=%BIN_DIR%\..
|
||||
|
||||
rem Run build
|
||||
call "%BIN_DIR%\build.bat" %*
|
||||
if %ERRORLEVEL% neq 0 (exit /b 1)
|
||||
|
||||
rem Run tests
|
||||
call "%BIN_DIR%\run_tests.bat" %*
|
||||
if %ERRORLEVEL% neq 0 (exit /b 1)
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Building with scan-build in debug mode..."
|
||||
echo "------------------------------------------------"
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
source $BIN_DIR/common/setup debug # release or debug
|
||||
|
||||
cd $BUILD_DIR
|
||||
scan-build --use-analyzer /usr/local/opt/llvm/bin/clang++ cmake --build . "${@:2}" -- -j8
|
||||
@@ -44,6 +44,6 @@ if [ "$(uname -s)" == "Darwin" ]; then
|
||||
# variable. If both the command-line option is specified and the
|
||||
# environment variable is set, the command-line option will take precedence.
|
||||
#
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.9
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.13
|
||||
fi
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
source $BIN_DIR/common/setup $1
|
||||
source $BIN_DIR/common/setup $1 # $1: release or debug
|
||||
|
||||
cd $BUILD_DIR
|
||||
cmake -D "CMAKE_PREFIX_PATH=$PREFIX_PATH" -D "CMAKE_BUILD_TYPE=$BUILD_TYPE" -D "CMAKE_INSTALL_PREFIX=$INSTALL_PREFIX" "${@:2}" $PROJECT_DIR
|
||||
# $BUILD_TYPE: Release or Debug
|
||||
cmake -D "CMAKE_PREFIX_PATH=$PREFIX_PATH" -D "CMAKE_BUILD_TYPE=$BUILD_TYPE" -D "CMAKE_INSTALL_PREFIX=$INSTALL_PREFIX" "${@:2}" $PROJECT_DIR
|
||||
@@ -11,5 +11,6 @@ call "%BIN_DIR%\common\setup.bat" %*
|
||||
if %ERRORLEVEL% neq 0 (exit /b 1)
|
||||
|
||||
rem Run CMake configuration step
|
||||
rem BUILD_TYPE: Release or Debug
|
||||
cd "%BUILD_DIR%"
|
||||
cmake -G "Visual Studio 12 2013 Win64" -D "CMAKE_PREFIX_PATH=%PREFIX_PATH%" -D "CMAKE_BUILD_TYPE=%BUILD_TYPE%" -D "CMAKE_INSTALL_PREFIX=%INSTALL_PREFIX%" %PROJECT_DIR%
|
||||
cmake -G "Visual Studio 15 2017 Win64" -D "CMAKE_PREFIX_PATH=%PREFIX_PATH%" -D "CMAKE_BUILD_TYPE=%BUILD_TYPE%" -D "CMAKE_INSTALL_PREFIX=%INSTALL_PREFIX%" %PROJECT_DIR%
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "Configuring with scan-build in debug mode..."
|
||||
echo "------------------------------------------------"
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
source $BIN_DIR/common/setup debug # debug
|
||||
|
||||
cd $BUILD_DIR
|
||||
BUILD_TYPE=Debug # $BUILD_TYPE: Release or Debug
|
||||
scan-build -v --use-analyzer /usr/local/opt/llvm/bin/clang++ cmake -D "CMAKE_PREFIX_PATH=$PREFIX_PATH" -D "CMAKE_BUILD_TYPE=$BUILD_TYPE" -D "CMAKE_INSTALL_PREFIX=$INSTALL_PREFIX" "${@:2}" $PROJECT_DIR
|
||||
@@ -0,0 +1,46 @@
|
||||
@echo off
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
rem // This script installs debug *.dll files
|
||||
rem -------------------------------------------
|
||||
|
||||
set INSTALL_DIR=%BUILD_DIR%\src\robomongo\Debug\
|
||||
if not exist %INSTALL_DIR%*.dll (
|
||||
echo ----------------------------------------
|
||||
echo Installing debug *.dll files ...
|
||||
echo INSTALL_DIR: %INSTALL_DIR%
|
||||
echo ----------------------------------------
|
||||
)
|
||||
|
||||
rem // Find OpenSSL and Qt paths
|
||||
for %%i in (%ROBOMONGO_CMAKE_PREFIX_PATH%) do (
|
||||
set xx=%%i
|
||||
if not "!xx!"=="!xx:ssl=!" ( set OPENSSL_DIR=!xx! )
|
||||
if not "!xx!"=="!xx:qt=!" ( set Qt_DIR=!xx! )
|
||||
)
|
||||
set OPENSSL_DIR=%OPENSSL_DIR: =%
|
||||
set Qt_DIR=%Qt_DIR: =%
|
||||
|
||||
rem // Copy dll files
|
||||
for /d %%a in (
|
||||
"%VS140COMNTOOLS%\..\..\VC\redist\debug_nonredist\x64\Microsoft.VC140.DebugCRT\msvcp140d.dll"
|
||||
"%VS140COMNTOOLS%\..\..\VC\redist\debug_nonredist\x64\Microsoft.VC140.DebugCRT\vcruntime140d.dll"
|
||||
"%OPENSSL_DIR%\libssl-1_1-x64.dll"
|
||||
"%OPENSSL_DIR%\libcrypto-1_1-x64.dll"
|
||||
"%Qt_DIR%\bin\Qt5Cored.dll"
|
||||
"%Qt_DIR%\bin\Qt5Guid.dll"
|
||||
"%Qt_DIR%\bin\Qt5Networkd.dll"
|
||||
"%Qt_DIR%\bin\Qt5Widgetsd.dll"
|
||||
) do (
|
||||
if not exist !INSTALL_DIR!%%~NXa (
|
||||
xcopy %%a !INSTALL_DIR! /d /y
|
||||
)
|
||||
)
|
||||
|
||||
if not exist %INSTALL_DIR%\imageformats\qgifd.dll (
|
||||
xcopy /s "%Qt_DIR%\plugins\imageformats" %INSTALL_DIR%\imageformats\ /d /y
|
||||
)
|
||||
|
||||
if not exist %INSTALL_DIR%\platforms\qminimald.dll (
|
||||
xcopy /s "%Qt_DIR%\plugins\platforms" %INSTALL_DIR%\platforms\ /d /y
|
||||
)
|
||||
@@ -6,7 +6,9 @@ source $BIN_DIR/common/setup $1
|
||||
|
||||
if [ "$(uname -s)" == "Darwin" ]; then
|
||||
# On Mac OS we should run executable from bundle
|
||||
"$BUILD_DIR/src/robomongo/Robomongo.app/Contents/MacOS/Robomongo"
|
||||
"$BUILD_DIR/src/robomongo/Robo 3T.app/Contents/MacOS/Robo 3T"
|
||||
else
|
||||
"$BUILD_DIR/src/robomongo/robomongo"
|
||||
fi
|
||||
echo "Note: ./install must be executed before this script."
|
||||
echo "Starting $BUILD_DIR/install/bin/robo3t..."
|
||||
"$BUILD_DIR/install/bin/robo3t"
|
||||
fi
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
source $BIN_DIR/common/setup $1
|
||||
|
||||
echo
|
||||
echo "******************* Running unit tests in $BUILD_TYPE mode *******************"
|
||||
echo
|
||||
|
||||
if [ "$(uname -s)" == "Darwin" ]; then
|
||||
EXE="$BUILD_DIR/src/robomongo-unit-tests/robo_unit_tests"
|
||||
echo "Running file: $EXE"
|
||||
"$EXE"
|
||||
else # Linux
|
||||
echo "Error: Currently unit testing is disabled for Linux due to MongoDB linking problem"
|
||||
exit 0
|
||||
EXE="$BUILD_DIR/src/robomongo-unit-tests/robo_unit_tests"
|
||||
echo "Running file: $EXE"
|
||||
"$EXE"
|
||||
fi
|
||||
@@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
setlocal enableextensions enabledelayedexpansion
|
||||
|
||||
rem Path to bin and project folder
|
||||
set BIN_DIR_WITH_BACKSLASH=%~dp0%
|
||||
set BIN_DIR=%BIN_DIR_WITH_BACKSLASH:~0,-1%
|
||||
set PROJECT_DIR=%BIN_DIR%\..
|
||||
|
||||
rem Run tests
|
||||
echo.
|
||||
echo ******************* Running unit tests for Release mode *******************
|
||||
echo ** Note: Only Release mode is supported on Windows
|
||||
echo.
|
||||
echo "Running file: \build\Release\src\robomongo-unit-tests\Release\robo_unit_tests.exe"
|
||||
call "%PROJECT_DIR%\\build\Release\src\robomongo-unit-tests\Release\robo_unit_tests.exe" %*
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
|
||||
VERSION="$(echo $1 | tr '[A-Z]' '[a-z]')"
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Usage: tag <name>"
|
||||
echo "Example: tag 0.9.0-rc9"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$(git rev-parse --abbrev-ref HEAD)" != "master" ]; then
|
||||
echo "Error: You are not on master branch"
|
||||
exit
|
||||
fi
|
||||
|
||||
cd $PROJECT_DIR
|
||||
git tag -a "v${VERSION}" -m "${VERSION}"
|
||||
git push --tags
|
||||
@@ -41,38 +41,46 @@ set(MongoDB_DEFINITIONS
|
||||
BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
|
||||
BOOST_THREAD_HAS_BUG
|
||||
MONGO_CONFIG_HAVE_HEADER_UNISTD_H
|
||||
# Suppress "warning C4996: std::allocator..." from third_party\abseil-cpp-master
|
||||
_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
# Suppress "warning C4996: std::iterator..." from third_party\mozjs-60
|
||||
_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
|
||||
)
|
||||
|
||||
# Set common compiler include directories
|
||||
set(MOZJS_VER mozjs-60)
|
||||
set(MongoDB_INCLUDE_DIRS
|
||||
${MongoDB_DIR}/src
|
||||
${MongoDB_DIR}/src/third_party/boost-1.56.0
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/include
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/mongo_sources
|
||||
${MongoDB_DIR}/src/third_party/pcre-8.37
|
||||
${MongoDB_DIR}/src
|
||||
${MongoDB_DIR}/src/third_party/abseil-cpp-master/abseil-cpp
|
||||
${MongoDB_DIR}/src/third_party/boost-1.70.0
|
||||
${MongoDB_DIR}/src/third_party/fmt/dist/include
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/include
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/mongo_sources
|
||||
${MongoDB_DIR}/src/third_party/pcre-8.42
|
||||
${MongoDB_DIR}/src/third_party/SafeInt
|
||||
${MongoDB_BUILD_DIR}
|
||||
)
|
||||
|
||||
if(SYSTEM_LINUX)
|
||||
set(MongoDB_OBJECT_LIST_PLATFORM_PART linux)
|
||||
list(APPEND MongoDB_INCLUDE_DIRS
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/platform/x86_64/linux/include)
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/platform/x86_64/linux/include)
|
||||
elseif(SYSTEM_WINDOWS)
|
||||
set(MongoDB_OBJECT_LIST_PLATFORM_PART windows)
|
||||
list(APPEND MongoDB_INCLUDE_DIRS
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/platform/x86_64/windows/include)
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/platform/x86_64/windows/include)
|
||||
elseif(SYSTEM_MACOSX)
|
||||
set(MongoDB_OBJECT_LIST_PLATFORM_PART macosx)
|
||||
list(APPEND MongoDB_INCLUDE_DIRS
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/platform/x86_64/osx/include)
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/platform/x86_64/macOS/include)
|
||||
elseif(SYSTEM_FREEBSD)
|
||||
set(MongoDB_OBJECT_LIST_PLATFORM_PART freebsd)
|
||||
list(APPEND MongoDB_INCLUDE_DIRS
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/platform/x86_64/freebsd/include)
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/platform/x86_64/freebsd/include)
|
||||
elseif(SYSTEM_OPENBSD)
|
||||
set(MongoDB_OBJECT_LIST_PLATFORM_PART openbsd)
|
||||
list(APPEND MongoDB_INCLUDE_DIRS
|
||||
${MongoDB_DIR}/src/third_party/mozjs-38/platform/x86_64/openbsd/include)
|
||||
${MongoDB_DIR}/src/third_party/${MOZJS_VER}/platform/x86_64/openbsd/include)
|
||||
endif()
|
||||
|
||||
# Read list of object files
|
||||
@@ -86,11 +94,30 @@ string(STRIP "${MongoDB_RELATIVE_LIBS}" MongoDB_RELATIVE_LIBS)
|
||||
# Convert string to list
|
||||
string(REPLACE " " ";" MongoDB_RELATIVE_LIBS ${MongoDB_RELATIVE_LIBS})
|
||||
|
||||
# todo: Find a better solution
|
||||
# Robo 1.4: Added as workaround fix for build error:
|
||||
# fatal error LNK1170: line in command file contains 131071 or more characters
|
||||
# Happens when the path of robo-shell is a long string (e.g. "E:/user/code/robomongo-shell")
|
||||
set(MongoDB_OBJECTS_DIR_ENV $ENV{MongoDB_OBJECTS})
|
||||
if(MongoDB_OBJECTS_DIR_ENV)
|
||||
set(MongoDB_OBJECTS_DIR ${MongoDB_OBJECTS_DIR_ENV})
|
||||
else()
|
||||
set(MongoDB_OBJECTS_DIR ${MongoDB_DIR})
|
||||
endif()
|
||||
|
||||
# Convert to absolute path
|
||||
foreach(lib ${MongoDB_RELATIVE_LIBS})
|
||||
list(APPEND MongoDB_LIBS ${MongoDB_DIR}/${lib})
|
||||
list(APPEND MongoDB_LIBS ${MongoDB_OBJECTS_DIR}/${lib})
|
||||
endforeach()
|
||||
|
||||
if(SYSTEM_WINDOWS)
|
||||
list(APPEND MongoDB_LIBS Crypt32.lib Secur32.lib Dnsapi.lib winhttp.lib)
|
||||
elseif(SYSTEM_MACOSX)
|
||||
list(APPEND MongoDB_LIBS -lcurl)
|
||||
elseif(SYSTEM_LINUX)
|
||||
list(APPEND MongoDB_LIBS -lresolv -lcurl)
|
||||
endif()
|
||||
|
||||
# Get MongoDB repository recent tag
|
||||
execute_process(
|
||||
COMMAND git describe --abbrev=0 --tags
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
##################################################
|
||||
# Find and Add OpenSSL shared (dynamic) library
|
||||
#
|
||||
# - This module defines the following variables:
|
||||
# OpenSSL_DIR
|
||||
# OPENSSL_VERSION
|
||||
#
|
||||
# - Imported shared(dynamic) libraries "ssl" and "crypto" are created.
|
||||
#
|
||||
# - It is assumed that OpenSSL has been built and path to OpenSSL build directory is
|
||||
# added into system(environment) variable ROBOMONGO_CMAKE_PREFIX_PATH.
|
||||
#
|
||||
##################################################
|
||||
|
||||
# Try to find OpenSSL directory (uses CMAKE_PREFIX_PATH locations)
|
||||
#-------------------------------------------
|
||||
find_path(
|
||||
OpenSSL_DIR include/openssl/ssl.h
|
||||
DOC "Path to OpenSSL (github.com/openssl/openssl) root directory"
|
||||
)
|
||||
|
||||
# Find OpenSSL version
|
||||
#-------------------------------------------
|
||||
set (OPENSSL_INCLUDE_DIR "${OpenSSL_DIR}/include")
|
||||
|
||||
function(from_hex HEX DEC)
|
||||
string(TOUPPER "${HEX}" HEX)
|
||||
set(_res 0)
|
||||
string(LENGTH "${HEX}" _strlen)
|
||||
|
||||
while (_strlen GREATER 0)
|
||||
math(EXPR _res "${_res} * 16")
|
||||
string(SUBSTRING "${HEX}" 0 1 NIBBLE)
|
||||
string(SUBSTRING "${HEX}" 1 -1 HEX)
|
||||
if (NIBBLE STREQUAL "A")
|
||||
math(EXPR _res "${_res} + 10")
|
||||
elseif (NIBBLE STREQUAL "B")
|
||||
math(EXPR _res "${_res} + 11")
|
||||
elseif (NIBBLE STREQUAL "C")
|
||||
math(EXPR _res "${_res} + 12")
|
||||
elseif (NIBBLE STREQUAL "D")
|
||||
math(EXPR _res "${_res} + 13")
|
||||
elseif (NIBBLE STREQUAL "E")
|
||||
math(EXPR _res "${_res} + 14")
|
||||
elseif (NIBBLE STREQUAL "F")
|
||||
math(EXPR _res "${_res} + 15")
|
||||
else()
|
||||
math(EXPR _res "${_res} + ${NIBBLE}")
|
||||
endif()
|
||||
|
||||
string(LENGTH "${HEX}" _strlen)
|
||||
endwhile()
|
||||
|
||||
set(${DEC} ${_res} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if (OPENSSL_INCLUDE_DIR)
|
||||
if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
|
||||
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
|
||||
REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
|
||||
|
||||
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
|
||||
# The status gives if this is a developer or prerelease and is ignored here.
|
||||
# Major, minor, and fix directly translate into the version numbers shown in
|
||||
# the string. The patch field translates to the single character suffix that
|
||||
# indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
|
||||
# on.
|
||||
|
||||
string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
|
||||
"\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
|
||||
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
|
||||
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
|
||||
from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
|
||||
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
|
||||
from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
|
||||
list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
|
||||
|
||||
if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
|
||||
from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
|
||||
# 96 is the ASCII code of 'a' minus 1
|
||||
math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
|
||||
unset(_tmp)
|
||||
# Once anyone knows how OpenSSL would call the patch versions beyond 'z'
|
||||
# this should be updated to handle that, too. This has not happened yet
|
||||
# so it is simply ignored here for now.
|
||||
string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
|
||||
endif ()
|
||||
|
||||
set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
# Add imported ssl and crypto libraries
|
||||
#-------------------------------------------
|
||||
|
||||
# Add imported target ssl (ssleay32)
|
||||
add_library(ssl SHARED IMPORTED)
|
||||
|
||||
# Add imported target for crypto (libeay32)
|
||||
add_library(crypto SHARED IMPORTED)
|
||||
|
||||
# todo: refactor
|
||||
if(SYSTEM_WINDOWS)
|
||||
set_target_properties(ssl PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_IMPLIB "${OpenSSL_DIR}/libssl.lib"
|
||||
)
|
||||
set_target_properties(crypto PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_IMPLIB "${OpenSSL_DIR}/libcrypto.lib"
|
||||
)
|
||||
else()
|
||||
if(SYSTEM_MACOSX)
|
||||
SET(EXT "dylib")
|
||||
elseif(SYSTEM_LINUX)
|
||||
SET(EXT "so")
|
||||
endif()
|
||||
set_target_properties(ssl PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_LOCATION "${OpenSSL_DIR}/libssl.${EXT}"
|
||||
)
|
||||
set_target_properties(crypto PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_LOCATION "${OpenSSL_DIR}/libcrypto.${EXT}"
|
||||
)
|
||||
endif()
|
||||
|
||||
# End of file
|
||||
@@ -1,3 +1,3 @@
|
||||
|
||||
set(ROBOMONGO_DISPLAY_NAME "Robomongo")
|
||||
set(ROBOMONGO_DISPLAY_FULL_NAME "Robomongo ${PROJECT_VERSION}")
|
||||
set(ROBOMONGO_DISPLAY_NAME "Robo 3T")
|
||||
set(ROBOMONGO_DISPLAY_FULL_NAME "Robo 3T ${PROJECT_VERSION}")
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
# Show configuration summary and build tip
|
||||
message("")
|
||||
message(" _______________[ Robomongo configuration summary ]________________")
|
||||
message(" _______________[ Robo 3T configuration summary ]________________")
|
||||
message("| ")
|
||||
message("|-- Dependencies:")
|
||||
message("| ")
|
||||
message("| Qt5 Core: ${Qt5Core_VERSION} ${Qt5Core_DIR}")
|
||||
message("| Qt5 Gui: ${Qt5Gui_VERSION} ${Qt5Gui_DIR}")
|
||||
message("| Qt5 Widgets: ${Qt5Widgets_VERSION} ${Qt5Widgets_DIR}")
|
||||
message("| Qt5 PrintSupport: ${Qt5Widgets_VERSION} ${Qt5PrintSupport_DIR}")
|
||||
message("| MongoDB: ${MongoDB_VERSION} ${MongoDB_BUILD_DIR}")
|
||||
message("| Qt5 Core: ${Qt5Core_VERSION} ${Qt5Core_DIR}")
|
||||
message("| Qt5 Gui: ${Qt5Gui_VERSION} ${Qt5Gui_DIR}")
|
||||
message("| Qt5 Widgets: ${Qt5Widgets_VERSION} ${Qt5Widgets_DIR}")
|
||||
message("| Qt5 PrintSupport: ${Qt5Widgets_VERSION} ${Qt5PrintSupport_DIR}")
|
||||
message("| Qt5 Network: ${Qt5Network_VERSION} ${Qt5Network_DIR}")
|
||||
message("| Qt5 Xml: ${Qt5Xml_VERSION} ${Qt5Xml_DIR}")
|
||||
message("| MongoDB: ${MongoDB_VERSION} ${MongoDB_BUILD_DIR}")
|
||||
message("| MongoDB Objects: ${MongoDB_VERSION} ${MongoDB_OBJECTS_DIR}/build")
|
||||
message("| OpenSSL: ${OPENSSL_VERSION} ${OpenSSL_DIR}")
|
||||
message("| libssh2: ${LIBSSH2_VERSION} ${LIBSSH2_DIR}")
|
||||
message("| QJson: ${QJSON_VERSION} ${QJSON_DIR}")
|
||||
message("| QScintilla: ${QSCINTILLA_VERSION} ${QSCINTILLA_DIR}")
|
||||
message("| Google Test: ${GOOGLE_TEST_VERSION} ${GOOGLE_TEST_DIR}")
|
||||
message("| ESPRIMA: ${ESPRIMA_VERSION} ${ESPRIMA_DIR}")
|
||||
message("|")
|
||||
message("|-- Summary:")
|
||||
message("|")
|
||||
@@ -17,14 +26,18 @@ if (SYSTEM_MACOSX)
|
||||
message("| Target SDK: ${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
||||
endif()
|
||||
message("| Build type: ${CMAKE_BUILD_TYPE}")
|
||||
message("| Build number: ${BUILD_NUMBER}")
|
||||
message("| Install path: ${CMAKE_INSTALL_PREFIX}")
|
||||
message("|")
|
||||
message("|-- Building and installing:")
|
||||
message("|-- Build, Run and Install:")
|
||||
message("| ")
|
||||
message("| Now you can build Robomongo with the following command:")
|
||||
message("| $ cmake --build .")
|
||||
message("| $ bin/build")
|
||||
message("| $ bin/run")
|
||||
message("| $ bin/install")
|
||||
message("|")
|
||||
message("| And install it to ${CMAKE_INSTALL_PREFIX}:")
|
||||
message("| $ cmake --build . --target install")
|
||||
message("|-- Run Unit Tests:")
|
||||
message("| ")
|
||||
message("| $ bin/build_and_run_tests")
|
||||
message("| $ bin/run_tests (without building)")
|
||||
message("|__________________________________________________________________")
|
||||
message("")
|
||||
|
||||
@@ -52,6 +52,18 @@ elseif("${CMAKE_BUILD_TYPE}" MATCHES "MinSizeRel")
|
||||
set(BUILD_MINSIZEREL TRUE)
|
||||
endif()
|
||||
|
||||
# Compiler checks
|
||||
# We check Clang using MATCH instead of strict equality, because as of CMake 3.0.0 the
|
||||
# CMAKE_<LANG>_COMPILER_ID value for Apple-provided Clang is AppleClang. To test
|
||||
# for both the Apple-provided Clang and the regular Clang we use MATCH.
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(COMPILER_CLANG TRUE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "^GNU$")
|
||||
set(COMPILER_GCC TRUE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "^MSVC$")
|
||||
set(COMPILER_MSVC TRUE)
|
||||
endif()
|
||||
|
||||
# Link "groups" and "whole-archive" options
|
||||
if(SYSTEM_LINUX OR SYSTEM_FREEBSD OR SYSTEM_OPENBSD)
|
||||
set(LINK_LIBGROUP_START -Wl,--start-group)
|
||||
|
||||
@@ -24,10 +24,11 @@ if(SYSTEM_LINUX)
|
||||
set(qt_conf_dir ${bin_dir})
|
||||
set(qt_conf_plugins "../lib")
|
||||
elseif(SYSTEM_MACOSX)
|
||||
set(bundle_name Robomongo.app)
|
||||
set(bundle_name "Robo 3T.app")
|
||||
set(contents_path ${bundle_name}/Contents)
|
||||
|
||||
set(bin_dir ${contents_path}/MacOS)
|
||||
set(styles_dir ${contents_path}/MacOS/styles)
|
||||
set(lib_dir ${contents_path}/Frameworks)
|
||||
set(resources_dir ${contents_path}/Resources)
|
||||
set(license_dir ${resources_dir})
|
||||
@@ -37,6 +38,7 @@ elseif(SYSTEM_MACOSX)
|
||||
set(qt_conf_plugins "PlugIns/Qt")
|
||||
elseif(SYSTEM_WINDOWS)
|
||||
set(bin_dir .)
|
||||
set(styles_dir ${bin_dir}/styles)
|
||||
set(lib_dir .)
|
||||
set(resources_dir .)
|
||||
set(license_dir .)
|
||||
@@ -56,6 +58,29 @@ install(
|
||||
FILES "${CMAKE_BINARY_DIR}/qt.conf"
|
||||
DESTINATION "${qt_conf_dir}")
|
||||
|
||||
# Install OpenSSL dynamic lib files
|
||||
if(SYSTEM_WINDOWS)
|
||||
install(
|
||||
FILES
|
||||
"${OpenSSL_DIR}/libssl-1_1-x64.dll"
|
||||
"${OpenSSL_DIR}/libcrypto-1_1-x64.dll"
|
||||
DESTINATION ${bin_dir})
|
||||
elseif(SYSTEM_MACOSX)
|
||||
install(
|
||||
FILES
|
||||
"${OpenSSL_DIR}/libssl.1.1.dylib"
|
||||
"${OpenSSL_DIR}/libcrypto.1.1.dylib"
|
||||
DESTINATION ${lib_dir}/lib)
|
||||
elseif(SYSTEM_LINUX)
|
||||
install(
|
||||
FILES
|
||||
"${OpenSSL_DIR}/libssl.so"
|
||||
"${OpenSSL_DIR}/libssl.so.1.0.0"
|
||||
"${OpenSSL_DIR}/libcrypto.so"
|
||||
"${OpenSSL_DIR}/libcrypto.so.1.0.0"
|
||||
DESTINATION ${lib_dir})
|
||||
endif()
|
||||
|
||||
# Install binary
|
||||
install(
|
||||
TARGETS robomongo
|
||||
@@ -72,16 +97,21 @@ install(
|
||||
DESTINATION ${license_dir})
|
||||
|
||||
# Install common dependencies
|
||||
install_qt_lib(Core Gui Widgets PrintSupport)
|
||||
install_qt_lib(Core Gui Widgets PrintSupport Network Xml)
|
||||
install_qt_plugins(QGifPlugin QICOPlugin)
|
||||
install_icu_libs()
|
||||
set(QT_STYLES_DIR ${Qt5Core_DIR}/../../../plugins/styles/)
|
||||
|
||||
if(SYSTEM_LINUX)
|
||||
install_qt_lib(XcbQpa DBus)
|
||||
install_qt_plugins(
|
||||
QGtk2ThemePlugin
|
||||
QXcbIntegrationPlugin)
|
||||
|
||||
|
||||
install(
|
||||
FILES
|
||||
"/usr/lib/x86_64-linux-gnu/libstdc++.so.6"
|
||||
"/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28"
|
||||
DESTINATION ${lib_dir})
|
||||
elseif(SYSTEM_MACOSX)
|
||||
install_qt_lib(MacExtras DBus)
|
||||
install_qt_plugins(
|
||||
@@ -91,18 +121,23 @@ elseif(SYSTEM_MACOSX)
|
||||
|
||||
# Install icon
|
||||
install(
|
||||
FILES "${CMAKE_SOURCE_DIR}/install/macosx/Robomongo.icns"
|
||||
FILES "${CMAKE_SOURCE_DIR}/install/macosx/robomongo.icns"
|
||||
DESTINATION "${resources_dir}")
|
||||
|
||||
# Install styles
|
||||
install(FILES "${QT_STYLES_DIR}/libqmacstyle.dylib" DESTINATION ${styles_dir})
|
||||
elseif(SYSTEM_WINDOWS)
|
||||
install_qt_plugins(
|
||||
QWindowsIntegrationPlugin
|
||||
QMinimalIntegrationPlugin
|
||||
QOffscreenIntegrationPlugin)
|
||||
|
||||
# Install Styles
|
||||
install(FILES "${QT_STYLES_DIR}/qwindowsvistastyle.dll" DESTINATION ${styles_dir})
|
||||
|
||||
# Install runtime libraries:
|
||||
# msvcp120.dll
|
||||
# msvcr120.dll
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ execute_process(
|
||||
string(TIMESTAMP timestamp "%Y-%m-%d")
|
||||
|
||||
# Package name (as it should appear in UI)
|
||||
set(CPACK_PACKAGE_NAME Robomongo)
|
||||
set(CPACK_PACKAGE_NAME robo3t)
|
||||
|
||||
# Version of the package
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||
@@ -34,10 +34,10 @@ set(CPACK_MONOLITHIC_INSTALL ON)
|
||||
set(CPACK_STRIP_FILES ON)
|
||||
|
||||
# Additional information
|
||||
set(CPACK_PACKAGE_VENDOR Paralect)
|
||||
set(CPACK_PACKAGE_CONTACT robomongo@paralect.com)
|
||||
set(CPACK_PACKAGE_VENDOR "3T Software Labs Ltd")
|
||||
set(CPACK_PACKAGE_CONTACT robo3t@3t.io)
|
||||
set(CPACK_PACKAGE_DESCRIPTION "Shell-centric cross-platform MongoDB management tool.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Robomongo is a shell-centric cross-platform MongoDB management tool.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Robo 3T is a shell-centric cross-platform MongoDB management tool.")
|
||||
|
||||
# Use lowercase for system name and package file name
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name)
|
||||
@@ -62,7 +62,7 @@ elseif(SYSTEM_MACOSX)
|
||||
|
||||
elseif(SYSTEM_WINDOWS)
|
||||
set(files_dir "${CMAKE_SOURCE_DIR}/install/windows")
|
||||
set(exe_name "Robomongo.exe")
|
||||
set(exe_name "robo3t.exe")
|
||||
|
||||
set(CPACK_GENERATOR NSIS ZIP)
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/DESCRIPTION")
|
||||
|
||||
@@ -10,17 +10,18 @@ elseif(SYSTEM_WINDOWS)
|
||||
# The /MP option can reduce the total time to compile the source files. This option
|
||||
# causes the compiler to create one or more copies of itself, each in a separate process.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} psapi.lib bcrypt.lib Iphlpapi.lib dbghelp.lib ws2_32.lib winmm.lib version.lib")
|
||||
endif()
|
||||
|
||||
set(PROJECT_NAME "Robomongo")
|
||||
set(PROJECT_NAME "Robo 3T")
|
||||
set(PROJECT_NAME_TITLE ${PROJECT_NAME})
|
||||
set(PROJECT_DOMAIN "www.robomongo.org")
|
||||
set(PROJECT_COMPANYNAME "Paralect")
|
||||
set(PROJECT_COPYRIGHT "Copyright (C) 2013-2015 ${PROJECT_COMPANYNAME} All Rights Reserved.")
|
||||
set(PROJECT_COMPANYNAME_DOMAIN "www.paralect.com")
|
||||
set(PROJECT_GITHUB_FORK "www.github.com/paralect/robomongo")
|
||||
set(PROJECT_GITHUB_ISSUES "www.github.com/paralect/robomongo/issues")
|
||||
set(PROJECT_COMPANYNAME "3T Software Labs Ltd")
|
||||
set(PROJECT_COPYRIGHT "Copyright (C) 2014-2017 ${PROJECT_COMPANYNAME} All Rights Reserved.")
|
||||
set(PROJECT_COMPANYNAME_DOMAIN "https://studio3t.com/")
|
||||
set(PROJECT_GITHUB_FORK "www.github.com/Studio3T/robomongo")
|
||||
set(PROJECT_GITHUB_ISSUES "www.github.com/Studio3T/robomongo/issues")
|
||||
|
||||
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
Building Robo 3T (macOS and Linux)
|
||||
==================
|
||||
|
||||
A. Prerequisites
|
||||
-------------
|
||||
|
||||
1. Modern Compiler
|
||||
A modern and complete C++17 compiler:
|
||||
```
|
||||
GCC 8.0 or newer
|
||||
Clang 7 (or Apple XCode 10 Clang) or newer
|
||||
On Linux and macOS, the libcurl library and header is required. macOS includes libcurl.
|
||||
Fedora/RHEL - dnf install libcurl-devel
|
||||
Ubuntu/Debian - apt-get install libcurl-dev
|
||||
Python 3.7
|
||||
```
|
||||
|
||||
For details see: https://github.com/mongodb/mongo/wiki/Build-Mongodb-From-Source
|
||||
|
||||
2. Install CMake (3.10.0 or later)
|
||||
|
||||
Example:
|
||||
```
|
||||
sudo apt-get install build-essential
|
||||
// or
|
||||
wget http://www.cmake.org/files/v3.10/cmake-3.10.0.tar.gz
|
||||
tar xf cmake-3.10.0.tar.gz
|
||||
cd cmake-3.10.0
|
||||
./configure // macos: env CC=gcc ./bootstrap
|
||||
make
|
||||
sudo make install
|
||||
(sudo make uninstall)
|
||||
```
|
||||
|
||||
3. Install [Scons](http://scons.org/tag/releases.html) (3.1.2 or later)
|
||||
|
||||
```
|
||||
cd scons-**
|
||||
python setup.py install
|
||||
```
|
||||
|
||||
4. Install Qt
|
||||
|
||||
macOS: Qt 5.12.8
|
||||
Linux: Qt 5.9.3
|
||||
|
||||
```sh
|
||||
Example installation for macOS and Ubuntu:
|
||||
Go to http://download.qt.io/archive/qt/5.x/5.x.y/
|
||||
Download, run and install
|
||||
qt-opensource-mac-x64-clang-5.x.y.dmg (for macOS)
|
||||
qt-opensource-linux-x64-5.x.y.run (for Linux)
|
||||
After successful installation you should have
|
||||
/path/to/qt-5.x.y/5.x/clang_64 (for macOS)
|
||||
/path/to/qt-5.x.y/5.x/gcc_64 (for Linux)
|
||||
|
||||
More information for installing on Ubuntu:
|
||||
https://wiki.qt.io/Install_Qt_5_on_Ubuntu
|
||||
```
|
||||
|
||||
5. Download and Build OpenSSL - (explained below in section B)
|
||||
|
||||
B. Building Robo 3T and Dependencies
|
||||
-------------
|
||||
Ref: https://wiki.openssl.org/index.php/Compilation_and_Installation#OS_X
|
||||
|
||||
#### 1. Build OpenSSL
|
||||
|
||||
(Todo: Can we find pre-built OpenSSL? To check => https://wiki.openssl.org/index.php/Binaries)
|
||||
|
||||
Version 1.1.1f (Mar/2020) on macOS
|
||||
Version 1.0.2o (Mar/2018) on Linux
|
||||
|
||||
**macOS:**
|
||||
```sh
|
||||
wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1f.tar.gz
|
||||
tar -xf openssl-1.1.1f.tar.gz
|
||||
cd /opt/openssl-1.1.1f
|
||||
|
||||
(make clean)
|
||||
./Configure darwin64-x86_64-cc shared no-ssl2 no-ssl3 no-comp
|
||||
// Info: With openssl version 1.1.1, configure command with rpath stopped working
|
||||
// Last working configure command with rpath was:
|
||||
// ./Configure darwin64-x86_64-cc shared --openssldir="@rpath"
|
||||
|
||||
make (or sudo make)
|
||||
// Verify libssl.dylib and libcrypto.dylib file are created
|
||||
mkdir lib
|
||||
cp lib*.dylib lib/
|
||||
|
||||
// Due to broken './Configure' command with rpath above, these extra steps are also required:
|
||||
install_name_tool -id "@rpath/lib/libssl.1.1.dylib" libssl.dylib
|
||||
install_name_tool -change /usr/local/lib/libcrypto.1.1.dylib @rpath/lib/libcrypto.1.1.dylib libssl.dylib
|
||||
install_name_tool -id "@rpath/lib/libcrypto.1.1.dylib" libcrypto.dylib
|
||||
// Finally, we should have this output using otool:
|
||||
otool -L libssl.dylib
|
||||
libssl.dylib:
|
||||
@rpath/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
@rpath/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
|
||||
|
||||
otool -L libcrypto.dylib
|
||||
libcrypto.dylib:
|
||||
@rpath/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
|
||||
```
|
||||
|
||||
**Linux:**
|
||||
|
||||
```sh
|
||||
wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2o.tar.gz
|
||||
tar -xf openssl-1.0.2o.tar.gz
|
||||
cd /opt/openssl-1.0.2o
|
||||
(make clean)
|
||||
./config shared
|
||||
make
|
||||
// Verify libssl.so and libcrypto.so are created
|
||||
```
|
||||
|
||||
#### 2. Build Robo 3T Shell (fork of MongoDB)
|
||||
|
||||
Clone Robo 3T Shell and make sure you are on latest branch:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo-shell.git
|
||||
$ cd robomongo-shell
|
||||
$ git branch // "roboshell-v4.2"
|
||||
```
|
||||
|
||||
Set special environment variable `ROBOMONGO_CMAKE_PREFIX_PATH` to point to a set of
|
||||
directories:
|
||||
|
||||
1. Location of Qt 5 SDK
|
||||
2. Location of Robo 3T Shell
|
||||
3. Location of OpenSSL
|
||||
|
||||
Separate directories by semicolon `;` (not colon):
|
||||
|
||||
// macOS example:
|
||||
export ROBOMONGO_CMAKE_PREFIX_PATH="/path/to/qt-5.x.y/5.x/clang_64;/opt/robo-shell;/opt/openssl-x.y.z"
|
||||
|
||||
// Ubuntu example:
|
||||
export ROBOMONGO_CMAKE_PREFIX_PATH="/home/<user>/Qt5.x.y/5.x.y/gcc_64/;/opt/<user>/robo-shell;/opt/openssl-x.y.z"
|
||||
|
||||
Install pip requirements
|
||||
|
||||
```
|
||||
// macOS / Linux
|
||||
pip3 install --user -r etc/pip/compile-requirements.txt
|
||||
pip3 install --user -r etc/pip/dev-requirements.txt
|
||||
```
|
||||
|
||||
```
|
||||
// For ubuntu, the followings might be needed
|
||||
sudo aptitude install libcurl-dev
|
||||
|
||||
sudo pip3 install Typing
|
||||
sudo pip3 install Cheetah
|
||||
```
|
||||
|
||||
Build Robo 3T Shell (in release mode by default):
|
||||
|
||||
```sh
|
||||
$ bin/build
|
||||
```
|
||||
|
||||
Build Robo 3T Shell in debug mode:
|
||||
|
||||
```sh
|
||||
$ bin/build debug
|
||||
```
|
||||
|
||||
Clean build files for release mode:
|
||||
```sh
|
||||
$ bin/clean
|
||||
```
|
||||
|
||||
Clean build files for debug mode:
|
||||
```sh
|
||||
$ bin/clean debug
|
||||
```
|
||||
|
||||
For more information refer to [Building Robo 3T Shell](BuildRobo3TShell.md)
|
||||
|
||||
#### 3. Build Robo 3T
|
||||
|
||||
Download Robo 3T:
|
||||
|
||||
$ git clone https://github.com/Studio3T/robomongo
|
||||
$ cd robomongo
|
||||
|
||||
Run configuration step:
|
||||
|
||||
$ bin/configure
|
||||
|
||||
And finally, build Robo 3T:
|
||||
|
||||
$ bin/build
|
||||
|
||||
To run robomongo:
|
||||
|
||||
$ bin/run
|
||||
|
||||
|
||||
**Debug mode**
|
||||
|
||||
For debug mode append `debug` for each command
|
||||
e.g. `bin/configure debug` or `bin/build debug` etc..
|
||||
|
||||
**Helper commands**
|
||||
|
||||
Clean build files (in order to start build from scratch):
|
||||
|
||||
$ bin/clean
|
||||
|
||||
Install Robo 3T to `build/release/install` folder:
|
||||
|
||||
$ bin/install
|
||||
|
||||
Create package for your OS in `build/release/package` folder:
|
||||
|
||||
$ bin/pack
|
||||
|
||||
**Important Notes**
|
||||
- For macOS builds, it might be needed to patch QScintilla with `QScintilla-2.9.3-xcode8.patch` found at robomongo repository's root.
|
||||
|
||||
- For Ubuntu 16.04 builds, it has been reported that Robo 3T /bin/configure step might fail and installing `mesa-common-dev` package solves it. Details: https://github.com/paralect/robomongo/issues/1268
|
||||
|
||||
- For Centos builds, Robo 3T /bin/configure step might fail due to error: `failed to find gl/gl.h`. In this case, the following packages must be installed:
|
||||
|
||||
```sh
|
||||
$ sudo yum install mesa-libGL
|
||||
$ sudo yum install mesa-libGL-devel
|
||||
```
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
Building Robo 3T (Windows)
|
||||
==============================
|
||||
|
||||
A. Prerequisites
|
||||
-------------
|
||||
|
||||
#### 0. Git
|
||||
|
||||
Download Git installer from http://git-scm.com (we are using Git-2.7.0-64-bit).
|
||||
|
||||
When you'll see "Adjusting your PATH environment" wizard page, select
|
||||
"Use Git from the Windows Command Prompt" option. This will allow to
|
||||
execute Git from both Windows Command Prompt and Bash. This is required,
|
||||
because both MongoDB and Robo 3T uses `git` command during build process
|
||||
which must be perfomed from Windows Command Prompt (not Bash).
|
||||
|
||||
On "Configuring the line ending conversion" wizard page, select "Checkout
|
||||
Windows-style, commit Unix-style line ending" option. This is a common mode
|
||||
for cross-platform projects and required by both MongoDB and Robo 3T.
|
||||
|
||||
All other Git installer options are not important (use defaults).
|
||||
|
||||
If you are using SSH clone url, start SSH agent and add your private key
|
||||
with this commands in Git Bash:
|
||||
|
||||
$ eval `ssh-agent` # starts ssh agent
|
||||
$ ssh-add ~/.ssh/mykey # add your key (which can be in any folder)
|
||||
|
||||
#### 1. Visual Studio 2017 version 15.9 or newer (complete C++17 compiler)
|
||||
|
||||
We use Visual Studio 2017 version 15.9.22, and recommend to use this version to save
|
||||
time for Qt compilation. Currently prebuilt binaries for Qt are available
|
||||
from official Qt site. But you can use any newer version and compile Qt library
|
||||
yourself.
|
||||
|
||||
#### 2. ActivePython 3.7.4
|
||||
|
||||
Download ActivePython from http://www.activestate.com/activepython/downloads
|
||||
|
||||
Download MSI x64 version. Use default settings in installation wizard.
|
||||
This installer will add path to `python.exe` to your `PATH` variable.
|
||||
|
||||
#### 3. SCons 3.1.2 or newer
|
||||
|
||||
We use SCons 3.1.2
|
||||
|
||||
Download Scons from http://scons.org/tag/releases.html
|
||||
|
||||
Use ZIP archive, not MSI
|
||||
|
||||
Open Command Prompt, navigate to Scons directory and run:
|
||||
|
||||
$ setup.py install
|
||||
|
||||
This command will make `scons` command accessible from Command Prompt
|
||||
|
||||
#### 4. CMake
|
||||
We use CMake 3.10.0
|
||||
Download CMake from https://cmake.org/download
|
||||
|
||||
Use installer package, it will allow you to configure your PATH variable and `cmake`
|
||||
command will be available from Command Prompt. For this set "Add CMake to the system
|
||||
PATH for current user" in the installer wizard page.
|
||||
|
||||
#### 5. Qt 5.12.8
|
||||
|
||||
Download and install Qt from http://download.qt.io/archive/qt
|
||||
Run the installer and select only 'msvc2017 64-bit'
|
||||
|
||||
#### 6. OpenSSL (1.1.1f)
|
||||
Download openssl from https://www.openssl.org/source/old/1.1.1/openssl-1.1.1f.tar.gz
|
||||
|
||||
B. Building Robo 3T and Dependencies
|
||||
-------------
|
||||
|
||||
#### 1. Build OpenSSL
|
||||
|
||||
(Todo: Can we find pre-built OpenSSL? To check => https://wiki.openssl.org/index.php/Binaries)
|
||||
|
||||
Steps to build OpenSSL on windows:
|
||||
- Ensure you have perl installed on your machine (e.g. ActiveState or Strawberry), and available on your %PATH%
|
||||
- Ensure you have NASM installed on your machine, and available on your %PATH%
|
||||
|
||||
```sh
|
||||
Open Visual Studio tool x64 Cross Tools Command prompt
|
||||
cd to the directory where you have openssl sources cd c:\myPath\openssl
|
||||
perl Configure VC-WIN64A
|
||||
(nmake clean)
|
||||
nmake
|
||||
// Verify these files are created:
|
||||
libcrypto-1_1x64.dll, libssl-1_1-x64.dll (with all the build additionals such as .pdb .lik or static .lib)
|
||||
```
|
||||
|
||||
Refer to OpenSSL documentation for more information:
|
||||
https://wiki.openssl.org/index.php/Compilation_and_Installation#OpenSSL_1.1.0
|
||||
|
||||
#### 2. Build Robo 3T Shell (fork of MongoDB)
|
||||
|
||||
Clone Robo 3T Shell and make sure to be at `roboshell-v4.2` branch:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo-shell.git
|
||||
$ cd robomongo-shell
|
||||
$ git branch // roboshell-v4.2
|
||||
```
|
||||
|
||||
Set environment variable `ROBOMONGO_CMAKE_PREFIX_PATH`, required by Robo 3T-Shell and Robo 3T build scripts, needs to be set according to the following directories:
|
||||
|
||||
1. Location of Qt SDK
|
||||
2. Location of Robo 3T Shell
|
||||
3. Location of OpenSSL
|
||||
|
||||
**Important:**
|
||||
Make sure to move all your repos (robo, openssl, robo-shell etc..) into root directory of your drives (e.g. e:\robo-shell) and keep short repo names (e.g. robo-shell instead of robomongo-shell) otherwise you might end up with this error `If you see fatal error LNK1170: line in command file contains 131071 or more characters`
|
||||
|
||||
Separate directories by semicolon `;` (not colon). You can do this in Command Prompt:
|
||||
|
||||
> setx ROBOMONGO_CMAKE_PREFIX_PATH "e:\Qt\Qt5.9.3\5.9.3\msvc2015_64;e:\robo-shell;e:\openssl-x.y.z"
|
||||
|
||||
Open '**a new**' VS2017 x64 Native Tools Command Prompt and navigate to `robomongo-shell` folder.
|
||||
|
||||
|
||||
**Note:**
|
||||
|
||||
Run
|
||||
`pip3 install --user -r ../etc/pip/dev-requirements.txt`
|
||||
|
||||
If you have this type of errors:
|
||||
|
||||
```
|
||||
// 1st error
|
||||
ImportError: No module named typing
|
||||
// Solution:
|
||||
pip install Typing
|
||||
pip install Cheetah
|
||||
|
||||
// 2nd error: shell: cheetah module not found
|
||||
// Solution:
|
||||
copy C:\Users\<user>\AppData\Roaming\Python\Python27\site-packages
|
||||
to C:\Python27\Lib\site-packages
|
||||
|
||||
```
|
||||
|
||||
Build shell in release mode:
|
||||
|
||||
> bin\build
|
||||
|
||||
Build shell in debug mode:
|
||||
|
||||
> bin\build debug
|
||||
|
||||
Note that backslash is used (`\`), and not forward slash (`/`).
|
||||
|
||||
Clean build files for release mode:
|
||||
|
||||
> bin\clean
|
||||
|
||||
Clean build files for debug mode:
|
||||
|
||||
> bin\clean debug
|
||||
|
||||
Refer to MongoDB documentation for additional information:
|
||||
https://docs.mongodb.org/manual/contributors/tutorial/build-mongodb-from-source/#windows-specific-instructions
|
||||
|
||||
|
||||
#### 3. Build Robo 3T
|
||||
|
||||
Clone Robo 3T:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo.git
|
||||
```
|
||||
|
||||
Open VS2017 x64 Native Tools Command Prompt and navigate to `robomongo` folder.
|
||||
|
||||
Run configuration step:
|
||||
|
||||
> bin\configure
|
||||
|
||||
And finally, build Robo 3T:
|
||||
|
||||
> bin\build
|
||||
|
||||
```
|
||||
// If you see fatal error LNK1170: line in command file contains 131071 or more characters
|
||||
Solution-1:
|
||||
1. Move all your repos (robo, openssl, robo-shell etc..) into root directory of your drives.
|
||||
2. Use short names e.g. robo-shell instead of robomongo-shell.
|
||||
3. Update ROBOMONGO_CMAKE_PREFIX_PATH env. variable and try a fresh (clean) build.
|
||||
|
||||
Solution-2:
|
||||
1. Create environment variable MongoDB_OBJECTS, set a short path e.g. "C:/"
|
||||
2. Open a new VS2017 x64 Native Tools Command Prompt and build Robo 3T Shell
|
||||
3. Robo 3T Shell build script will copy the object files into MongoDB_OBJECTS directory
|
||||
4. Build Robo 3T again (clean build might be needed)
|
||||
```
|
||||
|
||||
**Run Robo 3T**
|
||||
|
||||
Install Robo 3T to `build\Release\install` folder:
|
||||
|
||||
> bin\install
|
||||
|
||||
And run Robo 3T
|
||||
|
||||
> \robomongo\build\Release\install\robo3t.exe
|
||||
|
||||
**Package Robo 3T**
|
||||
|
||||
Install Robo 3T to `build\Release\install` folder:
|
||||
|
||||
> bin\pack
|
||||
|
||||
Note: nsis-2.46-setup.exe with Full setup must be present.
|
||||
|
||||
|
||||
**Debug mode**
|
||||
|
||||
For debug mode append `debug` for each command
|
||||
e.g. `bin\configure debug` or `bin\build debug` etc..
|
||||
|
||||
**Helper commands**
|
||||
|
||||
Clean build files (in order to start build from scratch):
|
||||
|
||||
> bin\clean
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
Building Robo 3T Shell
|
||||
========================
|
||||
|
||||
Robo 3T uses [modified version](https://github.com/paralect/robomongo-shell/tree/roboshell-v3.4) of MongoDB that we call Robo 3T Shell.
|
||||
Before you can build Robo 3T, you have to build Robo 3T Shell. The following instructions are applicable only for Mac OS X and Linux. For Windows instructions please check [Building Robo 3T on Windows](BuildRobo3TOnWindows.md).
|
||||
|
||||
Build for Mac OS X or Linux
|
||||
---------------------------
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
1. Install [Scons](http://scons.org/tag/releases.html) (2.3.5 or newer)
|
||||
|
||||
|
||||
2. Clone Robo 3T Shell and checkout to `roboshell-v3.4` branch:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo-shell.git
|
||||
$ cd robomongo-shell
|
||||
$ git checkout roboshell-v3.4
|
||||
```
|
||||
|
||||
3. Build Robo 3T Shell:
|
||||
|
||||
```sh
|
||||
$ bin/build
|
||||
```
|
||||
|
||||
Done! Now you can continue with building Robo 3T
|
||||
with embedded MongoDB 3.4 shell (that you've just built).
|
||||
|
||||
|
||||
<br/>
|
||||
#### Advanced helper commands
|
||||
|
||||
The following commands are needed only if you are planning to develop or deeper understand
|
||||
Robo 3T or Robo 3T Shell build processes.
|
||||
|
||||
Clean build files for release mode (folder `build/opt` will be removed):
|
||||
|
||||
$ bin/clean
|
||||
|
||||
Here is a command that is executed by `bin/build` script:
|
||||
|
||||
$ scons mongo -j8 --release --osx-version-min=10.9
|
||||
|
||||
Argument `--osx-version-min` is required only for Mac OS.
|
||||
|
||||
Build MongoDB shell in debug mode:
|
||||
|
||||
$ scons mongo -j8 --dbg
|
||||
|
||||
Clear builds:
|
||||
|
||||
$ scons -c mongo # clears release build
|
||||
$ scons -c --dbg mongo # clears debug build
|
||||
@@ -1,12 +1,21 @@
|
||||
Building Robomongo Shell
|
||||
Building Robomongo Shell (Old Document)
|
||||
========================
|
||||
|
||||
**Important Note:**
|
||||
This document is for versions 1.0 and earlier and for MongoDB 3.2.
|
||||
See latest documents here: https://github.com/Studio3T/robomongo/wiki
|
||||
|
||||
Robomongo uses [modified version](https://github.com/paralect/robomongo-shell/tree/roboshell-v3.2) of MongoDB that we call Robomongo Shell. Before you can build Robomongo, you have to build Robomongo Shell. The following instructions are applicable only for Mac OS X and Linux. For Windows instructions please check [Building Robomongo on Windows](BuildingRobomongoOnWindows.md).
|
||||
|
||||
Build for Mac OS X or Linux
|
||||
---------------------------
|
||||
|
||||
1. Clone Robomongo Shell and checkout to `roboshell-v3.2` branch:
|
||||
#### Prerequisites
|
||||
|
||||
1. Install [Scons](http://scons.org/tag/releases.html) (2.4 or later)
|
||||
|
||||
|
||||
2. Clone Robomongo Shell and checkout to `roboshell-v3.2` branch:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo-shell.git
|
||||
@@ -14,7 +23,7 @@ Build for Mac OS X or Linux
|
||||
$ git checkout roboshell-v3.2
|
||||
```
|
||||
|
||||
2. Build Robomongo Shell:
|
||||
3. Build Robomongo Shell:
|
||||
|
||||
```sh
|
||||
$ bin/build
|
||||
|
||||
@@ -1,28 +1,108 @@
|
||||
Building Robomongo
|
||||
Building Robomongo (Mac OS X and Linux)
|
||||
==================
|
||||
|
||||
#### Step 1.
|
||||
**Important Note:**
|
||||
This document is for versions 1.0 and earlier and for MongoDB 3.2.
|
||||
See latest documents here: https://github.com/Studio3T/robomongo/wiki
|
||||
|
||||
Download and build Robomongo Shell (our fork of MongoDB).
|
||||
Refer to [Building Robomongo Shell](BuildingMongoDB.md) document.
|
||||
A. Prerequisites
|
||||
-------------
|
||||
|
||||
#### Step 2.
|
||||
1. Install CMake (3.2 or later)
|
||||
2. Install [Scons](http://scons.org/tag/releases.html) (2.4 or later)
|
||||
3. Install Qt 5.7
|
||||
|
||||
```sh
|
||||
Example installation for MAC OSX and Ubuntu:
|
||||
Go to http://download.qt.io/archive/qt/5.7/5.7.0/
|
||||
Download, run and install
|
||||
qt-opensource-mac-x64-clang-5.7.0.dmg (for MAC OSX)
|
||||
qt-opensource-linux-x64-5.7.0.run (for Linux)
|
||||
After successful installation you should have
|
||||
/path/to/qt-5.7.0/5.7/clang_64 (for MAC OSX)
|
||||
/path/to/qt-5.7.0/5.7/gcc_64 (for Linux)
|
||||
|
||||
More information for installing on Ubuntu:
|
||||
https://wiki.qt.io/Install_Qt_5_on_Ubuntu
|
||||
```
|
||||
|
||||
4. Download and Build OpenSSL (1.0.1p) - (explained below in section B)
|
||||
|
||||
B. Building Robomongo and Dependencies
|
||||
-------------
|
||||
|
||||
#### Step 1. Build OpenSSL (1.0.1p)
|
||||
|
||||
Steps to build OpenSSL on MAC:
|
||||
|
||||
```sh
|
||||
Download openssl-1.0.1p (ftp://ftp.openssl.org/source/old/1.0.1/openssl-1.0.1p.tar.gz)
|
||||
tar -xvzf openssl-1.0.1p.tar.gz
|
||||
cd /Users/<user>/Downloads/openssl-1.0.1p
|
||||
./Configure darwin64-x86_64-cc shared --openssldir="@rpath"
|
||||
make (or sudo make)
|
||||
mkdir lib
|
||||
cp libssl.1.0.0.dylib libcrypto.1.0.0.dylib lib/
|
||||
```
|
||||
Helper Commands
|
||||
```sh
|
||||
// to start fresh build
|
||||
make clean
|
||||
```
|
||||
|
||||
|
||||
Steps to build OpenSSL on Linux:
|
||||
|
||||
```sh
|
||||
Download openssl-1.0.1p (ftp://ftp.openssl.org/source/old/1.0.1/openssl-1.0.1p.tar.gz)
|
||||
tar -xvzf openssl-1.0.1p.tar.gz
|
||||
cd /home/<user>/Downloads/openssl-1.0.1p
|
||||
./config shared
|
||||
make
|
||||
mkdir lib
|
||||
cp libssl* libcrypto* lib/
|
||||
```
|
||||
|
||||
#### Step 2. Build Robomongo Shell (fork of MongoDB)
|
||||
|
||||
Clone Robomongo Shell and checkout to `roboshell-v3.2` branch:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo-shell.git
|
||||
$ cd robomongo-shell
|
||||
$ git checkout roboshell-v3.2
|
||||
```
|
||||
|
||||
Set special environment variable `ROBOMONGO_CMAKE_PREFIX_PATH` to point to a set of
|
||||
directories:
|
||||
|
||||
1. Location of Qt 5 SDK
|
||||
2. Location of Robomongo Shell
|
||||
3. Location of OpenSSL
|
||||
|
||||
Separate directories by semicolon `;` (not colon):
|
||||
|
||||
// MAC OSX example:
|
||||
$ export ROBOMONGO_CMAKE_PREFIX_PATH="/path/to/qt-5.7.0/5.7/clang_64;/path/to/robomongo-shell;/path/to/openssl-1.0.1p"
|
||||
// Ubuntu example:
|
||||
$ export ROBOMONGO_CMAKE_PREFIX_PATH="/path/to/qt-5.7.0/5.7/gcc_64;/path/to/robomongo-shell;/path/to/openssl-1.0.1p"
|
||||
|
||||
|
||||
Build Robomongo Shell:
|
||||
|
||||
```sh
|
||||
$ bin/build
|
||||
```
|
||||
|
||||
For more information refer to [Building Robomongo Shell](BuildingMongoDB.md)
|
||||
|
||||
#### Step 3. Build Robomongo
|
||||
|
||||
Download Robomongo:
|
||||
|
||||
$ git clone https://github.com/paralect/robomongo
|
||||
$ cd robomongo
|
||||
|
||||
Set special environment variable `ROBOMONGO_CMAKE_PREFIX_PATH` to point to a set of
|
||||
directories:
|
||||
|
||||
1. Location of Qt 5 SDK
|
||||
2. Location of Robomongo Shell (built in "Step 1")
|
||||
|
||||
Separate directories by semicolon `;` (not colon):
|
||||
|
||||
$ export ROBOMONGO_CMAKE_PREFIX_PATH="/path/to/qt-5.5/5.5/clang_64;/path/to/robomongo-shell"
|
||||
|
||||
Run configuration step:
|
||||
|
||||
$ bin/configure
|
||||
@@ -30,14 +110,14 @@ Run configuration step:
|
||||
And finally, build Robomongo:
|
||||
|
||||
$ bin/build
|
||||
|
||||
<br>
|
||||
## Helper commands
|
||||
|
||||
Execute just built Robomongo:
|
||||
To run robomongo:
|
||||
|
||||
$ bin/run
|
||||
|
||||
|
||||
**Helper commands**
|
||||
|
||||
Clean build files (in order to start build from scratch):
|
||||
|
||||
$ bin/clean
|
||||
@@ -49,4 +129,15 @@ Install Robomongo to `build/release/install` folder:
|
||||
Create package for your OS in `build/release/package` folder:
|
||||
|
||||
$ bin/pack
|
||||
|
||||
|
||||
**Important Notes**
|
||||
- For Ubuntu 16.04 builds, it has been reported that Robomongo /bin/configure step might fail and installing mesa-common-dev package solves it. Details: https://github.com/paralect/robomongo/issues/1268
|
||||
|
||||
- For Centos builds, Robomongo /bin/configure step might fail due to error: `failed to find gl/gl.h`. In this case, the following packages must be installed:
|
||||
|
||||
```sh
|
||||
$ sudo yum install mesa-libGL
|
||||
$ sudo yum install mesa-libGL-devel
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
Building Robomongo for Windows
|
||||
Building Robomongo (Windows)
|
||||
==============================
|
||||
|
||||
Prerequisites
|
||||
**Important Note:**
|
||||
This document is for versions 1.0 and earlier and for MongoDB 3.2.
|
||||
See latest documents here: https://github.com/Studio3T/robomongo/wiki
|
||||
|
||||
A. Prerequisites
|
||||
-------------
|
||||
|
||||
#### 0. Git
|
||||
@@ -64,25 +68,70 @@ Prerequisites
|
||||
command will be available from Command Prompt. For this set "Add CMake to the system
|
||||
PATH for current user" in the installer wizard page.
|
||||
|
||||
#### 5. Qt 5.5
|
||||
#### 5. Qt 5.7
|
||||
|
||||
Download Qt from http://www.qt.io/download-open-source/ (we use Qt Online installer)
|
||||
|
||||
When installing Qt, only one component is required by Robomongo:
|
||||
|
||||
Qt 5.5
|
||||
Qt 5.7
|
||||
[x] msvc2013 64-bit.
|
||||
|
||||
This components contains prebuilt 64-bit binaries for Visual Studio 2013.
|
||||
|
||||
You may uncheck all other components to download as little as possible.
|
||||
|
||||
#### 6. OpenSSL (1.0.1p)
|
||||
Download openssl-1.0.1p (ftp://ftp.openssl.org/source/old/1.0.1/openssl-1.0.1p.tar.gz)
|
||||
|
||||
|
||||
|
||||
B. Building Robomongo and Dependencies
|
||||
-------------
|
||||
|
||||
## Build Robomongo Shell (fork of MongoDB)
|
||||
#### 1. Build OpenSSL (1.0.1p)
|
||||
|
||||
Steps to build OpenSSL on windows:
|
||||
```sh
|
||||
Open Visual Studio tool x64 Cross Tools Command prompt
|
||||
cd to the directory where you have openssl sources cd c:\myPath\openssl
|
||||
perl Configure VC-WIN64A
|
||||
ms\do_win64a
|
||||
nmake -f ms\ntdll.mak
|
||||
```
|
||||
|
||||
**Check Point:**
|
||||
After successful build, newly created sub directory out32dll should contain dynamic lib files libeay32.lib (and libeay32.dll) and ssleay32.lib (and ssleay32.dll); and associated include files will be in newly created folder "inc32".
|
||||
|
||||
Helper Commands:
|
||||
```sh
|
||||
// clean to start fresh build
|
||||
nmake -f ms\ntdll.mak clean
|
||||
```
|
||||
|
||||
Refer to OpenSSL documentation for more information:
|
||||
https://wiki.openssl.org/index.php/Compilation_and_Installation#W64
|
||||
|
||||
#### 2. Build Robomongo Shell (fork of MongoDB)
|
||||
|
||||
Clone Robomongo Shell and checkout to roboshell-v3.2 branch:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo-shell.git
|
||||
$ cd robomongo-shell
|
||||
$ git checkout roboshell-v3.2
|
||||
```
|
||||
|
||||
Set environment variable `ROBOMONGO_CMAKE_PREFIX_PATH`, required by Robomongo-Shell and Robomongo build scripts, needs to be set according to the following directories:
|
||||
|
||||
1. Location of Qt SDK
|
||||
2. Location of Robomongo Shell
|
||||
3. Location of OpenSSL
|
||||
|
||||
Separate directories by semicolon `;` (not colon). You can do this in Command Prompt:
|
||||
|
||||
> setx ROBOMONGO_CMAKE_PREFIX_PATH "d:\Qt-5\5.7\msvc2013_64;d:\Projects\robomongo-shell;c:\myPath\openssl-1.0.1p"
|
||||
|
||||
Refer to MongoDB documentation for additional information:
|
||||
https://docs.mongodb.org/manual/contributors/tutorial/build-mongodb-from-source/#windows-specific-instructions
|
||||
|
||||
Open VS2013 x64 Native Tools Command Prompt and navigate to `robomongo-shell` folder.
|
||||
|
||||
@@ -96,20 +145,19 @@ Clean build files:
|
||||
|
||||
> bin\clean
|
||||
|
||||
Refer to MongoDB documentation for additional information:
|
||||
https://docs.mongodb.org/manual/contributors/tutorial/build-mongodb-from-source/#windows-specific-instructions
|
||||
|
||||
## Build Robomongo
|
||||
|
||||
Set special environment variable `ROBOMONGO_CMAKE_PREFIX_PATH` to point to set of
|
||||
directories:
|
||||
#### 3. Build Robomongo
|
||||
|
||||
1. Location of Qt SDK
|
||||
2. Location of Robomongo Shell
|
||||
Clone Robomongo:
|
||||
|
||||
Separate directories by semicolon `;` (not colon). You can do this in Command Prompt:
|
||||
|
||||
> setx ROBOMONGO_CMAKE_PREFIX_PATH "d:\Qt-5\5.5\msvc2013_64;d:\Projects\robomongo-shell"
|
||||
|
||||
Reopen your Command Prompt to make this variable available.
|
||||
```sh
|
||||
$ git clone https://github.com/paralect/robomongo.git
|
||||
```
|
||||
|
||||
Open VS2013 x64 Native Tools Command Prompt and navigate to `robomongo` folder.
|
||||
|
||||
Run configuration step:
|
||||
|
||||
@@ -118,15 +166,23 @@ Run configuration step:
|
||||
And finally, build Robomongo:
|
||||
|
||||
> bin\build
|
||||
|
||||
|
||||
#### Helper commands
|
||||
|
||||
|
||||
**Run Robomongo**
|
||||
|
||||
Install Robomongo to `build\Release\install` folder:
|
||||
|
||||
> bin\install
|
||||
|
||||
And run Robomongo
|
||||
|
||||
> \robomongo\build\Release\install\Robomongo.exe
|
||||
|
||||
**Helper commands**
|
||||
|
||||
Clean build files (in order to start build from scratch):
|
||||
|
||||
> bin\clean
|
||||
|
||||
Install Robomongo to `build\Release\install` folder:
|
||||
|
||||
> bin\install
|
||||
|
||||
|
||||
@@ -12,19 +12,100 @@ Runtime dependencies that are not privided by platforms but required by Robomong
|
||||
Diagnostic of dependencies
|
||||
--------------------------
|
||||
|
||||
##### Linux
|
||||
### Windows
|
||||
|
||||
View dependencies of executable or shared library:
|
||||
GUI: http://dependencywalker.com/
|
||||
|
||||
### Linux
|
||||
|
||||
#### a. View dependencies of executable or shared library:
|
||||
|
||||
$ ldd robomongo
|
||||
|
||||
View RPATH or RUNPATH records of executable or shared library:
|
||||
$ readelf -d robomongo
|
||||
|
||||
#### b. View dependency tree of executable or shared library:
|
||||
|
||||
$ lddtree robomongo
|
||||
$ ldd -v robomongo
|
||||
|
||||
#### c. View RPATH or RUNPATH records of executable or shared library:
|
||||
|
||||
$ objdump -x bin/robomongo | grep "RPATH\|RUNPATH"
|
||||
$ readelf -d bin/robomongo | grep RPATH
|
||||
|
||||
For Robomongo binary it should be `$ORIGIN/../lib`
|
||||
|
||||
##### Mac OS X
|
||||
#### d. Enable extensive logging for run-time shared library search
|
||||
|
||||
$ export LD_DEBUG=files
|
||||
$ bin/robomongo
|
||||
|
||||
Source:
|
||||
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
|
||||
|
||||
#### e. Modify RPATH using `chrpath` and the dynamic linker and RPATH using paths `patchelf`
|
||||
|
||||
$ patchelf --set-rpath '$ORIGIN/../lib' robo
|
||||
|
||||
More: https://nixos.org/patchelf.html
|
||||
|
||||
$ chrpath -r "/somepath/lib/" robomongo
|
||||
|
||||
More:
|
||||
https://linux.die.net/man/1/chrpath
|
||||
http://www.programering.com/a/MTOwcDNwATU.html // examples
|
||||
|
||||
#### f. Show symbols of shared lib file
|
||||
|
||||
Error:
|
||||
```
|
||||
/opt/robo-shell/src/mongo/util/net/ssl_manager_openssl.cpp:667:
|
||||
undefined reference to `SSL_library_init'
|
||||
```
|
||||
|
||||
How to debug:
|
||||
```
|
||||
openssl-1.1.1f: nm -gD libssl.so | grep SSL_library_init
|
||||
// not found, since SSL_library_init() is deprecated in 1.1.1
|
||||
|
||||
openssl-1.0.2o: nm -gD libssl.so | grep SSL_library_init
|
||||
0000000000055520 T SSL_library_init
|
||||
```
|
||||
|
||||
#### g. Update path of a dependency of an executable
|
||||
|
||||
```
|
||||
ldd exec_file | grep libcurlpp
|
||||
libcurlpp.so.1 => not found
|
||||
|
||||
patchelf --replace-needed libcurlpp.so.1 /foo/bar/libcurlpp.so.1 exec_file
|
||||
```
|
||||
|
||||
Another example (libcrypto.so.1.1 => not found):
|
||||
|
||||
```
|
||||
cd /opt/openssl-1.1.1f
|
||||
ldd libssl.so
|
||||
linux-vdso.so.1 => (0x00007ffcaf911000)
|
||||
libcrypto.so.1.1 => not found
|
||||
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd4087b4000)
|
||||
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd4083ea000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007fd408c65000)
|
||||
|
||||
sudo cp libcrypto.so.1.1 /lib/x86_64-linux-gnu/
|
||||
|
||||
ldd libssl.so
|
||||
linux-vdso.so.1 => (0x00007fff0f5d8000)
|
||||
libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007fd3dcc1e000)
|
||||
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd3dc854000)
|
||||
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd3dc650000)
|
||||
/lib64/ld-linux-x86-64.so.2 (0x00007fd3dd2d6000)
|
||||
|
||||
```
|
||||
|
||||
### Mac OS X
|
||||
|
||||
#### a. Show dependencies of executable or shared library:
|
||||
|
||||
Show dependencies of executable or shared library:
|
||||
|
||||
@@ -38,6 +119,57 @@ View LC_RPATH records of executable or shared library:
|
||||
|
||||
For Robomongo binary it should be `$executable_path/../Frameworks`
|
||||
|
||||
More about `otool -l`
|
||||
|
||||
```
|
||||
$ otool -l /opt/robo/build/release/src/robomongo/Robo\ 3T.app/Contents/MacOS/Robo\ 3T
|
||||
....
|
||||
Load command 23
|
||||
cmd LC_LOAD_DYLIB
|
||||
cmdsize 56
|
||||
name @rpath/lib/libssl.1.1.dylib (offset 24)
|
||||
time stamp 2 Thu Jan 1 03:00:02 1970
|
||||
current version 1.1.0
|
||||
compatibility version 1.1.0
|
||||
Load command 24
|
||||
cmd LC_LOAD_DYLIB
|
||||
cmdsize 56
|
||||
name @rpath/lib/libcrypto.1.1.dylib (offset 24)
|
||||
time stamp 2 Thu Jan 1 03:00:02 1970
|
||||
current version 1.1.0
|
||||
compatibility version 1.1.0
|
||||
....
|
||||
Load command 27
|
||||
cmd LC_RPATH
|
||||
cmdsize 48
|
||||
path /opt/Qt5.9.3/5.9.3/clang_64/lib (offset 12)
|
||||
Load command 28
|
||||
cmd LC_RPATH
|
||||
cmdsize 32
|
||||
path /opt/openssl-1.1.1f (offset 12)
|
||||
```
|
||||
|
||||
#### b. Edit dependencies of executable or shared library:
|
||||
```
|
||||
// Before
|
||||
otool -L libssl.dylib
|
||||
libssl.dylib:
|
||||
/usr/local/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
/usr/local/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
|
||||
|
||||
// Edit
|
||||
install_name_tool -id "@rpath/lib/libssl.1.1.dylib" libssl.dylib
|
||||
install_name_tool -change /usr/local/lib/libcrypto.1.1.dylib @rpath/lib/libcrypto.1.1.dylib libssl.dylib
|
||||
|
||||
// After
|
||||
otool -L libssl.dylib
|
||||
libssl.dylib:
|
||||
@rpath/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
@rpath/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
|
||||
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
|
||||
```
|
||||
|
||||
|
||||
Diagnostic of Qt plugins
|
||||
------------------------
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Robomongo</string>
|
||||
<string>Robo 3T</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
@@ -36,5 +36,7 @@
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSRequiresAquaSystemAppearance</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 827 B After Width: | Height: | Size: 827 B |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -14,7 +14,7 @@ File `robomongo.ico` will be generated.
|
||||
Which icon sizes are used on Windows?
|
||||
=====================================
|
||||
|
||||
The most important sizes are the one that is small. Robomongo should include
|
||||
The most important sizes are the one that is small. Robo 3T should include
|
||||
16, 20, 24, 40, 48. The bigger sizes are usually scaled well, without notable
|
||||
degrading in quality.
|
||||
|
||||
|
||||
@@ -26,14 +26,14 @@ IDI_ICON1 ICON "@windows_icon@"
|
||||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Paralect, Inc\0"
|
||||
VALUE "FileDescription", "Robomongo, MongoDB management tool\0"
|
||||
VALUE "CompanyName", "3T Software Labs Ltd\0"
|
||||
VALUE "FileDescription", "Robo 3T, MongoDB management tool\0"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "LegalCopyright", "Copyright Paralect, 2013 - 2016\0"
|
||||
VALUE "ProductName", "Robomongo\0"
|
||||
VALUE "LegalCopyright", "Copyright 3T Software Labs Ltd, 2014 - 2017\0"
|
||||
VALUE "ProductName", "Robo 3T\0"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
VALUE "OriginalFilename", "Robomongo.exe\0"
|
||||
VALUE "InternalName", "Robomongo\0"
|
||||
VALUE "OriginalFilename", "robo3t.exe\0"
|
||||
VALUE "InternalName", "Robo 3T\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
|
After Width: | Height: | Size: 468 KiB |
|
After Width: | Height: | Size: 361 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 262 KiB |
|
After Width: | Height: | Size: 145 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 236 KiB |
@@ -1,6 +1,6 @@
|
||||
Robomongo shortcut key reference
|
||||
================================
|
||||
|
||||
"3T", "Robomongo"
|
||||
### Windows/Linux users
|
||||
|
||||
Ctrl+Enter or F5 or Ctrl+R
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
###
|
||||
### Unit Testing with Google Test
|
||||
###
|
||||
|
||||
## !! Important Note: Currently unit testing is disabled for Linux due to MongoDB linking problem
|
||||
if (SYSTEM_LINUX)
|
||||
message("\n *Note: Currently unit testing is disabled for Linux due to MongoDB linking problem")
|
||||
return()
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
## New test & source file pairs MUST have the following format:
|
||||
# Test file: /path/Foo_test.cpp
|
||||
# Source file: /path/Foo.cpp or /path/Foo.h
|
||||
set(ROBO_SRC_DIR ${CMAKE_HOME_DIRECTORY}/src/robomongo)
|
||||
set(SOURCES_TEST
|
||||
${ROBO_SRC_DIR}/utils/RoboCrypt_test.cpp
|
||||
${ROBO_SRC_DIR}/utils/StringOperations_test.cpp
|
||||
${ROBO_SRC_DIR}/core/HexUtils_test.cpp
|
||||
)
|
||||
|
||||
add_executable(robo_unit_tests ${SOURCES_TEST})
|
||||
add_dependencies(robo_unit_tests robomongo)
|
||||
|
||||
get_target_property(ROBO_SOURCES robomongo SOURCES)
|
||||
list(FILTER ROBO_SOURCES INCLUDE REGEX "cpp")
|
||||
list(FILTER ROBO_SOURCES EXCLUDE REGEX "main.cpp")
|
||||
|
||||
if(SYSTEM_WINDOWS) ############# Windows
|
||||
set(OBJ_DIR ${CMAKE_BINARY_DIR}/src/robomongo/robomongo.dir/${CMAKE_BUILD_TYPE}/)
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}qrc_gui.obj;")
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}qrc_robo.obj;")
|
||||
foreach(SRC_FILE ${ROBO_SOURCES})
|
||||
get_filename_component(FILENAME ${SRC_FILE} NAME)
|
||||
string(REPLACE ".cpp" ".obj" FILENAME ${FILENAME})
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}${FILENAME};")
|
||||
endforeach()
|
||||
elseif(SYSTEM_MACOSX) ############# MacOS
|
||||
set(OBJ_DIR ${CMAKE_BINARY_DIR}/src/robomongo/CMakeFiles/robomongo.dir/)
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}/robomongo_autogen/mocs_compilation.cpp.o;")
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}/robomongo_autogen/YHP5W5E6RA/qrc_gui.cpp.o;")
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}/robomongo_autogen/3YJK5W5UP7/qrc_robo.cpp.o;")
|
||||
foreach(SRC_FILE ${ROBO_SOURCES})
|
||||
string(REPLACE ".cpp" ".cpp.o" OBJ_FILE ${SRC_FILE})
|
||||
set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}${OBJ_FILE};")
|
||||
endforeach()
|
||||
|
||||
find_library(SECURITY NAMES Security)
|
||||
find_library(CORE_FOUNDATION NAMES CoreFoundation)
|
||||
set(SSL_LIBRARIES ${SECURITY} ${CORE_FOUNDATION})
|
||||
|
||||
target_link_libraries(robo_unit_tests
|
||||
${SSL_LIBRARIES} -lresolv
|
||||
)
|
||||
# elseif(SYSTEM_LINUX) ############# LINUX
|
||||
# set(OBJ_DIR ${CMAKE_BINARY_DIR}/src/robomongo/CMakeFiles/robomongo.dir/)
|
||||
# message("--- OBJ_DIR: " ${OBJ_DIR})
|
||||
# set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}/robomongo_automoc.cpp.o;")
|
||||
# set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}/robomongo_automoc.dir/gui/resources/qrc_gui.cpp.o;")
|
||||
# set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}/robomongo_automoc.dir/resources/qrc_robo.cpp.o;")
|
||||
# foreach(SRC_FILE ${ROBO_SOURCES})
|
||||
# string(REPLACE ".cpp" ".cpp.o" OBJ_FILE ${SRC_FILE})
|
||||
# set(ROBO_OBJ_FILES "${ROBO_OBJ_FILES}${OBJ_DIR}${OBJ_FILE};")
|
||||
# endforeach()
|
||||
endif()
|
||||
|
||||
target_link_libraries(robo_unit_tests
|
||||
gtest gtest_main
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
Qt5::Xml
|
||||
qjson
|
||||
qscintilla
|
||||
mongodb
|
||||
ssh
|
||||
Threads::Threads
|
||||
${ROBO_OBJ_FILES}
|
||||
)
|
||||
|
||||
target_include_directories(robo_unit_tests
|
||||
PRIVATE
|
||||
${CMAKE_HOME_DIRECTORY}/src)
|
||||
|
||||
# For Windows we need to install Qt DLLs
|
||||
if(SYSTEM_WINDOWS)
|
||||
get_target_property(target_path Qt5::Core LOCATION)
|
||||
get_filename_component(qt_bin_dir ${target_path} DIRECTORY)
|
||||
set(QT_BIN_FILES "${QT_BIN_FILES}" ${qt_bin_dir}/Qt5Core${CMAKE_SHARED_LIBRARY_SUFFIX};)
|
||||
set(QT_BIN_FILES "${QT_BIN_FILES}" ${qt_bin_dir}/Qt5Gui${CMAKE_SHARED_LIBRARY_SUFFIX};)
|
||||
set(QT_BIN_FILES "${QT_BIN_FILES}" ${qt_bin_dir}/Qt5Network${CMAKE_SHARED_LIBRARY_SUFFIX};)
|
||||
set(QT_BIN_FILES "${QT_BIN_FILES}" ${qt_bin_dir}/Qt5PrintSupport${CMAKE_SHARED_LIBRARY_SUFFIX};)
|
||||
set(QT_BIN_FILES "${QT_BIN_FILES}" ${qt_bin_dir}/Qt5Widgets${CMAKE_SHARED_LIBRARY_SUFFIX};)
|
||||
set(QT_BIN_FILES "${QT_BIN_FILES}" ${qt_bin_dir}/Qt5Xml${CMAKE_SHARED_LIBRARY_SUFFIX};)
|
||||
|
||||
get_target_property(TESTS_BIN_DIR robo_unit_tests BINARY_DIR)
|
||||
file(COPY ${QT_BIN_FILES}
|
||||
DESTINATION ${TESTS_BIN_DIR}/${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
@@ -5,6 +5,10 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
#set(sanitize "-fsanitize=address")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${sanitize}")
|
||||
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${sanitize}")
|
||||
|
||||
set(SOURCES
|
||||
|
||||
# Isolated Scope #1
|
||||
@@ -24,14 +28,11 @@ set(SOURCES
|
||||
core/EventBus.cpp
|
||||
core/KeyboardManager.cpp
|
||||
core/domain/MongoNamespace.cpp
|
||||
core/domain/MongoUser.cpp
|
||||
core/domain/MongoUser.cpp
|
||||
core/domain/MongoFunction.cpp
|
||||
core/domain/MongoUtils.cpp
|
||||
core/domain/MongoCollection.cpp
|
||||
core/domain/MongoCollectionInfo.cpp
|
||||
core/domain/MongoQueryInfo.cpp
|
||||
core/domain/MongoShellResult.cpp
|
||||
core/domain/CursorPosition.cpp
|
||||
core/domain/ScriptInfo.cpp
|
||||
core/events/MongoEventsInfo.cpp
|
||||
@@ -49,12 +50,18 @@ set(SOURCES
|
||||
core/domain/App.cpp
|
||||
core/mongodb/MongoClient.cpp
|
||||
core/mongodb/MongoWorker.cpp
|
||||
core/mongodb/ReplicaSet.cpp
|
||||
core/settings/SettingsManager.cpp
|
||||
core/AppRegistry.cpp
|
||||
utils/StringOperations.cpp
|
||||
utils/common.cpp
|
||||
utils/SimpleCrypt.cpp
|
||||
utils/RoboCrypt.cpp
|
||||
|
||||
# Isolated Scope #3
|
||||
gui/GuiRegistry.cpp
|
||||
gui/dialogs/AboutDialog.cpp
|
||||
gui/dialogs/EulaDialog.cpp
|
||||
gui/dialogs/ConnectionAdvancedTab.cpp
|
||||
gui/dialogs/ConnectionAuthTab.cpp
|
||||
gui/dialogs/ConnectionBasicTab.cpp
|
||||
@@ -62,6 +69,7 @@ set(SOURCES
|
||||
gui/dialogs/ConnectionDialog.cpp
|
||||
gui/dialogs/CopyCollectionDialog.cpp
|
||||
gui/widgets/workarea/IndicatorLabel.cpp
|
||||
gui/dialogs/CreateCollectionDialog.cpp
|
||||
gui/dialogs/CreateDatabaseDialog.cpp
|
||||
gui/dialogs/CreateUserDialog.cpp
|
||||
gui/utils/ComboBoxUtils.cpp
|
||||
@@ -70,17 +78,23 @@ set(SOURCES
|
||||
# Isolated scope #4
|
||||
gui/dialogs/PreferencesDialog.cpp
|
||||
gui/dialogs/ConnectionsDialog.cpp
|
||||
gui/dialogs/ExportDialog.cpp
|
||||
gui/dialogs/ChangeShellTimeoutDialog.cpp
|
||||
|
||||
# Isolated scope #5
|
||||
gui/editors/PlainJavaScriptEditor.cpp
|
||||
gui/editors/JSLexer.cpp
|
||||
gui/editors/FindFrame.cpp
|
||||
gui/widgets/explorer/EditIndexDialog.cpp
|
||||
gui/widgets/explorer/AddEditIndexDialog.cpp
|
||||
gui/widgets/workarea/ScriptWidget.cpp
|
||||
|
||||
# Isolated scope #6
|
||||
gui/widgets/explorer/ExplorerCollectionTreeItem.cpp
|
||||
gui/widgets/explorer/ExplorerCollectionIndexesDir.cpp
|
||||
gui/widgets/explorer/ExplorerCollectionIndexItem.cpp
|
||||
gui/widgets/explorer/ExplorerTreeItem.cpp
|
||||
gui/widgets/explorer/ExplorerReplicaSetFolderItem.cpp
|
||||
gui/widgets/explorer/ExplorerReplicaSetTreeItem.cpp
|
||||
gui/widgets/explorer/ExplorerDatabaseTreeItem.cpp
|
||||
gui/widgets/explorer/ExplorerDatabaseCategoryTreeItem.cpp
|
||||
gui/widgets/explorer/ExplorerUserTreeItem.cpp
|
||||
@@ -111,37 +125,76 @@ set(SOURCES
|
||||
gui/widgets/workarea/QueryWidget.cpp
|
||||
gui/widgets/workarea/WorkAreaTabBar.cpp
|
||||
gui/widgets/workarea/WorkAreaTabWidget.cpp
|
||||
gui/widgets/workarea/WelcomeTab.cpp
|
||||
|
||||
# Final scope
|
||||
gui/widgets/LogWidget.cpp
|
||||
gui/MainWindow.cpp
|
||||
|
||||
gui/dialogs/SSHTunnelTab.cpp
|
||||
gui/dialogs/SSLTab.cpp
|
||||
core/settings/SshSettings.cpp
|
||||
core/settings/SslSettings.cpp
|
||||
core/settings/ReplicaSetSettings.cpp
|
||||
core/mongodb/SshTunnelWorker.cpp
|
||||
|
||||
resources/robo.qrc
|
||||
gui/resources/gui.qrc
|
||||
)
|
||||
|
||||
|
||||
# Robomongo target
|
||||
add_executable(robomongo MACOSX_BUNDLE WIN32 app/main.cpp ${SOURCES})
|
||||
|
||||
target_link_libraries(robomongo
|
||||
PRIVATE
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
Qt5::Xml
|
||||
qjson
|
||||
qscintilla
|
||||
mongodb
|
||||
ssh
|
||||
Threads::Threads) # Target from FindThreads CMake module
|
||||
|
||||
if(APPLE)
|
||||
find_library(SECURITY NAMES Security)
|
||||
find_library(CORE_FOUNDATION NAMES CoreFoundation)
|
||||
set(SSL_LIBRARIES ${SECURITY} ${CORE_FOUNDATION})
|
||||
|
||||
target_link_libraries(robomongo
|
||||
PRIVATE
|
||||
${SSL_LIBRARIES}
|
||||
-lresolv)
|
||||
endif(APPLE)
|
||||
|
||||
target_include_directories(robomongo
|
||||
PRIVATE
|
||||
${CMAKE_HOME_DIRECTORY}/src)
|
||||
|
||||
# Get build number
|
||||
find_package(Git)
|
||||
if(GIT_FOUND)
|
||||
MESSAGE( STATUS "Info: Git found" )
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE "BUILD_NUMBER"
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else(GIT_FOUND)
|
||||
MESSAGE( FATAL_ERROR "Unable to find Git" )
|
||||
set(BUILD_NUMBER 0)
|
||||
endif(GIT_FOUND)
|
||||
|
||||
if(BUILD_NUMBER STREQUAL "")
|
||||
MESSAGE( FATAL_ERROR "Failed to get BUILD_NUMBER" )
|
||||
endif()
|
||||
|
||||
MESSAGE( STATUS "Info: BUILD_NUMBER set as " \"${BUILD_NUMBER}\" )
|
||||
|
||||
target_compile_definitions(robomongo
|
||||
PRIVATE
|
||||
BUILDING_ROBO
|
||||
PROJECT_NAME="${PROJECT_NAME}"
|
||||
PROJECT_NAME_TITLE="${PROJECT_NAME_TITLE}"
|
||||
PROJECT_COPYRIGHT="${PROJECT_COPYRIGHT}"
|
||||
@@ -151,7 +204,17 @@ target_compile_definitions(robomongo
|
||||
PROJECT_GITHUB_FORK="${PROJECT_GITHUB_FORK}"
|
||||
PROJECT_GITHUB_ISSUES="${PROJECT_GITHUB_ISSUES}"
|
||||
PROJECT_VERSION="${PROJECT_VERSION}"
|
||||
PROJECT_NAME_LOWERCASE="${PROJECT_NAME_LOWERCASE}")
|
||||
PROJECT_VERSION_SHORT="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
BUILD_NUMBER="${BUILD_NUMBER}"
|
||||
PROJECT_NAME_LOWERCASE="${PROJECT_NAME_LOWERCASE}"
|
||||
PROJECT_QT_VERSION="${Qt5Core_VERSION}"
|
||||
MongoDB_VERSION="${MongoDB_VERSION}"
|
||||
OPENSSL_VERSION="${OPENSSL_VERSION}"
|
||||
LIBSSH2_VERSION="${LIBSSH2_VERSION}"
|
||||
QJSON_VERSION="${QJSON_VERSION}"
|
||||
GOOGLE_TEST_VERSION="${GOOGLE_TEST_VERSION}"
|
||||
ESPRIMA_VERSION="${ESPRIMA_VERSION}"
|
||||
)
|
||||
|
||||
if(SYSTEM_WINDOWS)
|
||||
# Create Windows Resource file
|
||||
@@ -162,45 +225,43 @@ if(SYSTEM_WINDOWS)
|
||||
unset(windows_icon)
|
||||
|
||||
# Add additional source file to "robomongo" target
|
||||
target_sources(robomongo
|
||||
PRIVATE
|
||||
"${CMAKE_BINARY_DIR}/winres.rc")
|
||||
target_sources(robomongo PRIVATE "${CMAKE_BINARY_DIR}/winres.rc")
|
||||
|
||||
# Rename output name for Windows
|
||||
set_target_properties(robomongo PROPERTIES
|
||||
OUTPUT_NAME "Robomongo")
|
||||
set_target_properties(robomongo PROPERTIES OUTPUT_NAME "robo3t")
|
||||
|
||||
# Suppress "warning C4477: 'sprintf'..." from robomongo\shell\db\ptimeutil.cpp
|
||||
# Suppress "warning C4291: ...no matching operator delete found" from third_party\mozjs-60
|
||||
set_target_properties(robomongo PROPERTIES COMPILE_FLAGS "/wd4477 /wd4291")
|
||||
|
||||
# Seems that we do not need to do this with recent versions of Qt
|
||||
target_link_libraries(robomongo
|
||||
PRIVATE
|
||||
Qt5::WinMain)
|
||||
target_link_libraries(robomongo PRIVATE Qt5::WinMain)
|
||||
|
||||
elseif(SYSTEM_MACOSX)
|
||||
set_target_properties(robomongo PROPERTIES
|
||||
INSTALL_RPATH "@executable_path/../Frameworks"
|
||||
OUTPUT_NAME "Robomongo"
|
||||
OUTPUT_NAME "Robo 3T"
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/install/macosx/Info.plist.in"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "Robomongo"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.paralect.Robomongo"
|
||||
MACOSX_BUNDLE_INFO_STRING "Robomongo ${PROJECT_VERSION}. Copyright Paralect, 2013 - 2016"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "Robo 3T"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "com.3tsoftwarelabs.robo3t"
|
||||
MACOSX_BUNDLE_INFO_STRING "Robo 3T ${PROJECT_VERSION}. Copyright 3T Software Labs Ltd, 2014 - 2017"
|
||||
MACOSX_BUNDLE_SHORT_VERSION "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_LONG_VERSION "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_COPYRIGHT "Copyright Paralect, 2013 - 2016"
|
||||
MACOSX_BUNDLE_ICON_FILE "Robomongo")
|
||||
MACOSX_BUNDLE_COPYRIGHT "Copyright 3T Software Labs Ltd, 2014 - 2017"
|
||||
MACOSX_BUNDLE_ICON_FILE "robomongo")
|
||||
|
||||
elseif(SYSTEM_LINUX)
|
||||
set_target_properties(robomongo PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN/../lib")
|
||||
INSTALL_RPATH "$ORIGIN/../lib"
|
||||
OUTPUT_NAME "robo3t")
|
||||
endif()
|
||||
|
||||
# Install
|
||||
include(RobomongoInstall)
|
||||
|
||||
|
||||
#
|
||||
# Tests targets (code below should be moved to separate file)
|
||||
#
|
||||
add_executable(tests WIN32 EXCLUDE_FROM_ALL app/main_test.cpp gui/editors/JSLexer.cpp)
|
||||
target_link_libraries(tests Qt5::Widgets qjson qscintilla mongodb Threads::Threads)
|
||||
target_include_directories(tests
|
||||
|
||||
@@ -6,20 +6,27 @@
|
||||
// Header "mongo/util/net/sock" is needed for mongo::enableIPv6()
|
||||
// Header "mongo/platform/basic" is required by "sock.h" under Windows
|
||||
#include <mongo/platform/basic.h>
|
||||
#include <mongo/util/net/sock.h>
|
||||
|
||||
#include <mongo/util/net/socket_utils.h>
|
||||
#include <mongo/base/initializer.h>
|
||||
#include <mongo/util/net/ssl_options.h>
|
||||
#include <mongo/db/service_context.h>
|
||||
#include <mongo/transport/transport_layer_asio.h>
|
||||
#include <mongo/shell/shell_options.h>
|
||||
#include <mongo/db/storage/storage_engine_init.h>
|
||||
|
||||
#include "robomongo/core/AppRegistry.h"
|
||||
#include "robomongo/core/settings/SettingsManager.h"
|
||||
#include "robomongo/core/utils/Logger.h"
|
||||
#include "robomongo/gui/MainWindow.h"
|
||||
#include "robomongo/gui/AppStyle.h"
|
||||
|
||||
#include "robomongo/gui/dialogs/EulaDialog.h"
|
||||
#include "robomongo/ssh/ssh.h"
|
||||
#include "robomongo/utils/RoboCrypt.h"
|
||||
|
||||
int main(int argc, char *argv[], char** envp)
|
||||
{
|
||||
if (rbm_ssh_init()) {
|
||||
if (rbm_ssh_init())
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Please check, do we really need envp for other OSes?
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -29,8 +36,26 @@ int main(int argc, char *argv[], char** envp)
|
||||
// Support for IPv6 is disabled by default. Enable it.
|
||||
mongo::enableIPv6(true);
|
||||
|
||||
// Perform SSL-enabled mongo initialization
|
||||
mongo::sslGlobalParams.sslMode.store(mongo::SSLParams::SSLMode_allowSSL);
|
||||
|
||||
// Cross Platform High DPI support - Qt 5.7
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
|
||||
// Initialization routine for MongoDB shell
|
||||
mongo::runGlobalInitializersOrDie(argc, argv, envp);
|
||||
mongo::setGlobalServiceContext(mongo::ServiceContext::make());
|
||||
// Todo from mongo repo: This should use a TransportLayerManager or TransportLayerFactory
|
||||
auto serviceContext = mongo::getGlobalServiceContext();
|
||||
mongo::transport::TransportLayerASIO::Options opts;
|
||||
opts.enableIPv6 = false; // Todo: When true, it breaks connection to localhost, github #1757
|
||||
opts.mode = mongo::transport::TransportLayerASIO::Options::kEgress;
|
||||
serviceContext->setTransportLayer(
|
||||
std::make_unique<mongo::transport::TransportLayerASIO>(opts, nullptr)
|
||||
);
|
||||
auto tlPtr = serviceContext->getTransportLayer();
|
||||
uassertStatusOK(tlPtr->setup());
|
||||
uassertStatusOK(tlPtr->start());
|
||||
|
||||
// Initialize Qt application
|
||||
QApplication app(argc, argv);
|
||||
@@ -39,30 +64,47 @@ int main(int argc, char *argv[], char** envp)
|
||||
// This can cause a conflict when using POSIX functions, for instance, when
|
||||
// converting between data types such as floats and strings, since the notation
|
||||
// may differ between locales. To get around this problem, call the POSIX
|
||||
// function setlocale(LC_NUMERIC,"C") right after initializing QApplication or
|
||||
// function setlocale(LC_NUMERIC, "C") right after initializing QApplication or
|
||||
// QCoreApplication to reset the locale that is used for number formatting to "C"-locale.
|
||||
// (http://doc.qt.io/qt-5/qcoreapplication.html#locale-settings)
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
|
||||
// EULA License Agreement
|
||||
auto const& settings { Robomongo::AppRegistry::instance().settingsManager() };
|
||||
if (!settings->acceptedEulaVersions().contains(PROJECT_VERSION)) {
|
||||
bool const showFormPage { settings->programExitedNormally() && !settings->disableHttpsFeatures() };
|
||||
Robomongo::EulaDialog eulaDialog(showFormPage);
|
||||
settings->setProgramExitedNormally(false);
|
||||
settings->save();
|
||||
int const result = eulaDialog.exec();
|
||||
settings->setProgramExitedNormally(true);
|
||||
settings->save();
|
||||
if (QDialog::Rejected == result) {
|
||||
rbm_ssh_cleanup();
|
||||
return 1;
|
||||
}
|
||||
// EULA accepted
|
||||
settings->addAcceptedEulaVersion(PROJECT_VERSION);
|
||||
settings->save();
|
||||
}
|
||||
|
||||
// Init GUI style
|
||||
Robomongo::AppStyleUtils::initStyle();
|
||||
|
||||
// To be set true at normal program exit
|
||||
settings->setProgramExitedNormally(false);
|
||||
settings->save();
|
||||
|
||||
// Application main window
|
||||
Robomongo::MainWindow win;
|
||||
Robomongo::MainWindow mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
// Resize main window. We are trying to keep it "almost" maximized.
|
||||
QRect screenGeometry = QApplication::desktop()->availableGeometry();
|
||||
int horizontalMargin = (int)(screenGeometry.width() * 0.1);
|
||||
int verticalMargin = (int)(screenGeometry.height() * 0.1);
|
||||
int width = screenGeometry.width() - horizontalMargin;
|
||||
int height = screenGeometry.height() - verticalMargin;
|
||||
win.resize(QSize(width, height));
|
||||
|
||||
// Center main window
|
||||
int x = (screenGeometry.width() - win.width()) / 2;
|
||||
int y = (screenGeometry.height() - win.height()) / 2;
|
||||
win.move(x, y);
|
||||
win.show();
|
||||
for(auto const& msgAndSeverity : Robomongo::RoboCrypt::roboCryptLogs())
|
||||
Robomongo::LOG_MSG(msgAndSeverity.first, msgAndSeverity.second);
|
||||
|
||||
int rc = app.exec();
|
||||
rbm_ssh_cleanup();
|
||||
|
||||
@@ -33,12 +33,19 @@ void precisionAssert(const std::string &text, double d) {
|
||||
std::stringstream s;
|
||||
s.precision(std::numeric_limits<double>::digits10);
|
||||
s << d;
|
||||
if (d == (long long)d)
|
||||
s << ".0";
|
||||
std::cout << "Checking " << text << " - ";
|
||||
assert(text == s.str());
|
||||
std::cout << "Correct. " << std::endl;
|
||||
}
|
||||
|
||||
void testPrecision() {
|
||||
precisionAssert("-9.987654321", -9.987654321);
|
||||
precisionAssert("-1.0", -1.0);
|
||||
precisionAssert("-0.0", -0.0);
|
||||
precisionAssert("0.0", 0.0);
|
||||
precisionAssert("9.0", 9.0);
|
||||
precisionAssert("9.8", 9.8);
|
||||
precisionAssert("9.9", 9.9);
|
||||
precisionAssert("9.98", 9.98);
|
||||
|
||||
@@ -30,4 +30,21 @@ namespace Robomongo
|
||||
|
||||
class MongoDocument;
|
||||
typedef boost::shared_ptr<MongoDocument> MongoDocumentPtr;
|
||||
|
||||
// todo: Use enum class
|
||||
enum ConnectionType {
|
||||
// This type of connection is shown in Explorer and also opens SSH tunnel for secondary
|
||||
// connections (if needed)
|
||||
ConnectionPrimary = 0,
|
||||
|
||||
// Never shown in Explorer and uses SSH tunnel from primary connection (if needed)
|
||||
ConnectionSecondary = 1,
|
||||
|
||||
// The same as Primary, but is specifically for testing connections.
|
||||
ConnectionTest = 2,
|
||||
|
||||
// Never shown in Explorer and can be used to refresh (via reconnecting) current connection view
|
||||
// (i.e. db version, storage engine, current replica set primary, status of replica set etc...)
|
||||
ConnectionRefresh = 3
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace
|
||||
template<typename type, int size>
|
||||
inline type findTypeInArray(const char *(&arr)[size], const char *text)
|
||||
{
|
||||
for (int i=0; i < size;++i )
|
||||
for (int i = 0; i < size; ++i )
|
||||
{
|
||||
if (strcmp(text,arr[i])==0)
|
||||
if (strcmp(text, arr[i]) == 0)
|
||||
{
|
||||
return static_cast<type>(i);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
struct RemoveIfReciver : public std::unary_function<const Robomongo::EventBus::SubscribersType&, bool>
|
||||
struct RemoveIfReciver
|
||||
{
|
||||
RemoveIfReciver(QObject *receiver) : _receiver(receiver) {}
|
||||
|
||||
bool operator()(const Robomongo::EventBus::SubscribersType& item) const {
|
||||
bool operator()(const Robomongo::EventBus::EventTypeAndSubscriber& item) const {
|
||||
if (item.second->receiver == _receiver) {
|
||||
delete item.second;
|
||||
return true;
|
||||
@@ -28,13 +28,13 @@ namespace
|
||||
QObject *_receiver;
|
||||
};
|
||||
|
||||
struct FindIfReciver : public std::unary_function<const Robomongo::EventBus::SubscribersType&, bool>
|
||||
struct FindIfReciver
|
||||
{
|
||||
FindIfReciver(QThread *thread) : _thread(thread) {}
|
||||
bool operator()(const Robomongo::EventBus::DispatchersType &item) const {
|
||||
if (item.first == _thread) {
|
||||
bool operator()(const Robomongo::EventBus::ThreadAndDispatcher &item) const {
|
||||
if (item.first == _thread)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
QThread *_thread;
|
||||
@@ -50,19 +50,16 @@ namespace Robomongo
|
||||
|
||||
EventBus::~EventBus()
|
||||
{
|
||||
for (DispatchersContainerType::iterator it = _dispatchersByThread.begin(); it != _dispatchersByThread.end(); ++it) {
|
||||
DispatchersType item = *it;
|
||||
delete item.second;
|
||||
}
|
||||
for (auto const& dispatchersByThread : _dispatchersByThread)
|
||||
delete dispatchersByThread.second;
|
||||
}
|
||||
|
||||
void EventBus::publish(Event *event)
|
||||
{
|
||||
QMutexLocker lock(&_lock);
|
||||
QList<QObject*> theReceivers;
|
||||
EventBusDispatcher *dis = NULL;
|
||||
for (SubscribersContainerType::iterator it = _subscribersByEventType.begin(); it != _subscribersByEventType.end(); ++it ) {
|
||||
SubscribersType item = *it;
|
||||
EventBusDispatcher *dis = nullptr;
|
||||
for (auto const& item : _subscribersByEventType) {
|
||||
if (event->type() == item.first) {
|
||||
EventBusSubscriber *subscriber = item.second;
|
||||
if (!subscriber->sender || subscriber->sender == event->sender()) {
|
||||
@@ -118,7 +115,7 @@ namespace Robomongo
|
||||
VERIFY(connect(receiver, SIGNAL(destroyed(QObject*)), this, SLOT(unsubscibe(QObject*))));
|
||||
|
||||
// add subscriber
|
||||
_subscribersByEventType.push_back(SubscribersType(type, new EventBusSubscriber(dis, receiver, sender)));
|
||||
_subscribersByEventType.push_back(EventTypeAndSubscriber(type, new EventBusSubscriber(dis, receiver, sender)));
|
||||
}
|
||||
|
||||
void EventBus::unsubscibe(QObject *receiver)
|
||||
@@ -134,8 +131,9 @@ namespace Robomongo
|
||||
*/
|
||||
EventBusDispatcher *EventBus::dispatcher(QThread *thread)
|
||||
{
|
||||
DispatchersContainerType::iterator disIt = std::find_if(
|
||||
_dispatchersByThread.begin(), _dispatchersByThread.end(), FindIfReciver(thread));
|
||||
auto const& disIt = std::find_if(
|
||||
_dispatchersByThread.begin(), _dispatchersByThread.end(), FindIfReciver(thread)
|
||||
);
|
||||
|
||||
if (disIt != _dispatchersByThread.end()) {
|
||||
return (*disIt).second;
|
||||
@@ -143,7 +141,7 @@ namespace Robomongo
|
||||
else {
|
||||
EventBusDispatcher *dis = new EventBusDispatcher();
|
||||
dis->moveToThread(thread);
|
||||
_dispatchersByThread.push_back(DispatchersType(thread, dis));
|
||||
_dispatchersByThread.push_back(ThreadAndDispatcher(thread, dis));
|
||||
return dis;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,9 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef std::pair<QEvent::Type, EventBusSubscriber *> SubscribersType;
|
||||
typedef std::vector<SubscribersType > SubscribersContainerType;
|
||||
typedef std::pair<QThread *, EventBusDispatcher *> DispatchersType;
|
||||
typedef std::vector<DispatchersType> DispatchersContainerType;
|
||||
typedef std::pair<QEvent::Type, EventBusSubscriber *> EventTypeAndSubscriber;
|
||||
typedef std::pair<QThread *, EventBusDispatcher *> ThreadAndDispatcher;
|
||||
|
||||
EventBus();
|
||||
~EventBus();
|
||||
|
||||
@@ -65,7 +64,7 @@ namespace Robomongo
|
||||
|
||||
private:
|
||||
QMutex _lock;
|
||||
SubscribersContainerType _subscribersByEventType;
|
||||
DispatchersContainerType _dispatchersByThread;
|
||||
std::vector<EventTypeAndSubscriber> _subscribersByEventType;
|
||||
std::vector<ThreadAndDispatcher> _dispatchersByThread;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,19 +1,35 @@
|
||||
#include "robomongo/core/EventError.h"
|
||||
|
||||
#include "robomongo/utils/StringOperations.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
EventError::EventError() :
|
||||
_isNull(true) {}
|
||||
|
||||
EventError::EventError(const std::string &errorMessage) :
|
||||
_errorMessage(errorMessage),
|
||||
EventError::EventError(const std::string &errorMessage, ErrorCode errorCode /*= Unknown*/,
|
||||
bool showErrorWindow /* = true */) :
|
||||
_errorMessage(captilizeFirstChar(errorMessage)),
|
||||
_errorCode(errorCode),
|
||||
_showErrorWindow(showErrorWindow),
|
||||
_isNull(false) {}
|
||||
|
||||
bool EventError::isNull() const {
|
||||
EventError::EventError(const std::string &errorMessage, ReplicaSet const& replicaSetInfo,
|
||||
bool showErrorWindow /* = true */ ) :
|
||||
_errorMessage(errorMessage),
|
||||
_errorCode(SetPrimaryUnreachable),
|
||||
_replicaSetInfo(replicaSetInfo),
|
||||
_showErrorWindow(showErrorWindow),
|
||||
_isNull(false) {}
|
||||
|
||||
bool EventError::isNull() const
|
||||
{
|
||||
return _isNull;
|
||||
}
|
||||
|
||||
const std::string &EventError::errorMessage() const {
|
||||
const std::string &EventError::errorMessage() const
|
||||
{
|
||||
return _errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#include "robomongo/core/mongodb/ReplicaSet.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
/**
|
||||
@@ -10,7 +12,11 @@ namespace Robomongo
|
||||
*/
|
||||
class EventError
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
enum ErrorCode { Unknown, SetPrimaryUnreachable, ServerHasDifferentMembers };
|
||||
|
||||
/**
|
||||
* @brief Creates "null" (or, in other words, empty) error.
|
||||
* Subsequent call of isNull() on this object will return true.
|
||||
@@ -21,7 +27,14 @@ namespace Robomongo
|
||||
* @brief Creates error object with specified error message.
|
||||
* Subsequent call of isNull() on this object will return false.
|
||||
*/
|
||||
explicit EventError(const std::string &errorMessage);
|
||||
explicit EventError(const std::string &errorMessage, ErrorCode errorCode = Unknown,
|
||||
bool showErrorWindow = true);
|
||||
|
||||
/**
|
||||
* @brief Creates error object only for replica set connection failures
|
||||
*/
|
||||
explicit EventError(const std::string &errorMessage, ReplicaSet const& replicaSetInfo,
|
||||
bool showErrorWindow = true);
|
||||
|
||||
/**
|
||||
* @brief Tests whether error is "null" (or, in other words, empty).
|
||||
@@ -35,13 +48,19 @@ namespace Robomongo
|
||||
* @brief Returns error message that describes this error.
|
||||
*/
|
||||
const std::string &errorMessage() const;
|
||||
|
||||
ErrorCode errorCode() const { return _errorCode; }
|
||||
ReplicaSet replicaSetInfo() const { return _replicaSetInfo; }
|
||||
bool showErrorWindow() const { return _showErrorWindow; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Error message
|
||||
*/
|
||||
const std::string _errorMessage;
|
||||
|
||||
bool _isNull;
|
||||
std::string const _errorMessage;
|
||||
ErrorCode const _errorCode = Unknown;
|
||||
ReplicaSet const _replicaSetInfo;
|
||||
bool const _showErrorWindow = true;
|
||||
bool const _isNull;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace Robomongo
|
||||
char *data = new char[bytes];
|
||||
|
||||
const char *p = s.c_str();
|
||||
for( size_t i = 0; i < bytes; i++ ) {
|
||||
data[i] = mongo::fromHex(p);
|
||||
for (size_t i = 0; i < bytes; i++) {
|
||||
data[i] = mongo::fromHex(p).getValue();
|
||||
p += 2;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace Robomongo
|
||||
mongo::BinDataType binType = element.binDataType();
|
||||
|
||||
if (binType != mongo::newUUID && binType != mongo::bdtUUID)
|
||||
throw new std::invalid_argument("Binary subtype should be 3 (bdtUUID) or 4 (newUUID)");
|
||||
throw std::invalid_argument("Binary subtype should be 3 (bdtUUID) or 4 (newUUID)");
|
||||
|
||||
int len;
|
||||
const char *data = element.binData(len);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "gtest/gtest.h"
|
||||
#include "HexUtils.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
/* Example Test:
|
||||
*
|
||||
* TEST( [Test_Case_Name], [Test_Name] )
|
||||
* TEST( [Test_Case_Name], [UnitOfWorkName_ScenarioUnderTest_ExpectedBehavior] )
|
||||
* TEST( StringParserTests, NumberLeftOf_StringWithoutNumber_ReturnsFalse) {
|
||||
// ...
|
||||
}
|
||||
*/
|
||||
|
||||
TEST(hex_utils_tests, test_1)
|
||||
{
|
||||
EXPECT_TRUE(Robomongo::HexUtils::isHexString("a"));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#include "robomongo/core/domain/App.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "robomongo/core/domain/MongoServer.h"
|
||||
#include "robomongo/core/domain/MongoShell.h"
|
||||
#include "robomongo/core/domain/MongoCollection.h"
|
||||
#include "robomongo/core/settings/ConnectionSettings.h"
|
||||
#include "robomongo/core/settings/ReplicaSetSettings.h"
|
||||
#include "robomongo/core/settings/SshSettings.h"
|
||||
#include "robomongo/core/settings/SslSettings.h"
|
||||
#include "robomongo/core/mongodb/SshTunnelWorker.h"
|
||||
#include "robomongo/core/EventBus.h"
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
@@ -32,43 +37,127 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
App::~App()
|
||||
{}
|
||||
|
||||
App::App(EventBus *const bus) : QObject(),
|
||||
_bus(bus) {
|
||||
_bus(bus), _lastServerHandle(0) {
|
||||
_bus->subscribe(this, EstablishSshConnectionResponse::Type);
|
||||
_bus->subscribe(this, ListenSshConnectionResponse::Type);
|
||||
_bus->subscribe(this, LogEvent::Type);
|
||||
}
|
||||
|
||||
App::~App()
|
||||
std::unique_ptr<MongoServer>
|
||||
App::continueOpenServer(int serverHandle, ConnectionSettings* connSettings, ConnectionType type,
|
||||
int localport)
|
||||
{
|
||||
std::for_each(_shells.begin(), _shells.end(), stdutils::default_delete<MongoShell*>());
|
||||
std::for_each(_servers.begin(), _servers.end(), stdutils::default_delete<MongoServer*>());
|
||||
ConnectionSettings* connSettingsClone = connSettings->clone();
|
||||
|
||||
// Modify connection settings when SSH tunnel is used
|
||||
if ((type == ConnectionPrimary || type == ConnectionTest)
|
||||
&& connSettingsClone->sshSettings()->enabled()) {
|
||||
connSettingsClone->setServerHost("127.0.0.1");
|
||||
connSettingsClone->setServerPort(localport);
|
||||
}
|
||||
|
||||
auto server{ std::make_unique<MongoServer>(serverHandle, connSettingsClone, type) };
|
||||
server->runWorkerThread();
|
||||
|
||||
auto replicaSetStr = QString::fromStdString(connSettings->connectionName()) + " [Replica Set]";
|
||||
replicaSetStr = (connSettings->replicaSetSettings()->members().size() > 0)
|
||||
? replicaSetStr + QString::fromStdString(connSettings->replicaSetSettings()->members()[0])
|
||||
: replicaSetStr + "";
|
||||
|
||||
QString serverAddress = connSettings->isReplicaSet()
|
||||
? replicaSetStr
|
||||
: QString::fromStdString(connSettings->getFullAddress());
|
||||
|
||||
LOG_MSG(QString("Connecting to %1...").arg(serverAddress), mongo::logger::LogSeverity::Info());
|
||||
server->tryConnect();
|
||||
return server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and opens new server connection.
|
||||
* @param connection: ConnectionSettings, that will be owned by MongoServer.
|
||||
* @param visible: should this server be visible in UI (explorer) or not.
|
||||
*/
|
||||
MongoServer *App::openServer(ConnectionSettings *connection, bool visible) {
|
||||
if (visible)
|
||||
* Creates and opens new server connection.
|
||||
* @param connection: ConnectionSettings, that will be owned by MongoServer.
|
||||
* @param visible: should this server be visible in UI (explorer) or not.
|
||||
*/
|
||||
std::unique_ptr<MongoServer>
|
||||
App::openServerInternal(ConnectionSettings* connSettings, ConnectionType type)
|
||||
{
|
||||
++_lastServerHandle;
|
||||
|
||||
if (type == ConnectionPrimary)
|
||||
_bus->publish(new ConnectingEvent(this));
|
||||
|
||||
// When connection is not "visible" or do not have
|
||||
// When connection is SECONDARY or do not have
|
||||
// ssh settings enabled, continue without SSH Tunnel
|
||||
if (!visible || !connection->sshSettings()->enabled()) {
|
||||
return continueOpenServer(connection, visible);
|
||||
if (type == ConnectionSecondary || !connSettings->sshSettings()->enabled()) {
|
||||
return continueOpenServer(_lastServerHandle, connSettings, type);
|
||||
}
|
||||
|
||||
// Open SSH channel and only after that open connection
|
||||
LOG_MSG(QString("Creating SSH tunnel to %1:%2...")
|
||||
.arg(QtUtils::toQString(connection->sshSettings()->host()))
|
||||
.arg(connection->sshSettings()->port()), mongo::logger::LogSeverity::Info());
|
||||
.arg(QtUtils::toQString(connSettings->sshSettings()->host()))
|
||||
.arg(connSettings->sshSettings()->port()), mongo::logger::LogSeverity::Info());
|
||||
|
||||
ConnectionSettings* settingsCopy = connection->clone();
|
||||
ConnectionSettings* settingsCopy = connSettings->clone();
|
||||
SshTunnelWorker* sshWorker = new SshTunnelWorker(settingsCopy);
|
||||
_bus->send(sshWorker, new EstablishSshConnectionRequest(this, sshWorker, settingsCopy, visible));
|
||||
return NULL;
|
||||
_bus->send(sshWorker, new EstablishSshConnectionRequest(this, _lastServerHandle, sshWorker, settingsCopy, type));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool App::openServer(ConnectionSettings *connection, ConnectionType type)
|
||||
{
|
||||
SshSettings *ssh = connection->sshSettings();
|
||||
|
||||
if (ssh->enabled() && ssh->askPassword() &&
|
||||
(type == ConnectionPrimary || type == ConnectionTest)) {
|
||||
bool ok = false;
|
||||
|
||||
bool isByKey = ssh->authMethod() == "publickey";
|
||||
std::string passText = isByKey ? "passphrase" : "password";
|
||||
|
||||
std::stringstream s;
|
||||
s << "In order to continue, please provide the " << passText;
|
||||
|
||||
if (isByKey)
|
||||
s << " for the key file";
|
||||
|
||||
s << "." << std::endl << std::endl;
|
||||
|
||||
if (ssh->authMethod() == "publickey")
|
||||
s << "Private Key: " << ssh->privateKeyFile() << std::endl;
|
||||
|
||||
s << "Server: " << ssh->host() << std::endl;
|
||||
s << "User: " << ssh->userName() << std::endl;
|
||||
|
||||
|
||||
s << std::endl << "Enter your " << passText << " that will never be stored:";
|
||||
|
||||
QString userInput = QInputDialog::getText(NULL, tr("SSH Authentication"),
|
||||
QtUtils::toQString(s.str()),
|
||||
QLineEdit::Password, "", &ok);
|
||||
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
ssh->setAskedPassword(QtUtils::toStdString(userInput));
|
||||
}
|
||||
|
||||
SslSettings *sslSettings = connection->sslSettings();
|
||||
|
||||
if (sslSettings->sslEnabled() && sslSettings->usePemFile() && sslSettings->askPassphrase()
|
||||
&& (type == ConnectionPrimary || type == ConnectionTest))
|
||||
{
|
||||
if (!askSslPassphrasePromptDialog(connection))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_servers.push_back(move(openServerInternal(connection, type)));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,46 +166,59 @@ namespace Robomongo
|
||||
*/
|
||||
void App::closeServer(MongoServer *server)
|
||||
{
|
||||
_servers.erase(std::remove_if(_servers.begin(), _servers.end(), stdutils::RemoveIfFound<MongoServer*>(server)), _servers.end());
|
||||
_servers.erase(std::remove_if(_servers.begin(), _servers.end(),
|
||||
[&](auto const& el) { return el.get() == server; }), _servers.end());
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(MongoCollection *collection,const QString &filePathToSave)
|
||||
void App::openShell(MongoCollection *collection, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = collection->database()->server()->connectionRecord();
|
||||
connection->setDefaultDatabase(collection->database()->name());
|
||||
QString script = detail::buildCollectionQuery(collection->name(), "find({})");
|
||||
return openShell(connection, ScriptInfo(script, true, CursorPosition(0, -2), QtUtils::toQString(collection->database()->name()),filePathToSave));
|
||||
auto const& dbname = collection->database()->name();
|
||||
connection->setDefaultDatabase(dbname);
|
||||
QString const& script = detail::buildCollectionQuery(collection->name(), "find({})");
|
||||
openShell(collection->database()->server(), connection,
|
||||
ScriptInfo(script, true, dbname, CursorPosition(0, -2), QtUtils::toQString(dbname), filePathToSave)
|
||||
);
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(MongoServer *server,const QString &script, const std::string &dbName,
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition,const QString &filePathToSave)
|
||||
void App::openShell(MongoServer *server, const QString &script, const std::string &dbName,
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = server->connectionRecord();
|
||||
|
||||
if (!dbName.empty())
|
||||
connection->setDefaultDatabase(dbName);
|
||||
|
||||
return openShell(connection, ScriptInfo(script, execute, cursorPosition, shellName,filePathToSave));
|
||||
openShell(server, connection,
|
||||
ScriptInfo(script, execute, dbName, cursorPosition, shellName, filePathToSave)
|
||||
);
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(MongoDatabase *database, const QString &script,
|
||||
void App::openShell(MongoDatabase *database, const QString &script,
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition,const QString &filePathToSave)
|
||||
const CursorPosition &cursorPosition, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = database->server()->connectionRecord();
|
||||
connection->setDefaultDatabase(database->name());
|
||||
return openShell(connection, ScriptInfo(script, execute, cursorPosition, shellName,filePathToSave));
|
||||
openShell(database->server(), connection, ScriptInfo(script, execute, database->name(),
|
||||
cursorPosition, shellName, filePathToSave));
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo)
|
||||
void App::openShell(MongoServer* server, ConnectionSettings* connection, const ScriptInfo &scriptInfo)
|
||||
{
|
||||
MongoServer *server = openServer(connection, false);
|
||||
MongoShell *shell = new MongoShell(server,scriptInfo);
|
||||
_shells.push_back(shell);
|
||||
_bus->publish(new OpeningShellEvent(this, shell));
|
||||
auto serverClone{ openServerInternal(connection, ConnectionSecondary) };
|
||||
if (!serverClone || !server)
|
||||
return;
|
||||
|
||||
auto shell{ std::make_unique<MongoShell>(serverClone.get(), scriptInfo) };
|
||||
_servers.push_back(move(serverClone));
|
||||
// Connection between explorer's server and tab's MongoShells
|
||||
_bus->subscribe(server, ReplicaSetRefreshed::Type, shell.get());
|
||||
_bus->publish(new OpeningShellEvent(this, shell.get()));
|
||||
shell->execute();
|
||||
return shell;
|
||||
_shells.push_back(move(shell));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,67 +227,89 @@ namespace Robomongo
|
||||
*/
|
||||
void App::closeShell(MongoShell *shell)
|
||||
{
|
||||
auto const itr = std::find_if(_shells.begin(), _shells.end(),
|
||||
[&](auto const& el) { return el.get() == shell; }
|
||||
);
|
||||
|
||||
// Do nothing, if this shell not owned by this App.
|
||||
MongoShellsContainerType::iterator it = std::find_if(_shells.begin(),_shells.end(),std::bind1st(std::equal_to<MongoShell *>(),shell));
|
||||
if (it == _shells.end())
|
||||
if (itr == _shells.end())
|
||||
return;
|
||||
|
||||
_shells.erase(it);
|
||||
closeServer(shell->server());
|
||||
delete shell;
|
||||
}
|
||||
|
||||
MongoServer* App::continueOpenServer(ConnectionSettings *connection, bool visible, int localport) {
|
||||
ConnectionSettings* settings = connection->clone();
|
||||
|
||||
// Modify connection settings when SSH tunnel is used
|
||||
if (visible && settings->sshSettings()->enabled()) {
|
||||
settings->setServerHost("127.0.0.1");
|
||||
settings->setServerPort(localport);
|
||||
}
|
||||
|
||||
MongoServer *server = new MongoServer(settings, visible);
|
||||
_servers.push_back(server);
|
||||
|
||||
server->runWorkerThread();
|
||||
|
||||
LOG_MSG(QString("Connecting to %1...").arg(QtUtils::toQString(server->connectionRecord()->getFullAddress())), mongo::logger::LogSeverity::Info());
|
||||
server->tryConnect();
|
||||
return server;
|
||||
_shells.erase(itr);
|
||||
}
|
||||
|
||||
void App::handle(EstablishSshConnectionResponse *event) {
|
||||
if (event->isError()) {
|
||||
_bus->publish(new ConnectionFailedEvent(this, event->error().errorMessage()));
|
||||
_bus->publish(new ConnectionFailedEvent(
|
||||
this, event->serverHandle, event->connectionType, event->error().errorMessage(),
|
||||
ConnectionFailedEvent::SshConnection));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_MSG(QString("SSH tunnel created successfully"), mongo::logger::LogSeverity::Info());
|
||||
|
||||
_bus->send(event->worker, new ListenSshConnectionRequest(this));
|
||||
continueOpenServer(event->settings, event->visible, event->localport);
|
||||
|
||||
// record event->worker and delete when needed
|
||||
_servers.push_back(move(
|
||||
continueOpenServer(event->serverHandle, event->settings, event->connectionType, event->localport)
|
||||
));
|
||||
_bus->send(event->worker, new ListenSshConnectionRequest(this, event->serverHandle, event->connectionType));
|
||||
}
|
||||
|
||||
void App::handle(LogEvent *event) {
|
||||
if (event->level == LogEvent::ERROR) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Error());
|
||||
} else if (event->level == LogEvent::WARN) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Warning());
|
||||
} else if (event->level == LogEvent::INFO) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Info());
|
||||
} else if (event->level == LogEvent::DEBUG) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Log());
|
||||
}
|
||||
LOG_MSG(event->message, event->mongoLogSeverity());
|
||||
|
||||
if (!event->informUser)
|
||||
return;
|
||||
|
||||
QMessageBox(
|
||||
event->qMessageBoxIcon(),
|
||||
QString::fromStdString(event->severity()),
|
||||
QtUtils::toQString(event->severity() + ": " + event->message)
|
||||
).exec();
|
||||
}
|
||||
|
||||
void App::handle(ListenSshConnectionResponse *event) {
|
||||
if (event->isError()) {
|
||||
_bus->publish(new ConnectionFailedEvent(this, event->error().errorMessage()));
|
||||
_bus->publish(
|
||||
new ConnectionFailedEvent(this, event->serverHandle, event->connectionType,
|
||||
event->error().errorMessage(), ConnectionFailedEvent::SshChannel)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_MSG(QString("SSH tunnel closed."), mongo::logger::LogSeverity::Error());
|
||||
}
|
||||
|
||||
void App::fireConnectionFailedEvent(int serverHandle, ConnectionType type, std::string errormsg,
|
||||
ConnectionFailedEvent::Reason reason) {
|
||||
_bus->publish(new ConnectionFailedEvent(this, serverHandle, type, errormsg, reason));
|
||||
}
|
||||
|
||||
bool App::askSslPassphrasePromptDialog(ConnectionSettings *connSettings) const
|
||||
{
|
||||
auto sslSettings = connSettings->sslSettings();
|
||||
bool ok = false;
|
||||
|
||||
std::stringstream s;
|
||||
s << "In order to continue, please provide the passphrase";
|
||||
s << "." << std::endl << std::endl;
|
||||
|
||||
s << "Server: " << connSettings->serverHost() << ":" << connSettings->serverPort() << std::endl;
|
||||
s << "PEM file: " << sslSettings->pemKeyFile() << std::endl;
|
||||
|
||||
s << std::endl << "Enter your PEM key passphrase (will never be stored):";
|
||||
|
||||
QString userInput = QInputDialog::getText(NULL, tr("TLS Authentication"),
|
||||
QtUtils::toQString(s.str()),
|
||||
QLineEdit::Password, "", &ok);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sslSettings->setPemPassPhrase(QtUtils::toStdString(userInput));
|
||||
return ok;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,8 +38,6 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef std::vector<MongoServer*> MongoServersContainerType;
|
||||
typedef std::vector<MongoShell*> MongoShellsContainerType;
|
||||
App(EventBus *const bus);
|
||||
~App();
|
||||
|
||||
@@ -47,8 +45,9 @@ namespace Robomongo
|
||||
* @brief Creates and opens new server connection.
|
||||
* @param connection: ConnectionSettings, that will be owned by MongoServer.
|
||||
* @param visible: should this server be visible in UI (explorer) or not.
|
||||
* @return Succeeded or not
|
||||
*/
|
||||
MongoServer *openServer(ConnectionSettings *connection, bool visible);
|
||||
bool openServer(ConnectionSettings *connection, ConnectionType type);
|
||||
|
||||
/**
|
||||
* @brief Closes MongoServer connection and frees all resources, owned
|
||||
@@ -59,18 +58,23 @@ namespace Robomongo
|
||||
/**
|
||||
* @brief Open new shell based on specified collection
|
||||
*/
|
||||
MongoShell *openShell(MongoCollection *collection,const QString &filePathToSave=QString());
|
||||
void openShell(MongoCollection *collection, const QString &filePathToSave = QString());
|
||||
|
||||
MongoShell *openShell(MongoServer *server, const QString &script, const std::string &dbName = std::string(),
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &file = QString());
|
||||
void openShell(MongoServer *server, const QString &script, const std::string &dbName = std::string(),
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &file = QString());
|
||||
|
||||
MongoShell *openShell(MongoDatabase *database, const QString &script,
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &filePathToSave = QString());
|
||||
void openShell(MongoDatabase *database, const QString &script,
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(),
|
||||
const QString &filePathToSave = QString());
|
||||
|
||||
MongoShell *openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo);
|
||||
MongoServersContainerType getServers() const {return _servers; };
|
||||
/**
|
||||
* @brief Open new shell using explorer's MongoServer (ExplorerServerTreeItem's _server)
|
||||
*/
|
||||
void openShell(MongoServer* server, ConnectionSettings* connSettings, const ScriptInfo &scriptInfo);
|
||||
|
||||
auto const& getServers() const { return _servers; };
|
||||
|
||||
/**
|
||||
* @brief Closes MongoShell and frees all resources, owned by specified MongoShell.
|
||||
@@ -78,24 +82,43 @@ namespace Robomongo
|
||||
*/
|
||||
void closeShell(MongoShell *shell);
|
||||
|
||||
void fireConnectionFailedEvent(int serverHandle, ConnectionType type, std::string errormsg,
|
||||
ConnectionFailedEvent::Reason reason);
|
||||
|
||||
int getLastServerHandle() const { return _lastServerHandle; };
|
||||
|
||||
public Q_SLOTS:
|
||||
void handle(EstablishSshConnectionResponse *event);
|
||||
void handle(ListenSshConnectionResponse *event);
|
||||
void handle(LogEvent *event);
|
||||
|
||||
private:
|
||||
MongoServer* continueOpenServer(ConnectionSettings *connection, bool visible, int localport = 0);
|
||||
std::unique_ptr<MongoServer> openServerInternal(ConnectionSettings* connSettings, ConnectionType type);
|
||||
|
||||
std::unique_ptr<MongoServer>
|
||||
continueOpenServer(int serverHandle, ConnectionSettings* connSettings, ConnectionType type, int localport = 0);
|
||||
|
||||
/**
|
||||
* @brief Create prompt dialog to enter SSL PEM key passphrase and save passphrase into SSL settings
|
||||
* @param connection Pointer to active connection settings
|
||||
* @return true on success, false otherwise
|
||||
*/
|
||||
bool askSslPassphrasePromptDialog(ConnectionSettings *connSettings) const;
|
||||
|
||||
/**
|
||||
* MongoServers, owned by this App.
|
||||
*/
|
||||
MongoServersContainerType _servers;
|
||||
std::vector<std::unique_ptr<MongoServer>> _servers;
|
||||
|
||||
/**
|
||||
* MongoShells, owned by this App.
|
||||
*/
|
||||
MongoShellsContainerType _shells;
|
||||
std::vector<std::unique_ptr<MongoShell>> _shells;
|
||||
|
||||
EventBus *const _bus;
|
||||
|
||||
// Increase monotonically when new MongoServer is created
|
||||
// Never decreases.
|
||||
int _lastServerHandle;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
struct AggrInfo
|
||||
{
|
||||
AggrInfo() {}
|
||||
|
||||
AggrInfo(const std::string& collectionName, int skip, int batchSize,
|
||||
mongo::BSONObj const& pipeline, mongo::BSONObj const& options, int resultIndex) :
|
||||
collectionName(collectionName), skip(skip), batchSize(batchSize), pipeline(pipeline),
|
||||
options(options), isValid(true), resultIndex(resultIndex)
|
||||
{}
|
||||
|
||||
std::string collectionName = "";
|
||||
int skip = 0;
|
||||
int batchSize = 0;
|
||||
mongo::BSONObj pipeline;
|
||||
mongo::BSONObj options;
|
||||
bool isValid = false;
|
||||
int resultIndex = -1;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "MongoCollectionInfo.h"
|
||||
#include "robomongo/core/utils/BsonUtils.h"
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "robomongo/core/mongodb/MongoWorker.h"
|
||||
#include "robomongo/core/AppRegistry.h"
|
||||
#include "robomongo/core/EventBus.h"
|
||||
#include "robomongo/core/utils/Logger.h"
|
||||
#include "robomongo/utils/common.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
@@ -15,6 +17,13 @@ namespace Robomongo
|
||||
R_REGISTER_EVENT(MongoDatabaseFunctionsLoadingEvent)
|
||||
R_REGISTER_EVENT(MongoDatabaseCollectionsLoadingEvent)
|
||||
|
||||
const std::string MongoDatabase::StorageEngineType::WIRED_TIGER = "wiredTiger";
|
||||
const std::string MongoDatabase::StorageEngineType::MMAPV1 = "mmapv1";
|
||||
|
||||
const float MongoDatabase::DBVersion::MONGODB_2_6 = 2.6f;
|
||||
const float MongoDatabase::DBVersion::MONGODB_3_0 = 3.0f;
|
||||
const float MongoDatabase::DBVersion::MONGODB_3_2 = 3.2f;
|
||||
|
||||
MongoDatabase::MongoDatabase(MongoServer *server, const std::string &name) :
|
||||
QObject(),
|
||||
_system(name == "admin" || name == "local"),
|
||||
@@ -30,113 +39,144 @@ namespace Robomongo
|
||||
void MongoDatabase::loadCollections()
|
||||
{
|
||||
_bus->publish(new MongoDatabaseCollectionsLoadingEvent(this));
|
||||
_bus->send(_server->client(), new LoadCollectionNamesRequest(this, _name));
|
||||
_bus->send(_server->worker(), new LoadCollectionNamesRequest(this, _name));
|
||||
}
|
||||
|
||||
void MongoDatabase::loadUsers()
|
||||
{
|
||||
_bus->publish(new MongoDatabaseUsersLoadingEvent(this));
|
||||
_bus->send(_server->client(), new LoadUsersRequest(this, _name));
|
||||
_bus->send(_server->worker(), new LoadUsersRequest(this, _name));
|
||||
}
|
||||
|
||||
void MongoDatabase::loadFunctions()
|
||||
{
|
||||
_bus->publish(new MongoDatabaseFunctionsLoadingEvent(this));
|
||||
_bus->send(_server->client(), new LoadFunctionsRequest(this, _name));
|
||||
_bus->send(_server->worker(), new LoadFunctionsRequest(this, _name));
|
||||
}
|
||||
void MongoDatabase::createCollection(const std::string &collection)
|
||||
|
||||
void MongoDatabase::createCollection(const std::string &collection, long long size, bool capped, int maxDocNum, const mongo::BSONObj& extraOptions)
|
||||
{
|
||||
_bus->send(_server->client(), new CreateCollectionRequest(this, MongoNamespace(_name, collection)));
|
||||
_bus->send(_server->worker(),
|
||||
new CreateCollectionRequest(this, MongoNamespace(_name, collection), extraOptions, size, capped, maxDocNum));
|
||||
}
|
||||
|
||||
void MongoDatabase::dropCollection(const std::string &collection)
|
||||
{
|
||||
_bus->send(_server->client(), new DropCollectionRequest(this, MongoNamespace(_name, collection)));
|
||||
_bus->send(_server->worker(), new DropCollectionRequest(this, MongoNamespace(_name, collection)));
|
||||
}
|
||||
|
||||
void MongoDatabase::renameCollection(const std::string &collection, const std::string &newCollection)
|
||||
{
|
||||
_bus->send(_server->client(), new RenameCollectionRequest(this, MongoNamespace(_name, collection), newCollection));
|
||||
_bus->send(_server->worker(), new RenameCollectionRequest(this, MongoNamespace(_name, collection),
|
||||
newCollection));
|
||||
}
|
||||
|
||||
void MongoDatabase::duplicateCollection(const std::string &collection, const std::string &newCollection)
|
||||
{
|
||||
_bus->send(_server->client(), new DuplicateCollectionRequest(this, MongoNamespace(_name, collection), newCollection));
|
||||
_bus->send(_server->worker(), new DuplicateCollectionRequest(this, MongoNamespace(_name, collection), newCollection));
|
||||
}
|
||||
|
||||
void MongoDatabase::copyCollection(MongoServer *server, const std::string &sourceDatabase, const std::string &collection)
|
||||
{
|
||||
_bus->send(_server->client(), new CopyCollectionToDiffServerRequest(this, server->client(), sourceDatabase, collection, _name));
|
||||
_bus->send(_server->worker(), new CopyCollectionToDiffServerRequest(this, server->worker(), sourceDatabase, collection, _name));
|
||||
}
|
||||
|
||||
void MongoDatabase::createUser(const MongoUser &user, bool overwrite)
|
||||
void MongoDatabase::createUser(const MongoUser &user)
|
||||
{
|
||||
_bus->send(_server->client(), new CreateUserRequest(this, _name, user, overwrite));
|
||||
_bus->send(_server->worker(), new CreateUserRequest(this, _name, user));
|
||||
}
|
||||
|
||||
void MongoDatabase::dropUser(const mongo::OID &id)
|
||||
void MongoDatabase::dropUser(std::string const& userName)
|
||||
{
|
||||
_bus->send(_server->client(), new DropUserRequest(this, _name, id));
|
||||
_bus->send(_server->worker(), new DropUserRequest(this, _name, userName));
|
||||
}
|
||||
|
||||
void MongoDatabase::createFunction(const MongoFunction &fun)
|
||||
{
|
||||
_bus->send(_server->client(), new CreateFunctionRequest(this, _name, fun));
|
||||
_bus->send(_server->worker(), new CreateFunctionRequest(this, _name, _server->version(), fun));
|
||||
}
|
||||
|
||||
void MongoDatabase::updateFunction(const std::string &name, const MongoFunction &fun)
|
||||
{
|
||||
_bus->send(_server->client(), new CreateFunctionRequest(this, _name, fun, name));
|
||||
_bus->send(_server->worker(), new CreateFunctionRequest(this, _name, _server->version(), fun, name));
|
||||
}
|
||||
|
||||
void MongoDatabase::dropFunction(const std::string &name)
|
||||
{
|
||||
_bus->send(_server->client(), new DropFunctionRequest(this, _name, name));
|
||||
_bus->send(_server->worker(), new DropFunctionRequest(this, _name, _server->version(), name));
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(LoadCollectionNamesResponse *loaded)
|
||||
void MongoDatabase::handle(LoadCollectionNamesResponse *event)
|
||||
{
|
||||
if (loaded->isError()) {
|
||||
_bus->publish(new MongoDatabaseCollectionListLoadedEvent(this, loaded->error()));
|
||||
if (event->isError()) {
|
||||
_bus->publish(new MongoDatabaseCollectionListLoadedEvent(this, event->error()));
|
||||
genericEventErrorHandler(event, "Failed to refresh 'Collections'.", _bus, this);
|
||||
return;
|
||||
}
|
||||
|
||||
clearCollections();
|
||||
const std::vector<MongoCollectionInfo> &colectionsInfos = loaded->collectionInfos();
|
||||
for (std::vector<MongoCollectionInfo>::const_iterator it = colectionsInfos.begin(); it != colectionsInfos.end(); ++it) {
|
||||
const MongoCollectionInfo &info = *it;
|
||||
MongoCollection *collection = new MongoCollection(this, info);
|
||||
addCollection(collection);
|
||||
}
|
||||
|
||||
for (auto const& collectionInfo : event->collectionInfos())
|
||||
addCollection(new MongoCollection(this, collectionInfo));
|
||||
|
||||
_bus->publish(new MongoDatabaseCollectionListLoadedEvent(this, _collections));
|
||||
LOG_MSG("'Collections' refreshed.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(CreateFunctionResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to create function \'" + event->functionName + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadFunctions();
|
||||
LOG_MSG("Function \'" + event->functionName + "\' created.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(CreateUserResponse *event)
|
||||
{
|
||||
if (event->isError())
|
||||
return;
|
||||
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to create user \'" + event->userName + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadUsers();
|
||||
LOG_MSG("User \'" + event->userName + "\' created.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(LoadUsersResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
_bus->publish(new MongoDatabaseUsersLoadedEvent(this, event->error()));
|
||||
|
||||
if (_server->connectionRecord()->isReplicaSet()) // replica set
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
|
||||
genericEventErrorHandler(event, "Failed to refresh 'Users'.", _bus, this);
|
||||
return;
|
||||
}
|
||||
|
||||
_bus->publish(new MongoDatabaseUsersLoadedEvent(this, this, event->users()));
|
||||
LOG_MSG("'Users' refreshed.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(LoadFunctionsResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
_bus->publish(new MongoDatabaseFunctionsLoadedEvent(this, event->error()));
|
||||
|
||||
if (_server->connectionRecord()->isReplicaSet()) // replica set
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
|
||||
genericEventErrorHandler(event, "Failed to refresh 'Functions'.", _bus, this);
|
||||
return;
|
||||
}
|
||||
|
||||
_bus->publish(new MongoDatabaseFunctionsLoadedEvent(this, this, event->functions()));
|
||||
LOG_MSG("'Functions' refreshed.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
void MongoDatabase::clearCollections()
|
||||
@@ -149,4 +189,92 @@ namespace Robomongo
|
||||
{
|
||||
_collections.push_back(collection);
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(CreateCollectionResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to create collection \'" + event->collection + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadCollections();
|
||||
LOG_MSG("Collection \'" + event->collection + "\' created.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(DropCollectionResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to drop collection \'" + event->collection + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadCollections();
|
||||
LOG_MSG("Collection \'" + event->collection + "\' dropped", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MongoDatabase::handle(DropFunctionResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to remove function \'" + event->functionName + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadFunctions();
|
||||
LOG_MSG("Function \'" + event->functionName + "\' removed", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(DropUserResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to drop user \'" + event->username + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadUsers();
|
||||
LOG_MSG("User \'" + event->username + "\' dropped", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(RenameCollectionResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to rename collection.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadCollections();
|
||||
LOG_MSG("Collection \'" + event->oldCollection + "\' renamed to \'" +
|
||||
event->newCollection +"\'." , mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(DuplicateCollectionResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
genericEventErrorHandler(event, "Failed to duplicate collection \'" + event->sourceCollection + "\'.",
|
||||
_bus, this);
|
||||
}
|
||||
else {
|
||||
loadCollections();
|
||||
LOG_MSG("Collection \'" + event->sourceCollection + "\' duplicated as \'" +
|
||||
event->duplicateCollection + "\'.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoDatabase::handleIfReplicaSetUnreachable(Event *event)
|
||||
{
|
||||
if (!_server->connectionRecord()->isReplicaSet())
|
||||
return;
|
||||
|
||||
if (EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
auto refreshEvent = ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo());
|
||||
_server->handle(&refreshEvent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,25 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Database storage engine type
|
||||
*/
|
||||
struct StorageEngineType
|
||||
{
|
||||
static const std::string WIRED_TIGER;
|
||||
static const std::string MMAPV1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MongoDB version
|
||||
*/
|
||||
struct DBVersion
|
||||
{
|
||||
static const float MONGODB_2_6;
|
||||
static const float MONGODB_3_0;
|
||||
static const float MONGODB_3_2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MongoDatabase
|
||||
* @param server: pointer to parent MongoServer
|
||||
@@ -37,14 +56,14 @@ namespace Robomongo
|
||||
|
||||
void loadFunctions();
|
||||
|
||||
void createCollection(const std::string &collection);
|
||||
void createCollection(const std::string &collection, long long size, bool capped, int maxDocNum, const mongo::BSONObj& extraOptions);
|
||||
void dropCollection(const std::string &collection);
|
||||
void renameCollection(const std::string &collection, const std::string &newCollection);
|
||||
void duplicateCollection(const std::string &collection, const std::string &newCollection);
|
||||
void copyCollection(MongoServer *server, const std::string &sourceDatabase, const std::string &collection);
|
||||
|
||||
void createUser(const MongoUser &user, bool overwrite);
|
||||
void dropUser(const mongo::OID &id);
|
||||
void createUser(const MongoUser &user);
|
||||
void dropUser(std::string const& userName);
|
||||
|
||||
void createFunction(const MongoFunction &fun);
|
||||
void updateFunction(const std::string &name, const MongoFunction &fun);
|
||||
@@ -64,11 +83,19 @@ namespace Robomongo
|
||||
void handle(LoadCollectionNamesResponse *event);
|
||||
void handle(LoadUsersResponse *event);
|
||||
void handle(LoadFunctionsResponse *event);
|
||||
void handle(CreateFunctionResponse *event);
|
||||
void handle(CreateUserResponse *event);
|
||||
void handle(CreateCollectionResponse *event);
|
||||
void handle(DropCollectionResponse *event);
|
||||
void handle(DropFunctionResponse *event);
|
||||
void handle(DropUserResponse *event);
|
||||
void handle(RenameCollectionResponse *event);
|
||||
void handle(DuplicateCollectionResponse *event);
|
||||
|
||||
private:
|
||||
void clearCollections();
|
||||
void addCollection(MongoCollection *collection);
|
||||
void handleIfReplicaSetUnreachable(Event *event);
|
||||
|
||||
private:
|
||||
MongoServer *_server;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "robomongo/core/domain/MongoDocument.h"
|
||||
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
#include "robomongo/core/settings/SettingsManager.h"
|
||||
#include "robomongo/core/AppRegistry.h"
|
||||
#include "robomongo/core/utils/BsonUtils.h"
|
||||
@@ -38,7 +38,7 @@ namespace Robomongo
|
||||
std::vector<MongoDocumentPtr> MongoDocument::fromBsonObj(const std::vector<mongo::BSONObj> &bsonObjs)
|
||||
{
|
||||
std::vector<MongoDocumentPtr> list;
|
||||
for (std::vector<mongo::BSONObj>::const_iterator it=bsonObjs.begin(); it!=bsonObjs.end(); ++it) {
|
||||
for (std::vector<mongo::BSONObj>::const_iterator it = bsonObjs.begin(); it != bsonObjs.end(); ++it) {
|
||||
list.push_back(fromBsonObj(*it));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "robomongo/core/domain/MongoFunction.h"
|
||||
#include "robomongo/core/utils/BsonUtils.h"
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
MongoFunction::MongoFunction(const mongo::BSONObj &obj)
|
||||
{
|
||||
_name = BsonUtils::getField<mongo::String>(obj,"_id");
|
||||
_name = BsonUtils::getField<mongo::String>(obj, "_id");
|
||||
_code = obj.getField("value")._asCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "robomongo/core/domain/MongoQueryInfo.h"
|
||||
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
@@ -9,8 +9,8 @@ namespace Robomongo
|
||||
std::string prepareServerAddress(const std::string &address)
|
||||
{
|
||||
size_t pos = address.find_first_of("{");
|
||||
if (pos!=std::string::npos){
|
||||
return address.substr(0,pos);
|
||||
if (pos != std::string::npos) {
|
||||
return address.substr(0, pos);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Robomongo
|
||||
|
||||
CollectionInfo::CollectionInfo(const std::string &server, const std::string &database, const std::string &collection)
|
||||
:_serverAddress(server),
|
||||
_ns(database,collection)
|
||||
_ns(database, collection)
|
||||
{}
|
||||
|
||||
bool CollectionInfo::isValid() const
|
||||
|
||||
@@ -4,55 +4,86 @@
|
||||
#include "robomongo/core/settings/ConnectionSettings.h"
|
||||
#include "robomongo/core/settings/SshSettings.h"
|
||||
#include "robomongo/core/settings/SettingsManager.h"
|
||||
#include "robomongo/core/settings/ReplicaSetSettings.h"
|
||||
#include "robomongo/core/mongodb/MongoWorker.h"
|
||||
#include "robomongo/core/mongodb/SshTunnelWorker.h"
|
||||
#include "robomongo/core/AppRegistry.h"
|
||||
#include "robomongo/core/domain/App.h"
|
||||
#include "robomongo/core/EventBus.h"
|
||||
#include "robomongo/core/events/MongoEventsInfo.h"
|
||||
#include "robomongo/core/utils/Logger.h"
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
#include "robomongo/gui/MainWindow.h"
|
||||
#include "robomongo/utils/common.h"
|
||||
#include "robomongo/utils/StringOperations.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace Robomongo {
|
||||
R_REGISTER_EVENT(MongoServerLoadingDatabasesEvent)
|
||||
|
||||
MongoServer::MongoServer(ConnectionSettings *settings, bool visible) : QObject(),
|
||||
MongoServer::MongoServer(int handle, ConnectionSettings *settings, ConnectionType connectionType)
|
||||
: QObject(),
|
||||
_version(0.0f),
|
||||
_visible(visible),
|
||||
_client(NULL),
|
||||
_connectionType(connectionType),
|
||||
_worker(nullptr),
|
||||
_isConnected(false),
|
||||
_settings(settings),
|
||||
_bus(AppRegistry::instance().bus()) { }
|
||||
_connSettings(settings),
|
||||
_handle(handle),
|
||||
_bus(AppRegistry::instance().bus()),
|
||||
_app(AppRegistry::instance().app()),
|
||||
_replicaSetInfo(nullptr)
|
||||
{}
|
||||
|
||||
bool MongoServer::isConnected() const {
|
||||
return _isConnected;
|
||||
}
|
||||
|
||||
ConnectionSettings *MongoServer::connectionRecord() const {
|
||||
return _settings;
|
||||
return _connSettings.get();
|
||||
}
|
||||
|
||||
MongoServer::~MongoServer() {
|
||||
clearDatabases();
|
||||
|
||||
if (_client != NULL) {
|
||||
_client->stopAndDelete();
|
||||
if (_worker) {
|
||||
_worker->stopAndDelete();
|
||||
}
|
||||
|
||||
// MongoWorker "_client" does not deleted here, because it is now owned by
|
||||
// MongoWorker "_worker" is not deleted here, because it is now owned by
|
||||
// another thread (call to moveToThread() made in MongoWorker constructor).
|
||||
// It will be deleted by this thread by means of "deleteLater()", which
|
||||
// is also specified in MongoWorker constructor.
|
||||
|
||||
delete _settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to connect to MongoDB server.
|
||||
* @throws MongoException, if fails
|
||||
*/
|
||||
void MongoServer::tryConnect() {
|
||||
_bus->send(_client, new EstablishConnectionRequest(this));
|
||||
void MongoServer::tryConnect()
|
||||
{
|
||||
_bus->send(_worker, new EstablishConnectionRequest(this, _connectionType, _connSettings->uuid().toStdString()));
|
||||
}
|
||||
|
||||
QStringList MongoServer::getDatabasesNames() const {
|
||||
void MongoServer::tryRefresh()
|
||||
{
|
||||
_bus->send(_worker, new EstablishConnectionRequest(this, ConnectionRefresh, _connSettings->uuid().toStdString()));
|
||||
}
|
||||
|
||||
void MongoServer::tryRefreshReplicaSetConnection()
|
||||
{
|
||||
_bus->send(_worker, new EstablishConnectionRequest(this, ConnectionRefresh, _connSettings->uuid().toStdString()));
|
||||
}
|
||||
|
||||
void MongoServer::tryRefreshReplicaSetFolder(bool expanded, bool showLoading /*= true*/)
|
||||
{
|
||||
if (!_connSettings->isReplicaSet())
|
||||
return;
|
||||
|
||||
if (showLoading)
|
||||
_bus->publish(new ReplicaSetFolderLoading(this));
|
||||
|
||||
_bus->send(_worker, new RefreshReplicaSetFolderRequest(this, expanded));
|
||||
}
|
||||
|
||||
QStringList MongoServer::getDatabasesNames() const
|
||||
{
|
||||
QStringList result;
|
||||
for (QList<MongoDatabase *>::const_iterator it = _databases.begin(); it != _databases.end(); ++it) {
|
||||
MongoDatabase *datab = *it;
|
||||
@@ -61,11 +92,17 @@ namespace Robomongo {
|
||||
return result;
|
||||
}
|
||||
|
||||
void MongoServer::createDatabase(const std::string &dbName) {
|
||||
_bus->send(_client,new CreateDatabaseRequest(this, dbName));
|
||||
void MongoServer::addDatabase(MongoDatabase *database) {
|
||||
_databases.append(database);
|
||||
}
|
||||
|
||||
MongoDatabase *MongoServer::findDatabaseByName(const std::string &dbName) const {
|
||||
void MongoServer::createDatabase(const std::string &dbName)
|
||||
{
|
||||
_bus->send(_worker, new CreateDatabaseRequest(this, dbName));
|
||||
}
|
||||
|
||||
MongoDatabase *MongoServer::findDatabaseByName(const std::string &dbName) const
|
||||
{
|
||||
for (QList<MongoDatabase *>::const_iterator it = _databases.begin(); it != _databases.end(); ++it) {
|
||||
MongoDatabase *datab = *it;
|
||||
if (datab->name() == dbName) {
|
||||
@@ -76,7 +113,7 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
void MongoServer::dropDatabase(const std::string &dbName) {
|
||||
_bus->send(_client,new DropDatabaseRequest(this, dbName));
|
||||
_bus->send(_worker, new DropDatabaseRequest(this, dbName));
|
||||
}
|
||||
|
||||
void MongoServer::insertDocuments(const std::vector<mongo::BSONObj> &objCont,
|
||||
@@ -87,94 +124,379 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
void MongoServer::insertDocument(const mongo::BSONObj &obj, const MongoNamespace &ns) {
|
||||
_bus->send(_client,new InsertDocumentRequest(this, obj, ns));
|
||||
_bus->send(_worker, new InsertDocumentRequest(this, obj, ns));
|
||||
}
|
||||
|
||||
void MongoServer::saveDocuments(const std::vector<mongo::BSONObj> &objCont, const MongoNamespace &ns) {
|
||||
for (std::vector<mongo::BSONObj>::const_iterator it = objCont.begin(); it != objCont.end(); it++) {
|
||||
saveDocument(*it,ns);
|
||||
saveDocument(*it, ns);
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::saveDocument(const mongo::BSONObj &obj, const MongoNamespace &ns) {
|
||||
_bus->send(_client, new InsertDocumentRequest(this, obj, ns, true));
|
||||
_bus->send(_worker, new InsertDocumentRequest(this, obj, ns, true));
|
||||
}
|
||||
|
||||
void MongoServer::removeDocuments(mongo::Query query, const MongoNamespace &ns, bool justOne) {
|
||||
_bus->send(_client, new RemoveDocumentRequest(this, query, ns, justOne));
|
||||
void MongoServer::removeDocuments(mongo::Query query, const MongoNamespace &ns,
|
||||
RemoveDocumentCount removeCount, int index)
|
||||
{
|
||||
_bus->send(_worker, new RemoveDocumentRequest(this, query, ns, removeCount, index));
|
||||
}
|
||||
|
||||
void MongoServer::loadDatabases() {
|
||||
void MongoServer::loadDatabases()
|
||||
{
|
||||
_bus->publish(new MongoServerLoadingDatabasesEvent(this));
|
||||
_bus->send(_client, new LoadDatabaseNamesRequest(this));
|
||||
if (_connSettings->isReplicaSet()) {
|
||||
tryRefreshReplicaSetConnection();
|
||||
}
|
||||
else { // single server
|
||||
_bus->send(_worker, new LoadDatabaseNamesRequest(this));
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::clearDatabases() {
|
||||
void MongoServer::clearDatabases()
|
||||
{
|
||||
qDeleteAll(_databases);
|
||||
_databases.clear();
|
||||
}
|
||||
|
||||
void MongoServer::addDatabase(MongoDatabase *database) {
|
||||
_databases.append(database);
|
||||
}
|
||||
void MongoServer::handle(EstablishConnectionResponse *event)
|
||||
{
|
||||
_connectionType = event->connectionType;
|
||||
|
||||
void MongoServer::handle(EstablishConnectionResponse *event) {
|
||||
// In any case, replica set info must be updated, there might be reachable secondary(ies).
|
||||
// Also cached set name must be updated or cleared for failed connections.
|
||||
updateReplicaSetSettings(event);
|
||||
|
||||
// --- Connection Failed
|
||||
if (event->isError()) {
|
||||
_isConnected = false;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Cannot connect to the MongoDB at " << connectionRecord()->getFullAddress()
|
||||
<< ".\n\nError:\n" << event->error().errorMessage();
|
||||
|
||||
_bus->publish(new ConnectionFailedEvent(this, ss.str()));
|
||||
handleConnectionFailure(event);
|
||||
return;
|
||||
}
|
||||
|
||||
const ConnectionInfo &info = event->info();
|
||||
// --- Connections Successful
|
||||
// Save various information after successful connection
|
||||
const ConnectionInfo &info = event->info;
|
||||
_version = info._version;
|
||||
_storageEngineType = info._storageEngineType;
|
||||
_isConnected = true;
|
||||
|
||||
// Do nothing if this is not "visible" connection
|
||||
if (!_visible) {
|
||||
return;
|
||||
// ConnectionRefresh is used just to update connection view (_version, _storageEngineType, _repPrimary etc..)
|
||||
// So we return here after updating(refreshing) information related to connection view.
|
||||
if (ConnectionRefresh == event->connectionType) {
|
||||
if (_connSettings->isReplicaSet()) {
|
||||
// If it is replica set connection, do not return yet.
|
||||
LOG_MSG("Replica set refreshed. [" + _connSettings->connectionName() + ']',
|
||||
mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
else { // single server
|
||||
LOG_MSG("Server refreshed.", mongo::logger::LogSeverity::Info());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_bus->publish(new ConnectionEstablishedEvent(this));
|
||||
clearDatabases();
|
||||
for(std::vector<std::string>::const_iterator it = info._databases.begin(); it != info._databases.end(); ++it) {
|
||||
const std::string &name = *it;
|
||||
MongoDatabase *db = new MongoDatabase(this, name);
|
||||
addDatabase(db);
|
||||
// Only for single servers
|
||||
if (!_connSettings->isReplicaSet()) {
|
||||
_bus->publish(new ConnectionEstablishedEvent(this, _connectionType, info));
|
||||
// Do nothing if this is not a "primary" connection
|
||||
if (ConnectionPrimary != _connectionType)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConnectionPrimary == _connectionType)
|
||||
LOG_MSG("Establish connection successful. Connection: " + _connSettings->connectionName(),
|
||||
mongo::logger::LogSeverity::Info());
|
||||
|
||||
clearDatabases();
|
||||
for (auto const& dbname : info._databases) {
|
||||
MongoDatabase *db = new MongoDatabase(this, dbname);
|
||||
addDatabase(db); // todo: serverClones for replica sets should not do this
|
||||
}
|
||||
|
||||
if (_connSettings->isReplicaSet()) {
|
||||
_bus->publish(new ConnectionEstablishedEvent(this, event->connectionType, info));
|
||||
// In order to do first connection much faster, time consuming refresh
|
||||
// "repSetMonitor->startOrContinueRefresh(). refreshAll()" is being requested after
|
||||
// successful connection.
|
||||
if (ConnectionPrimary == event->connectionType)
|
||||
_bus->send(_worker, new RefreshReplicaSetFolderRequest(this, false));
|
||||
}
|
||||
|
||||
// Save connected db version if not saved before and if this is primary connection.
|
||||
QString const versionStr = QString::fromStdString(info._dbVersionStr);
|
||||
auto const& settingsManager = AppRegistry::instance().settingsManager();
|
||||
if (ConnectionPrimary == _connectionType &&
|
||||
!settingsManager->dbVersionsConnected().contains(versionStr)) {
|
||||
settingsManager->addDbVersionConnected(versionStr);
|
||||
settingsManager->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MongoServer::handle(LoadDatabaseNamesResponse *event) {
|
||||
void MongoServer::handle(RefreshReplicaSetFolderResponse *event)
|
||||
{
|
||||
handleReplicaSetRefreshEvents(event->isError(), event->error(), event->replicaSet, event->expanded);
|
||||
}
|
||||
|
||||
void MongoServer::handle(LoadDatabaseNamesResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
_bus->publish(new DatabaseListLoadedEvent(this, event->error()));
|
||||
return;
|
||||
}
|
||||
|
||||
clearDatabases();
|
||||
for(std::vector<std::string>::iterator it = event->databaseNames.begin(); it != event->databaseNames.end(); ++it) {
|
||||
const std::string &name = *it;
|
||||
MongoDatabase *db = new MongoDatabase(this, name);
|
||||
addDatabase(db);
|
||||
}
|
||||
|
||||
for (auto const& dbname : event->databaseNames)
|
||||
addDatabase(new MongoDatabase(this, dbname));
|
||||
|
||||
_bus->publish(new DatabaseListLoadedEvent(this, _databases));
|
||||
LOG_MSG("Database list refreshed. Connection: " + _connSettings->connectionName(),
|
||||
mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
void MongoServer::handle(InsertDocumentResponse *event) {
|
||||
_bus->publish(new InsertDocumentResponse(event->sender(), event->error()));
|
||||
void MongoServer::handle(InsertDocumentResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
hideProgressBar();
|
||||
if (_connSettings->isReplicaSet()) {
|
||||
if (ConnectionPrimary == _connectionType) { // Insert document from explorer context menu
|
||||
if (EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
auto refreshEvent = ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo());
|
||||
handle(&refreshEvent);
|
||||
}
|
||||
}
|
||||
else { // Insert document from tab results window (Notifier, OutputWindow widget)
|
||||
_bus->publish(new InsertDocumentResponse(this, event->error()));
|
||||
}
|
||||
}
|
||||
genericEventErrorHandler(event, "Failed to insert document.", _bus, this);
|
||||
}
|
||||
else {
|
||||
_bus->publish(new InsertDocumentResponse(this, event->error()));
|
||||
LOG_MSG("Document inserted.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::handle(RemoveDocumentResponse *event) {
|
||||
_bus->publish(new RemoveDocumentResponse(event->sender(), event->error()));
|
||||
void MongoServer::handle(RemoveDocumentResponse *event)
|
||||
{
|
||||
if (event->removeCount == RemoveDocumentCount::MULTI && event->index > 0)
|
||||
return;
|
||||
|
||||
std::string subStr;
|
||||
switch (event->removeCount) {
|
||||
case RemoveDocumentCount::ONE: subStr = "document."; break;
|
||||
case RemoveDocumentCount::MULTI: subStr = "documents."; break;
|
||||
case RemoveDocumentCount::ALL: subStr = "all documents."; break;
|
||||
default: subStr = "(logic error)."; break;
|
||||
}
|
||||
|
||||
if (event->isError()) {
|
||||
hideProgressBar();
|
||||
if (_connSettings->isReplicaSet() &&
|
||||
EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
auto refreshEvent = ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo());
|
||||
handle(&refreshEvent);
|
||||
}
|
||||
genericEventErrorHandler(event, "Failed to remove " + subStr, _bus, this);
|
||||
}
|
||||
else { // success
|
||||
_bus->publish(new RemoveDocumentResponse(this, event->error(), event->removeCount, event->index));
|
||||
LOG_MSG("Removed " + subStr, mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::runWorkerThread() {
|
||||
_client = new MongoWorker(_settings->clone(),
|
||||
AppRegistry::instance().settingsManager()->loadMongoRcJs(),
|
||||
AppRegistry::instance().settingsManager()->batchSize());
|
||||
void MongoServer::runWorkerThread()
|
||||
{
|
||||
_worker = new MongoWorker(_connSettings->clone(),
|
||||
AppRegistry::instance().settingsManager()->loadMongoRcJs(),
|
||||
AppRegistry::instance().settingsManager()->batchSize(),
|
||||
AppRegistry::instance().settingsManager()->mongoTimeoutSec(),
|
||||
AppRegistry::instance().settingsManager()->shellTimeoutSec());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::handle(CreateDatabaseResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
if (_connSettings->isReplicaSet() &&
|
||||
EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
auto refreshEvent = ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo());
|
||||
handle(&refreshEvent);
|
||||
}
|
||||
genericEventErrorHandler(event, "Failed to create database \'" + event->database + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadDatabases();
|
||||
LOG_MSG("Database \'" + event->database + "\' created.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::handle(DropDatabaseResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
if (_connSettings->isReplicaSet() &&
|
||||
EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
auto refreshEvent = ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo());
|
||||
handle(&refreshEvent);
|
||||
}
|
||||
genericEventErrorHandler(event, "Failed to drop database \'" + event->database + "\'.", _bus, this);
|
||||
}
|
||||
else {
|
||||
loadDatabases();
|
||||
LOG_MSG("Database \'" + event->database + "\' dropped.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::handle(ReplicaSetRefreshed *event)
|
||||
{
|
||||
handleReplicaSetRefreshEvents(event->isError(), event->error(), event->replicaSet, false);
|
||||
}
|
||||
|
||||
void MongoServer::changeWorkerShellTimeout(int newTimeout)
|
||||
{
|
||||
_worker->changeTimeout(newTimeout);
|
||||
}
|
||||
|
||||
void MongoServer::handleReplicaSetRefreshEvents(bool isError, EventError eventError,
|
||||
ReplicaSet const& replicaSet, bool expanded)
|
||||
{
|
||||
if (isError) { // Primary is unreachable
|
||||
_replicaSetInfo.reset(new ReplicaSet(replicaSet));
|
||||
LOG_MSG("Replica set folder refreshed with error. " + eventError.errorMessage() +
|
||||
". Connection: " + _connSettings->connectionName(), mongo::logger::LogSeverity::Error());
|
||||
_bus->publish(new ReplicaSetFolderRefreshed(this, eventError, true));
|
||||
return;
|
||||
}
|
||||
|
||||
// Primary is reachable
|
||||
// Update replica set settings and mongo server _replicaSetInfo
|
||||
_replicaSetInfo.reset(new ReplicaSet(replicaSet));
|
||||
_connSettings->setServerHost(_replicaSetInfo->primary.host());
|
||||
_connSettings->setServerPort(_replicaSetInfo->primary.port());
|
||||
_connSettings->replicaSetSettings()->setCachedSetName(
|
||||
_connSettings->replicaSetSettings()->setNameUserEntered().empty() ? _replicaSetInfo->setName : "");
|
||||
|
||||
LOG_MSG("Replica set folder refreshed. Connection: " + _connSettings->connectionName(),
|
||||
mongo::logger::LogSeverity::Info());
|
||||
_bus->publish(new ReplicaSetFolderRefreshed(this, expanded));
|
||||
}
|
||||
|
||||
void MongoServer::updateReplicaSetSettings(EstablishConnectionResponse* event)
|
||||
{
|
||||
if (!_connSettings->isReplicaSet())
|
||||
return;
|
||||
|
||||
_replicaSetInfo.reset(new ReplicaSet(event->replicaSet));
|
||||
_connSettings->setServerHost(_replicaSetInfo->primary.host());
|
||||
_connSettings->setServerPort(_replicaSetInfo->primary.port());
|
||||
_connSettings->replicaSetSettings()->setCachedSetName(
|
||||
_connSettings->replicaSetSettings()->setNameUserEntered().empty() ? _replicaSetInfo->setName : "");
|
||||
|
||||
if (_connSettings->replicaSetSettings()->setNameUserEntered().empty()) {
|
||||
// Cache replica set name for 2 times faster first connection
|
||||
if (ConnectionPrimary == _connectionType) {
|
||||
ConnectionSettings* originalConnSettings = AppRegistry::instance().settingsManager()
|
||||
->getConnectionSettingsByUuid(event->info._uuid);
|
||||
if (originalConnSettings) {
|
||||
auto setName = event->isError() ? "" : _replicaSetInfo->setName;
|
||||
originalConnSettings->replicaSetSettings()->setCachedSetName(setName);
|
||||
AppRegistry::instance().settingsManager()->save();
|
||||
LOG_MSG("Replica set name cached as \"" + setName + "\".", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
else
|
||||
LOG_MSG("Failed to cache the replica set name.", mongo::logger::LogSeverity::Warning());
|
||||
}
|
||||
}
|
||||
else { // User entered set name is not empty, clear cached set name just in case
|
||||
ConnectionSettings* originalConnSettings = AppRegistry::instance().settingsManager()
|
||||
->getConnectionSettingsByUuid(event->info._uuid);
|
||||
if (originalConnSettings) {
|
||||
originalConnSettings->replicaSetSettings()->setCachedSetName("");
|
||||
AppRegistry::instance().settingsManager()->save();
|
||||
LOG_MSG("Replica set's cached set name cleared. Using user entered set name.",
|
||||
mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::handleConnectionFailure(EstablishConnectionResponse* event)
|
||||
{
|
||||
_isConnected = false;
|
||||
|
||||
std::stringstream ss("Unknown error");
|
||||
auto eventErrorReason = event->errorReason;
|
||||
|
||||
if (_connSettings->isReplicaSet())
|
||||
{
|
||||
ss.clear();
|
||||
std::string server = "";
|
||||
if (_connSettings->replicaSetSettings()->members().size() > 0)
|
||||
server = "[" + _connSettings->replicaSetSettings()->members().front() + "]";
|
||||
|
||||
if (event->error().errorCode() == EventError::ErrorCode::ServerHasDifferentMembers) {
|
||||
ss << "Cannot connect to replica set \"" << _connSettings->connectionName() << "\"" << server
|
||||
<< ". \n\nA primary with different host name [" << event->replicaSet.primary <<
|
||||
"] found in server side. "
|
||||
"Please double check if same host names and ports are used as in server's replica set"
|
||||
" configuration. \nIf same set name is used for different replica sets, this configuration"
|
||||
" is supported only on different instances of Robomongo. "
|
||||
" Please open a new Robomongo instance for each replica set which has the same set name."
|
||||
"\n\nReason:\n" << event->error().errorMessage();
|
||||
}
|
||||
else {
|
||||
ss << "Cannot connect to replica set \"" << _connSettings->connectionName() << "\"" << server
|
||||
<< ". \nSet's primary is unreachable.\n\nReason:\n" << event->error().errorMessage();
|
||||
}
|
||||
|
||||
_bus->publish(new ConnectionFailedEvent(this, _handle, event->connectionType, ss.str(),
|
||||
ConnectionFailedEvent::MongoConnection));
|
||||
_app->fireConnectionFailedEvent(_handle, event->connectionType, ss.str(),
|
||||
ConnectionFailedEvent::MongoConnection);
|
||||
LOG_MSG("Establish connection failed. " + event->error().errorMessage() + ". Connection: "
|
||||
+ _connSettings->connectionName(), mongo::logger::LogSeverity::Error());
|
||||
}
|
||||
else // single server
|
||||
{
|
||||
if (EstablishConnectionResponse::ErrorReason::MongoSslConnection == eventErrorReason)
|
||||
{
|
||||
auto reason = ConnectionFailedEvent::SslConnection;
|
||||
ss.clear();
|
||||
ss << "Cannot connect to the MongoDB at " << connectionRecord()->getFullAddress()
|
||||
<< ".\n\nError:\n" << "TLS connection failure: " << event->error().errorMessage();
|
||||
_app->fireConnectionFailedEvent(_handle, _connectionType, ss.str(), reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto reason = (EstablishConnectionResponse::ErrorReason::MongoAuth == eventErrorReason) ?
|
||||
ConnectionFailedEvent::MongoAuth : ConnectionFailedEvent::MongoConnection;
|
||||
ss.clear();
|
||||
ss << "Cannot connect to the MongoDB at " << connectionRecord()->getFullAddress()
|
||||
<< ".\n\nError:\n" << event->error().errorMessage();
|
||||
_app->fireConnectionFailedEvent(_handle, _connectionType, ss.str(), reason);
|
||||
}
|
||||
|
||||
// When connection cannot be established, we should cleanup this instance of MongoServer if it wasn't
|
||||
// shown in UI (i.e. it is not a Secondary connection that is used for shells tab)
|
||||
if (_connectionType == ConnectionPrimary || _connectionType == ConnectionTest)
|
||||
{
|
||||
LOG_MSG("Establish connection failed. " + event->error().errorMessage() +
|
||||
". Connection: " + _connSettings->connectionName(),
|
||||
mongo::logger::LogSeverity::Error());
|
||||
_app->closeServer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MongoServer::hideProgressBar() const
|
||||
{
|
||||
MainWindow* mainWindow = nullptr;
|
||||
for (auto wid : QApplication::topLevelWidgets()) {
|
||||
if ((mainWindow = qobject_cast<MainWindow*>(wid)))
|
||||
break;
|
||||
}
|
||||
|
||||
if(mainWindow)
|
||||
mainWindow->hideQueryWidgetProgressBar();
|
||||
}
|
||||
|
||||
} // namespace Robomongo
|
||||
|
||||
@@ -8,10 +8,16 @@ namespace Robomongo
|
||||
{
|
||||
class MongoWorker;
|
||||
class MongoDatabase;
|
||||
class EstablishConnectionResponse;
|
||||
class EventBus;
|
||||
class App;
|
||||
|
||||
// Messages
|
||||
struct EstablishConnectionResponse;
|
||||
struct RefreshReplicaSetFolderResponse;
|
||||
class LoadDatabaseNamesResponse;
|
||||
class InsertDocumentResponse;
|
||||
class EventBus;
|
||||
struct CreateDatabaseResponse;
|
||||
struct DropDatabaseResponse;
|
||||
|
||||
/**
|
||||
* @brief MongoServer represents active connection to MongoDB server.
|
||||
@@ -29,30 +35,60 @@ namespace Robomongo
|
||||
* @param visible
|
||||
* @param defaultDatabase
|
||||
*/
|
||||
MongoServer(ConnectionSettings *connectionRecord, bool visible);
|
||||
MongoServer(int handle, ConnectionSettings *connectionRecord, ConnectionType connectionType);
|
||||
~MongoServer();
|
||||
|
||||
void runWorkerThread();
|
||||
|
||||
/**
|
||||
* @brief Try to connect to MongoDB server.
|
||||
* @brief Try to connect to MongoDB single server or replica set.
|
||||
* @throws MongoException, if fails
|
||||
*/
|
||||
void tryConnect();
|
||||
bool isConnected()const;
|
||||
|
||||
/**
|
||||
* @brief Try to re-connect to MongoDB server in order to refresh connection view.
|
||||
* Never shown in Explorer and can be used to refresh (via reconnecting) current connection view.
|
||||
* (i.e. db version, storage engine etc...)
|
||||
* @throws MongoException, if fails
|
||||
*/
|
||||
void tryRefresh();
|
||||
|
||||
/**
|
||||
* @brief Try to re-connect to MongoDB replica set in order to refresh connection view.
|
||||
* It is used to refresh (via reconnecting) current connection view.
|
||||
* (i.e. db version, storage engine, current replica set primary, status of replica set etc...)
|
||||
* It will update Explorer widgets depending on replica set status (online if primary reachable and
|
||||
* offline otherwise)
|
||||
*/
|
||||
void tryRefreshReplicaSetConnection();
|
||||
|
||||
/**
|
||||
* @brief Try to re-connect to MongoDB replica set in order to refresh connection view.
|
||||
* It is used to refresh (via reconnecting) current connection view.
|
||||
* (i.e. db version, storage engine, current replica set primary, status of replica set etc...)
|
||||
* It will update only 'Replica Set' folder widgets depending on replica set status
|
||||
* (online if primary reachable and offline otherwise)
|
||||
*/
|
||||
void tryRefreshReplicaSetFolder(bool expanded, bool showLoading = true);
|
||||
|
||||
bool isConnected() const;
|
||||
|
||||
void addDatabase(MongoDatabase *database);
|
||||
void createDatabase(const std::string &dbName);
|
||||
void dropDatabase(const std::string &dbName);
|
||||
QStringList getDatabasesNames() const;
|
||||
QList<MongoDatabase*> const& databases() const { return _databases; };
|
||||
MongoDatabase *findDatabaseByName(const std::string &dbName) const;
|
||||
|
||||
void insertDocuments(const std::vector<mongo::BSONObj> &objCont, const MongoNamespace &ns);
|
||||
void insertDocument(const mongo::BSONObj &obj, const MongoNamespace &ns);
|
||||
void saveDocuments(const std::vector<mongo::BSONObj> &objCont, const MongoNamespace &ns);
|
||||
void saveDocument(const mongo::BSONObj &obj, const MongoNamespace &ns);
|
||||
void removeDocuments(mongo::Query query, const MongoNamespace &ns, bool justOne = true);
|
||||
void removeDocuments(mongo::Query query, const MongoNamespace &ns, RemoveDocumentCount removeCount,
|
||||
int index = 0);
|
||||
float version() const{ return _version; }
|
||||
|
||||
const std::string& getStorageEngineType() const { return _storageEngineType; }
|
||||
|
||||
/**
|
||||
* @brief Returns associated connection record
|
||||
@@ -63,28 +99,44 @@ namespace Robomongo
|
||||
* @brief Loads databases of this server asynchronously.
|
||||
*/
|
||||
void loadDatabases();
|
||||
bool visible() const { return _visible; }
|
||||
MongoWorker *const client() const { return _client; }
|
||||
MongoWorker *const worker() const { return _worker; }
|
||||
|
||||
ReplicaSet* replicaSetInfo() const { return _replicaSetInfo.get(); }
|
||||
|
||||
void handle(ReplicaSetRefreshed *event);
|
||||
|
||||
void changeWorkerShellTimeout(int newTimeout);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void handle(EstablishConnectionResponse *event);
|
||||
void handle(RefreshReplicaSetFolderResponse *event);
|
||||
void handle(LoadDatabaseNamesResponse *event);
|
||||
void handle(InsertDocumentResponse *event);
|
||||
void handle(RemoveDocumentResponse *event);
|
||||
void handle(CreateDatabaseResponse *event);
|
||||
void handle(DropDatabaseResponse *event);
|
||||
|
||||
private:
|
||||
private:
|
||||
void clearDatabases();
|
||||
void addDatabase(MongoDatabase *database);
|
||||
void handleReplicaSetRefreshEvents(bool isError, EventError eventError, ReplicaSet const& replicaSet,
|
||||
bool expanded);
|
||||
void updateReplicaSetSettings(EstablishConnectionResponse* event);
|
||||
void handleConnectionFailure(EstablishConnectionResponse* event);
|
||||
void hideProgressBar() const;
|
||||
|
||||
MongoWorker* _client;
|
||||
ConnectionSettings* _settings;
|
||||
EventBus* _bus;
|
||||
MongoWorker *_worker;
|
||||
std::unique_ptr<ConnectionSettings> _connSettings;
|
||||
EventBus *_bus;
|
||||
App *_app;
|
||||
|
||||
float _version;
|
||||
bool _visible;
|
||||
std::string _storageEngineType;
|
||||
ConnectionType _connectionType;
|
||||
bool _isConnected;
|
||||
int _handle;
|
||||
|
||||
QList<MongoDatabase *> _databases;
|
||||
std::unique_ptr<ReplicaSet> _replicaSetInfo;
|
||||
};
|
||||
|
||||
class MongoServerLoadingDatabasesEvent : public Event
|
||||
|
||||
@@ -11,20 +11,21 @@
|
||||
#include "robomongo/core/settings/SettingsManager.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
{
|
||||
auto const& eventBus = []() { return AppRegistry::instance().bus(); };
|
||||
|
||||
MongoShell::MongoShell(MongoServer *server, const ScriptInfo &scriptInfo) :
|
||||
MongoShell::MongoShell(MongoServer *server, ScriptInfo scriptInfo) :
|
||||
QObject(),
|
||||
_scriptInfo(scriptInfo),
|
||||
_server(server)
|
||||
_server(server)
|
||||
{
|
||||
}
|
||||
|
||||
void MongoShell::open(const std::string &script, const std::string &dbName)
|
||||
{
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutingEvent(this));
|
||||
eventBus()->publish(new ScriptExecutingEvent(this));
|
||||
_scriptInfo.setScript(QtUtils::toQString(script));
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteScriptRequest(this, query(), dbName));
|
||||
eventBus()->send(_server->worker(), new ExecuteScriptRequest(this, query(), dbName));
|
||||
LOG_MSG(_scriptInfo.script(), mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
@@ -33,36 +34,41 @@ namespace Robomongo
|
||||
return QtUtils::toStdString(_scriptInfo.script());
|
||||
}
|
||||
|
||||
void MongoShell::execute(const std::string &dbName)
|
||||
void MongoShell::execute(const std::string &script /* = "" */,
|
||||
const std::string &dbName /* = "" */)
|
||||
{
|
||||
if (_scriptInfo.execute()) {
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutingEvent(this));
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteScriptRequest(this, query(), dbName));
|
||||
if(!_scriptInfo.script().isEmpty())
|
||||
LOG_MSG(_scriptInfo.script(), mongo::logger::LogSeverity::Info());
|
||||
} else {
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutingEvent(this));
|
||||
_scriptInfo.setScript("");
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteScriptRequest(this,query() , dbName));
|
||||
}
|
||||
if (!_scriptInfo.execute())
|
||||
return;
|
||||
|
||||
std::string const finalScript = script.empty() ? query() : script;
|
||||
eventBus()->publish(new ScriptExecutingEvent(this));
|
||||
eventBus()->send(_server->worker(),
|
||||
new ExecuteScriptRequest(this, finalScript, dbName, _aggrInfo));
|
||||
if (!_scriptInfo.script().isEmpty())
|
||||
LOG_MSG(_scriptInfo.script(), mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
void MongoShell::query(int resultIndex, const MongoQueryInfo &info)
|
||||
{
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteQueryRequest(this, resultIndex, info));
|
||||
eventBus()->send(_server->worker(), new ExecuteQueryRequest(this, resultIndex, info));
|
||||
}
|
||||
|
||||
void MongoShell::autocomplete(const std::string &prefix)
|
||||
{
|
||||
AutocompletionMode autocompletionMode = AppRegistry::instance().settingsManager()->autocompletionMode();
|
||||
AutocompletionMode autocompletionMode {
|
||||
AppRegistry::instance().settingsManager()->autocompletionMode()
|
||||
};
|
||||
if (autocompletionMode == AutocompleteNone)
|
||||
return;
|
||||
AppRegistry::instance().bus()->send(_server->client(), new AutocompleteRequest(this, prefix, autocompletionMode));
|
||||
|
||||
eventBus()->send(_server->worker(),
|
||||
new AutocompleteRequest(this, prefix, autocompletionMode)
|
||||
);
|
||||
}
|
||||
|
||||
void MongoShell::stop()
|
||||
{
|
||||
// _server->client()->interrupt();
|
||||
// _server->worker()->interrupt();
|
||||
// mongo::Scope::setInterruptFlag(true);
|
||||
}
|
||||
|
||||
@@ -84,30 +90,50 @@ namespace Robomongo
|
||||
void MongoShell::handle(ExecuteQueryResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
AppRegistry::instance().bus()->publish(new DocumentListLoadedEvent(this, event->error()));
|
||||
eventBus()->publish(new DocumentListLoadedEvent(this, event->error()));
|
||||
return;
|
||||
}
|
||||
|
||||
AppRegistry::instance().bus()->publish(new DocumentListLoadedEvent(this, event->resultIndex, event->queryInfo, query(), event->documents));
|
||||
eventBus()->publish(
|
||||
new DocumentListLoadedEvent(this,
|
||||
event->resultIndex, event->queryInfo, query(), event->documents)
|
||||
);
|
||||
}
|
||||
|
||||
void MongoShell::handle(ExecuteScriptResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutedEvent(this, event->error()));
|
||||
if (!event->isError()) {
|
||||
eventBus()->publish(
|
||||
new ScriptExecutedEvent(this, event->result, event->empty, event->timeoutReached())
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutedEvent(this, event->result, event->empty));
|
||||
if (_server->connectionRecord()->isReplicaSet()) {
|
||||
eventBus()->publish(
|
||||
new ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo())
|
||||
);
|
||||
|
||||
eventBus()->publish(
|
||||
new ScriptExecutedEvent(this, event->error(), event->timeoutReached())
|
||||
);
|
||||
return;
|
||||
}
|
||||
else { // single server
|
||||
eventBus()->publish(
|
||||
new ScriptExecutedEvent(this, event->error(), event->timeoutReached())
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MongoShell::handle(AutocompleteResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
AppRegistry::instance().bus()->publish(new AutocompleteResponse(this, event->error()));
|
||||
eventBus()->publish(new AutocompleteResponse(this, event->error()));
|
||||
return;
|
||||
}
|
||||
|
||||
AppRegistry::instance().bus()->publish(new AutocompleteResponse(this, event->list, event->prefix));
|
||||
eventBus()->publish(new AutocompleteResponse(this, event->list, event->prefix));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
#include <QObject>
|
||||
#include "robomongo/core/events/MongoEvents.h"
|
||||
#include "robomongo/core/domain/ScriptInfo.h"
|
||||
#include "robomongo/core/domain/MongoAggregateInfo.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
struct AggrInfo;
|
||||
|
||||
class MongoShell : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MongoShell(MongoServer *server,const ScriptInfo &scriptInfo);
|
||||
MongoShell(MongoServer *server, ScriptInfo scriptInfo);
|
||||
|
||||
void open(const std::string &script, const std::string &dbName = std::string());
|
||||
void query(int resultIndex, const MongoQueryInfo &info);
|
||||
@@ -18,11 +21,14 @@ namespace Robomongo
|
||||
void stop();
|
||||
MongoServer *server() const { return _server; }
|
||||
std::string query() const;
|
||||
void execute(const std::string &dbName = std::string());
|
||||
bool isExecutable() const {return _scriptInfo.execute(); }
|
||||
void execute(const std::string &script = "", const std::string &dbName = "");
|
||||
bool isExecutable() const { return _scriptInfo.execute(); }
|
||||
const QString &title() const { return _scriptInfo.title(); }
|
||||
std::string dbname() const { return _scriptInfo.dbname(); }
|
||||
const CursorPosition &cursor() const { return _scriptInfo.cursor(); }
|
||||
void setScript(const QString &script) { return _scriptInfo.setScript(script); }
|
||||
void setScriptExecutable(bool execute) { _scriptInfo.setExecutable(execute); }
|
||||
void setAggrInfo(AggrInfo const& aggrInfo) { _aggrInfo = aggrInfo; }
|
||||
QString filePath() const { return _scriptInfo.filePath(); }
|
||||
|
||||
bool saveToFile();
|
||||
@@ -36,6 +42,7 @@ namespace Robomongo
|
||||
|
||||
private:
|
||||
ScriptInfo _scriptInfo;
|
||||
AggrInfo _aggrInfo;
|
||||
MongoServer *_server;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "robomongo/core/domain/MongoShellResult.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
MongoShellResult::MongoShellResult(const std::string &type, const std::string &response, const MongoDocumentPtrContainerType &documents,
|
||||
const MongoQueryInfo &queryInfo, qint64 elapsedms) :
|
||||
_type(type),
|
||||
_response(response),
|
||||
_documents(documents),
|
||||
_queryInfo(queryInfo),
|
||||
_elapsedms(elapsedms) { }
|
||||
|
||||
MongoShellExecResult::MongoShellExecResult(const std::vector<MongoShellResult> &results,
|
||||
const std::string ¤tServer, bool isCurrentServerValid,
|
||||
const std::string ¤tDatabase, bool isCurrentDatabaseValid) :
|
||||
_results(results),
|
||||
_currentServer(currentServer),
|
||||
_currentDatabase(currentDatabase),
|
||||
_isCurrentServerValid(isCurrentServerValid),
|
||||
_isCurrentDatabaseValid(isCurrentDatabaseValid) { }
|
||||
}
|
||||
@@ -1,43 +1,84 @@
|
||||
#pragma once
|
||||
#include "robomongo/core/domain/MongoQueryInfo.h"
|
||||
#include "robomongo/core/domain/MongoAggregateInfo.h"
|
||||
#include "robomongo/core/domain/MongoDocument.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
/* -------------- MongoShellResult Class --------- */
|
||||
class MongoShellResult
|
||||
{
|
||||
public:
|
||||
typedef std::vector<MongoDocumentPtr> MongoDocumentPtrContainerType;
|
||||
MongoShellResult(const std::string &type, const std::string &response, const MongoDocumentPtrContainerType &documents,
|
||||
const MongoQueryInfo &queryInfo, qint64 elapsedms);
|
||||
MongoShellResult(
|
||||
const std::string &type, const std::string &response,
|
||||
const std::vector<MongoDocumentPtr> &documents,
|
||||
const MongoQueryInfo &queryInfo, const std::string &statement,
|
||||
qint64 elapsedms, AggrInfo aggrInfo = AggrInfo()) :
|
||||
_type(type),
|
||||
_response(response),
|
||||
_documents(documents),
|
||||
_queryInfo(queryInfo),
|
||||
_statement(statement),
|
||||
_elapsedms(elapsedms),
|
||||
_aggrInfo(aggrInfo)
|
||||
{ }
|
||||
|
||||
std::string response() const { return _response; }
|
||||
std::string type() const { return _type; }
|
||||
MongoDocumentPtrContainerType documents() const { return _documents; }
|
||||
std::vector<MongoDocumentPtr> documents() const { return _documents; }
|
||||
MongoQueryInfo queryInfo() const { return _queryInfo; }
|
||||
std::string statement() const { return _statement; }
|
||||
std::string statementShort() const {
|
||||
std::size_t const LEN = _statement.size() < 10 ? _statement.size() : 10;
|
||||
std::string statementShort { _statement, 0, LEN };
|
||||
statementShort.append((_statement.size() > 10) ? ".." : "");
|
||||
return statementShort;
|
||||
}
|
||||
|
||||
qint64 elapsedMs() const { return _elapsedms; }
|
||||
AggrInfo const& aggrInfo() const { return _aggrInfo; }
|
||||
|
||||
private:
|
||||
std::string _type;
|
||||
std::string _response;
|
||||
MongoDocumentPtrContainerType _documents;
|
||||
std::vector<MongoDocumentPtr> _documents;
|
||||
MongoQueryInfo _queryInfo;
|
||||
std::string const _statement;
|
||||
qint64 _elapsedms;
|
||||
AggrInfo _aggrInfo = AggrInfo();
|
||||
};
|
||||
|
||||
/* -------------- MongoShellExecResult Class --------- */
|
||||
class MongoShellExecResult
|
||||
{
|
||||
public:
|
||||
MongoShellExecResult() { }
|
||||
MongoShellExecResult(const std::vector<MongoShellResult> &results,
|
||||
const std::string ¤tServer, bool isCurrentServerValid,
|
||||
const std::string ¤tDatabase, bool isCurrentDatabaseValid);
|
||||
|
||||
std::vector<MongoShellResult> results() const { return _results; }
|
||||
MongoShellExecResult(
|
||||
const std::vector<MongoShellResult> &results,
|
||||
const std::string ¤tServer, bool isCurrentServerValid,
|
||||
const std::string ¤tDatabase, bool isCurrentDatabaseValid,
|
||||
bool timeoutReached = false) :
|
||||
_results(results),
|
||||
_currentServer(currentServer),
|
||||
_currentDatabase(currentDatabase),
|
||||
_isCurrentServerValid(isCurrentServerValid),
|
||||
_isCurrentDatabaseValid(isCurrentDatabaseValid),
|
||||
_timeoutReached(timeoutReached)
|
||||
{ }
|
||||
|
||||
MongoShellExecResult(bool error, std::string const& errorMsg = "", bool timeoutReached = false) :
|
||||
_error(error), _errorMessage(errorMsg), _timeoutReached(timeoutReached) { }
|
||||
|
||||
std::vector<MongoShellResult> const& results() const { return _results; }
|
||||
std::string currentServer() const { return _currentServer; }
|
||||
std::string currentDatabase() const { return _currentDatabase; }
|
||||
void setCurrentServer(std::string const& server) { _currentServer = server; }
|
||||
std::string currentDatabase() const { return _currentDatabase; }
|
||||
bool isCurrentServerValid() const { return _isCurrentServerValid; }
|
||||
bool isCurrentDatabaseValid() const { return _isCurrentDatabaseValid; }
|
||||
std::string errorMessage() const { return _errorMessage; }
|
||||
bool error() const { return _error; }
|
||||
bool timeoutReached() const { return _timeoutReached; }
|
||||
|
||||
private:
|
||||
std::vector<MongoShellResult> _results;
|
||||
@@ -45,5 +86,8 @@ namespace Robomongo
|
||||
std::string _currentDatabase;
|
||||
bool _isCurrentServerValid;
|
||||
bool _isCurrentDatabaseValid;
|
||||
std::string _errorMessage;
|
||||
bool _error = false;
|
||||
bool _timeoutReached = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#include "robomongo/core/domain/MongoUser.h"
|
||||
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
|
||||
#include "robomongo/core/utils/BsonUtils.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
const float MongoUser::minimumSupportedVersion = 2.4f;
|
||||
|
||||
MongoUser::MongoUser(const float version, const mongo::BSONObj &obj) :
|
||||
_version(version), _readOnly(false)
|
||||
{
|
||||
_id = obj.getField("_id").OID();
|
||||
_name = BsonUtils::getField<mongo::String>(obj,"user");
|
||||
_passwordHash = BsonUtils::getField<mongo::String>(obj,"pwd");
|
||||
if (_version<minimumSupportedVersion) {
|
||||
_readOnly = BsonUtils::getField<mongo::Bool>(obj,"readOnly");
|
||||
}
|
||||
else {
|
||||
_userSource = BsonUtils::getField<mongo::String>(obj,"userSource");
|
||||
std::vector<mongo::BSONElement> roles = BsonUtils::getField<mongo::Array>(obj, "roles");
|
||||
for (std::vector<mongo::BSONElement>::const_iterator it = roles.begin(); it!= roles.end(); ++it)
|
||||
{
|
||||
_role.push_back(BsonUtils::bsonelement_cast<std::string>(*it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MongoUser::MongoUser(const float version) :
|
||||
_version(version),_readOnly(false),_role() {}
|
||||
|
||||
mongo::BSONObj MongoUser::toBson() const
|
||||
{
|
||||
mongo::BSONObjBuilder builder;
|
||||
|
||||
if (!(_id == mongo::OID())) // if not empty (i.e. not Object("0000000000000000"))
|
||||
builder.append("_id", _id);
|
||||
|
||||
builder.append("user", _name);
|
||||
|
||||
if (!_passwordHash.empty())
|
||||
builder.append("pwd", _passwordHash);
|
||||
|
||||
if (_version<minimumSupportedVersion) {
|
||||
builder.append("readOnly", _readOnly);
|
||||
}
|
||||
else {
|
||||
if (!_userSource.empty())
|
||||
builder.append("userSource", _userSource);
|
||||
|
||||
mongo::BSONArrayBuilder builderA;
|
||||
for (RoleType::const_iterator it = _role.begin(); it!=_role.end(); ++it)
|
||||
{
|
||||
builderA << *it;
|
||||
}
|
||||
mongo::BSONObj arObj = builderA.arr();
|
||||
builder.appendArray("roles", arObj);
|
||||
}
|
||||
mongo::BSONObj obj = builder.obj();
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,46 +2,45 @@
|
||||
#include <mongo/bson/bsonobj.h>
|
||||
#include <mongo/bson/bsonelement.h>
|
||||
|
||||
#include "robomongo/core/utils/BsonUtils.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
class MongoUser
|
||||
{
|
||||
public:
|
||||
typedef std::vector<std::string> RoleType;
|
||||
/**
|
||||
* @brief Creates user from "system.users" document
|
||||
*/
|
||||
explicit MongoUser(const float version, const mongo::BSONObj &obj);
|
||||
typedef std::vector<std::string> RolesVector;
|
||||
|
||||
/**
|
||||
* @brief Creates new user with empty attributes
|
||||
*/
|
||||
MongoUser(const float version);
|
||||
explicit MongoUser(const float version, const mongo::BSONObj &obj) :
|
||||
_version(version), _readOnly(false),
|
||||
_name(BsonUtils::getField<mongo::String>(obj, "user"))
|
||||
{};
|
||||
|
||||
// Creates new user with empty attributes
|
||||
MongoUser(const float version) :
|
||||
_version(version), _readOnly(false), _roles() {}
|
||||
|
||||
mongo::OID id() const { return _id; }
|
||||
std::string name() const { return _name; }
|
||||
RoleType role() const { return _role; }
|
||||
std::string passwordHash() const { return _passwordHash; }
|
||||
std::string password() const { return _password; }
|
||||
std::vector<std::string> roles() const { return _roles; }
|
||||
|
||||
void setName(const std::string &name) { _name = name; }
|
||||
void setRole(const RoleType &role) { _role = role; }
|
||||
void setPasswordHash(const std::string &hash) { _passwordHash = hash; }
|
||||
void setPassword(const std::string &pwd) { _password = pwd; }
|
||||
void setRoles(const std::vector<std::string> &roles) { _roles = roles; }
|
||||
|
||||
std::string userSource() const { return _userSource; }
|
||||
void setUserSource(const std::string &source) { _userSource = source; }
|
||||
mongo::BSONObj toBson() const;
|
||||
bool readOnly() const { return _readOnly; }
|
||||
void setReadOnly(bool readonly) { _readOnly = readonly; }
|
||||
|
||||
float version() const { return _version; }
|
||||
static const float minimumSupportedVersion;
|
||||
static constexpr float minimumSupportedVersion = 2.4f;
|
||||
private:
|
||||
float _version;
|
||||
mongo::OID _id;
|
||||
std::string _name;
|
||||
bool _readOnly;
|
||||
RoleType _role;
|
||||
std::string _passwordHash;
|
||||
RolesVector _roles;
|
||||
std::string _password;
|
||||
std::string _userSource;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "robomongo/core/domain/Notifier.h"
|
||||
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include <QAction>
|
||||
#include <QClipboard>
|
||||
#include <QApplication>
|
||||
@@ -15,6 +18,7 @@
|
||||
|
||||
#include "robomongo/shell/db/ptimeutil.h"
|
||||
|
||||
#include "robomongo/gui/MainWindow.h"
|
||||
#include "robomongo/gui/widgets/workarea/BsonTreeItem.h"
|
||||
#include "robomongo/gui/dialogs/DocumentTextEditor.h"
|
||||
#include "robomongo/gui/utils/DialogUtils.h"
|
||||
@@ -25,10 +29,10 @@ namespace Robomongo
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
bool isSimpleType(Robomongo::BsonTreeItem *item)
|
||||
bool isSimpleType(Robomongo::BsonTreeItem const *item)
|
||||
{
|
||||
return Robomongo::BsonUtils::isSimpleType(item->type())
|
||||
|| Robomongo::BsonUtils::isUuidType(item->type(), item->binType());
|
||||
return BsonUtils::isSimpleType(item->type()) ||
|
||||
BsonUtils::isUuidType(item->type(), item->binType());
|
||||
}
|
||||
|
||||
bool isObjectIdType(Robomongo::BsonTreeItem *item)
|
||||
@@ -38,12 +42,22 @@ namespace Robomongo
|
||||
|
||||
bool isMultiSelection(const QModelIndexList &indexes)
|
||||
{
|
||||
return indexes.count()>1;
|
||||
return indexes.count() > 1;
|
||||
}
|
||||
|
||||
bool isDocumentType(BsonTreeItem *item)
|
||||
bool isDocumentType(BsonTreeItem const *item)
|
||||
{
|
||||
return Robomongo::BsonUtils::isDocument(item->type());
|
||||
return BsonUtils::isDocument(item->type());
|
||||
}
|
||||
|
||||
bool isArrayChild(BsonTreeItem const *item)
|
||||
{
|
||||
return BsonUtils::isArray(dynamic_cast<BsonTreeItem*>(item->parent())->type());
|
||||
}
|
||||
|
||||
bool isDocumentRoot(BsonTreeItem const *item)
|
||||
{
|
||||
return ( item == item->superParent() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,20 +69,20 @@ namespace Robomongo
|
||||
QModelIndexList uniqueRows(QModelIndexList indexes, bool returnSuperParents)
|
||||
{
|
||||
QModelIndexList result;
|
||||
for (QModelIndexList::const_iterator it = indexes.begin(); it!=indexes.end(); ++it)
|
||||
for (QModelIndexList::const_iterator it = indexes.begin(); it != indexes.end(); ++it)
|
||||
{
|
||||
QModelIndex isUnique = *it;
|
||||
Robomongo::BsonTreeItem *item = Robomongo::QtUtils::item<Robomongo::BsonTreeItem*>(isUnique);
|
||||
if(item){
|
||||
for (QModelIndexList::const_iterator jt = result.begin(); jt!=result.end(); ++jt)
|
||||
if (item) {
|
||||
for (QModelIndexList::const_iterator jt = result.begin(); jt != result.end(); ++jt)
|
||||
{
|
||||
Robomongo::BsonTreeItem *jItem = Robomongo::QtUtils::item<Robomongo::BsonTreeItem*>(*jt);
|
||||
if (jItem && jItem->superParent() == item->superParent()){
|
||||
if (jItem && jItem->superParent() == item->superParent()) {
|
||||
isUnique = QModelIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isUnique.isValid()){
|
||||
if (isUnique.isValid()) {
|
||||
if (returnSuperParents) {
|
||||
// Move index onto "super parent" element before pushing it into result set
|
||||
QModelIndex parent = isUnique.parent();
|
||||
@@ -92,8 +106,8 @@ namespace Robomongo
|
||||
_queryInfo(queryInfo)
|
||||
{
|
||||
QWidget *wid = dynamic_cast<QWidget*>(_observer);
|
||||
AppRegistry::instance().bus()->subscribe(this, InsertDocumentResponse::Type);
|
||||
AppRegistry::instance().bus()->subscribe(this, RemoveDocumentResponse::Type);
|
||||
AppRegistry::instance().bus()->subscribe(this, InsertDocumentResponse::Type, _shell->server());
|
||||
AppRegistry::instance().bus()->subscribe(this, RemoveDocumentResponse::Type, _shell->server());
|
||||
|
||||
_deleteDocumentAction = new QAction("Delete Document...", wid);
|
||||
VERIFY(connect(_deleteDocumentAction, SIGNAL(triggered()), SLOT(onDeleteDocument())));
|
||||
@@ -113,6 +127,12 @@ namespace Robomongo
|
||||
_copyValueAction = new QAction("Copy Value", wid);
|
||||
VERIFY(connect(_copyValueAction, SIGNAL(triggered()), SLOT(onCopyDocument())));
|
||||
|
||||
_copyValueNameAction = new QAction("Copy Name", wid);
|
||||
VERIFY(connect(_copyValueNameAction, SIGNAL(triggered()), SLOT(onCopyNameDocument())));
|
||||
|
||||
_copyValuePathAction = new QAction("Copy Path", wid);
|
||||
VERIFY(connect(_copyValuePathAction, SIGNAL(triggered()), SLOT(onCopyPathDocument())));
|
||||
|
||||
_copyTimestampAction = new QAction("Copy Timestamp from ObjectId", wid);
|
||||
VERIFY(connect(_copyTimestampAction, SIGNAL(triggered()), SLOT(onCopyTimestamp())));
|
||||
|
||||
@@ -122,26 +142,36 @@ namespace Robomongo
|
||||
|
||||
void Notifier::initMenu(QMenu *const menu, BsonTreeItem *const item)
|
||||
{
|
||||
bool isEditable = _queryInfo._info.isValid();
|
||||
bool onItem = item ? true : false;
|
||||
bool const isProjection = !_queryInfo._fields.isEmpty();
|
||||
bool const isEditable = _queryInfo._info.isValid() && !isProjection;
|
||||
bool const onItem = item ? true : false;
|
||||
|
||||
bool isSimple = false;
|
||||
bool isDocument = false;
|
||||
bool isObjectId = false;
|
||||
bool isNotArrayChild = false;
|
||||
bool isRoot = false;
|
||||
|
||||
if (item) {
|
||||
isSimple = detail::isSimpleType(item);
|
||||
isDocument = detail::isDocumentType(item);
|
||||
isObjectId = detail::isObjectIdType(item);
|
||||
isNotArrayChild = !detail::isArrayChild(item);
|
||||
isRoot = detail::isDocumentRoot(item);
|
||||
}
|
||||
|
||||
if (onItem && isEditable) menu->addAction(_editDocumentAction);
|
||||
if (onItem) menu->addAction(_viewDocumentAction);
|
||||
if (isEditable) menu->addAction(_insertDocumentAction);
|
||||
|
||||
if (onItem && (isSimple || isDocument)) menu->addSeparator();
|
||||
|
||||
if (onItem && isSimple) menu->addAction(_copyValueAction);
|
||||
|
||||
if (onItem && (isSimple || isDocument) && isNotArrayChild && !isRoot)
|
||||
menu->addAction(_copyValueNameAction);
|
||||
|
||||
if (onItem && (isSimple || isDocument) && !isRoot)
|
||||
menu->addAction(_copyValuePathAction);
|
||||
|
||||
if (onItem && isObjectId) menu->addAction(_copyTimestampAction);
|
||||
if (onItem && isDocument) menu->addAction(_copyJsonAction);
|
||||
if (onItem && isEditable) menu->addSeparator();
|
||||
@@ -156,11 +186,12 @@ namespace Robomongo
|
||||
if (isEditable) menu->addAction(_deleteDocumentsAction);
|
||||
}
|
||||
|
||||
void Notifier::deleteDocuments(std::vector<BsonTreeItem*> items, bool force)
|
||||
void Notifier::deleteDocuments(std::vector<BsonTreeItem*> const& items, bool force)
|
||||
{
|
||||
bool isNeededRefresh = false;
|
||||
for (std::vector<BsonTreeItem*>::const_iterator it = items.begin(); it != items.end(); ++it) {
|
||||
BsonTreeItem * documentItem = *it;
|
||||
|
||||
int index = 0;
|
||||
for (auto const * const documentItem : items) {
|
||||
if (!documentItem)
|
||||
break;
|
||||
|
||||
@@ -168,7 +199,8 @@ namespace Robomongo
|
||||
mongo::BSONElement id = obj.getField("_id");
|
||||
|
||||
if (id.eoo()) {
|
||||
QMessageBox::warning(dynamic_cast<QWidget*>(_observer), "Cannot delete", "Selected document doesn't have _id field. \n"
|
||||
QMessageBox::warning(dynamic_cast<QWidget*>(_observer), "Cannot delete",
|
||||
"Selected document doesn't have _id field. \n"
|
||||
"Maybe this is a system document that should be managed in a special way?");
|
||||
break;
|
||||
}
|
||||
@@ -187,45 +219,113 @@ namespace Robomongo
|
||||
break;
|
||||
}
|
||||
|
||||
isNeededRefresh=true;
|
||||
_shell->server()->removeDocuments(query, _queryInfo._info._ns);
|
||||
}
|
||||
isNeededRefresh = true;
|
||||
|
||||
if (isNeededRefresh)
|
||||
_shell->query(0, _queryInfo);
|
||||
RemoveDocumentCount removeCount = items.size() == 1 ? RemoveDocumentCount::ONE :
|
||||
RemoveDocumentCount::MULTI;
|
||||
_shell->server()->removeDocuments(query, _queryInfo._info._ns, removeCount, index);
|
||||
++index;
|
||||
mainWindow()->showQueryWidgetProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
void Notifier::handle(InsertDocumentResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
QMessageBox::warning(NULL, "Database Error", QString::fromStdString(event->error().errorMessage()));
|
||||
if (event->isError()) { // Error
|
||||
mainWindow()->hideQueryWidgetProgressBar();
|
||||
if (_shell->server()->connectionRecord()->isReplicaSet()) {
|
||||
// Insert document from tab results window (Notifier, OutputWindow widget)
|
||||
if (EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
AppRegistry::instance().bus()->publish(
|
||||
new ReplicaSetRefreshed(_shell, event->error(), event->error().replicaSetInfo()));
|
||||
}
|
||||
}
|
||||
else // single server
|
||||
QMessageBox::warning(NULL, "Database Error", QString::fromStdString(event->error().errorMessage()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Success
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
_shell->query(0, _queryInfo);
|
||||
}
|
||||
|
||||
void Notifier::handle(RemoveDocumentResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
// Commented because when you'll delete multiple documents,
|
||||
// we'll receive this event as many times as many selected
|
||||
// documents you have. This is incorrect and remove of
|
||||
// multiple documents should be a single command, instead
|
||||
// of many. Error message should be printed in the logs.
|
||||
if (event->isError()) {
|
||||
if (!(event->removeCount == RemoveDocumentCount::MULTI && event->index > 0))
|
||||
QMessageBox::warning(NULL, "Database Error", QString::fromStdString(event->error().errorMessage()));
|
||||
}
|
||||
else { // Success
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
_shell->query(0, _queryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// QMessageBox::warning(NULL, "Database Error", QString::fromStdString(event->error().errorMessage()));
|
||||
void Notifier::onCopyNameDocument()
|
||||
{
|
||||
QModelIndex const& selectedInd = _observer->selectedIndex();
|
||||
if (!selectedInd.isValid())
|
||||
return;
|
||||
|
||||
BsonTreeItem const *documentItem = QtUtils::item<BsonTreeItem*>(selectedInd);
|
||||
if (!documentItem)
|
||||
return;
|
||||
|
||||
if (!(detail::isSimpleType(documentItem) || detail::isDocumentType(documentItem) ||
|
||||
!detail::isArrayChild(documentItem) || !detail::isDocumentRoot(documentItem)))
|
||||
return;
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(QString::fromStdString(documentItem->fieldName()));
|
||||
}
|
||||
|
||||
void Notifier::onCopyPathDocument()
|
||||
{
|
||||
QModelIndex const& selectedInd = _observer->selectedIndex();
|
||||
if (!selectedInd.isValid())
|
||||
return;
|
||||
|
||||
BsonTreeItem const *documentItem = QtUtils::item<BsonTreeItem*>(selectedInd);
|
||||
if (!documentItem)
|
||||
return;
|
||||
|
||||
if (!(detail::isSimpleType(documentItem) || detail::isDocumentType(documentItem) ||
|
||||
!detail::isDocumentRoot(documentItem)))
|
||||
return;
|
||||
|
||||
QStringList namesList;
|
||||
BsonTreeItem const *documentItemHelper = documentItem;
|
||||
|
||||
while (!detail::isDocumentRoot(documentItemHelper)) {
|
||||
if (!detail::isArrayChild(documentItemHelper)) {
|
||||
namesList.push_front(QString::fromStdString(documentItemHelper->fieldName()));
|
||||
}
|
||||
|
||||
documentItemHelper = dynamic_cast<BsonTreeItem*>(documentItemHelper->parent());
|
||||
}
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(namesList.join("."));
|
||||
}
|
||||
|
||||
MainWindow* Notifier::mainWindow() const
|
||||
{
|
||||
MainWindow* mainWindow;
|
||||
for (auto wid : QApplication::topLevelWidgets()) {
|
||||
if ((mainWindow = qobject_cast<MainWindow*>(wid)))
|
||||
break;
|
||||
}
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
void Notifier::handleDeleteCommand()
|
||||
{
|
||||
if (_observer->selectedIndexes().count() > 1) {
|
||||
if (_observer->selectedIndexes().count() > 1)
|
||||
onDeleteDocuments();
|
||||
} else {
|
||||
onDeleteDocument();
|
||||
}
|
||||
else
|
||||
onDeleteDocument();
|
||||
}
|
||||
|
||||
void Notifier::onDeleteDocuments()
|
||||
@@ -237,14 +337,16 @@ namespace Robomongo
|
||||
if (!detail::isMultiSelection(selectedIndexes))
|
||||
return;
|
||||
|
||||
int answer = QMessageBox::question(dynamic_cast<QWidget*>(_observer), "Delete", QString("Do you want to delete %1 selected documents?").arg(selectedIndexes.count()));
|
||||
if (answer == QMessageBox::Yes) {
|
||||
int const answer = QMessageBox::question(dynamic_cast<QWidget*>(_observer), "Delete",
|
||||
QString("Do you want to delete %1 selected documents?").
|
||||
arg(selectedIndexes.count()));
|
||||
|
||||
if (QMessageBox::Yes == answer) {
|
||||
std::vector<BsonTreeItem*> items;
|
||||
for (QModelIndexList::const_iterator it = selectedIndexes.begin(); it!= selectedIndexes.end(); ++it) {
|
||||
BsonTreeItem *item = QtUtils::item<BsonTreeItem*>(*it);
|
||||
items.push_back(item);
|
||||
}
|
||||
deleteDocuments(items,true);
|
||||
for (auto index : selectedIndexes)
|
||||
items.push_back(QtUtils::item<BsonTreeItem*>(index));
|
||||
|
||||
deleteDocuments(items, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +362,7 @@ namespace Robomongo
|
||||
BsonTreeItem *documentItem = QtUtils::item<BsonTreeItem*>(selectedIndex);
|
||||
std::vector<BsonTreeItem*> vec;
|
||||
vec.push_back(documentItem);
|
||||
return deleteDocuments(vec,false);
|
||||
return deleteDocuments(vec, false);
|
||||
}
|
||||
|
||||
void Notifier::onEditDocument()
|
||||
@@ -276,22 +378,20 @@ namespace Robomongo
|
||||
if (!documentItem)
|
||||
return;
|
||||
|
||||
mongo::BSONObj obj = documentItem->superRoot();
|
||||
|
||||
std::string str = BsonUtils::jsonString(obj, mongo::TenGen, 1,
|
||||
AppRegistry::instance().settingsManager()->uuidEncoding(),
|
||||
AppRegistry::instance().settingsManager()->timeZone());
|
||||
std::string str = BsonUtils::jsonString(documentItem->superRoot(), mongo::TenGen, 1,
|
||||
AppRegistry::instance().settingsManager()->uuidEncoding(),
|
||||
AppRegistry::instance().settingsManager()->timeZone());
|
||||
|
||||
const QString &json = QtUtils::toQString(str);
|
||||
|
||||
DocumentTextEditor editor(_queryInfo._info,
|
||||
json, false, dynamic_cast<QWidget*>(_observer));
|
||||
DocumentTextEditor editor(_queryInfo._info, json, false, dynamic_cast<QWidget*>(_observer));
|
||||
|
||||
editor.setWindowTitle("Edit Document");
|
||||
int result = editor.exec();
|
||||
|
||||
if (result == QDialog::Accepted) {
|
||||
_shell->server()->saveDocuments(editor.bsonObj(), _queryInfo._info._ns);
|
||||
mainWindow()->showQueryWidgetProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,9 +438,8 @@ namespace Robomongo
|
||||
DocumentTextEditor::ReturnType obj = editor.bsonObj();
|
||||
for (DocumentTextEditor::ReturnType::const_iterator it = obj.begin(); it != obj.end(); ++it) {
|
||||
_shell->server()->insertDocument(*it, _queryInfo._info._ns);
|
||||
mainWindow()->showQueryWidgetProgressBar();
|
||||
}
|
||||
|
||||
_shell->query(0, _queryInfo);
|
||||
}
|
||||
|
||||
void Notifier::onCopyDocument()
|
||||
@@ -376,19 +475,19 @@ namespace Robomongo
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
|
||||
// new Date(parseInt(this.valueOf().slice(0,8), 16)*1000);
|
||||
QString hexTimestamp = documentItem->value().mid(10,8);
|
||||
QString hexTimestamp = documentItem->value().mid(10, 8);
|
||||
bool ok;
|
||||
long long milliTimestamp = (long long)hexTimestamp.toLongLong(&ok,16)*1000;
|
||||
long long milliTimestamp = (long long)hexTimestamp.toLongLong(&ok, 16)*1000;
|
||||
|
||||
bool isSupportedDate = (miutil::minDate < milliTimestamp) && (milliTimestamp < miutil::maxDate);
|
||||
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
|
||||
boost::posix_time::time_duration diff = boost::posix_time::millisec(milliTimestamp);
|
||||
boost::posix_time::ptime time = epoch + diff;
|
||||
|
||||
if(isSupportedDate)
|
||||
if (isSupportedDate)
|
||||
{
|
||||
std::string date = miutil::isotimeString(time,false,false);
|
||||
std::string date = miutil::isotimeString(time, false, false);
|
||||
clipboard->setText("ISODate(\""+QString::fromStdString(date)+"\")");
|
||||
}
|
||||
else {
|
||||
@@ -411,13 +510,13 @@ namespace Robomongo
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
mongo::BSONObj obj = documentItem->root();
|
||||
if (documentItem != documentItem->superParent()){
|
||||
obj = obj[QtUtils::toStdString(documentItem->key())].Obj();
|
||||
if (documentItem != documentItem->superParent()) {
|
||||
obj = obj[documentItem->fieldName()].Obj();
|
||||
}
|
||||
bool isArray = BsonUtils::isArray(documentItem->type());
|
||||
std::string str = BsonUtils::jsonString(obj, mongo::TenGen, 1,
|
||||
AppRegistry::instance().settingsManager()->uuidEncoding(),
|
||||
AppRegistry::instance().settingsManager()->timeZone(),isArray);
|
||||
AppRegistry::instance().settingsManager()->timeZone(), isArray);
|
||||
|
||||
const QString &json = QtUtils::toQString(str);
|
||||
clipboard->setText(json);
|
||||
|
||||
@@ -11,17 +11,18 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
class MainWindow;
|
||||
class MongoShell;
|
||||
class BsonTreeItem;
|
||||
class InsertDocumentResponse;
|
||||
class RemoveDocumentResponse;
|
||||
struct RemoveDocumentResponse;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
bool isSimpleType(BsonTreeItem *item);
|
||||
bool isSimpleType(BsonTreeItem const *item);
|
||||
bool isObjectIdType(BsonTreeItem *item);
|
||||
bool isMultiSelection(const QModelIndexList &indexes);
|
||||
bool isDocumentType(BsonTreeItem *item);
|
||||
bool isDocumentType(BsonTreeItem const *item);
|
||||
QModelIndexList uniqueRows(QModelIndexList indexes, bool returnSuperParents = false);
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ namespace Robomongo
|
||||
void initMenu(QMenu *const menu, BsonTreeItem *const item);
|
||||
void initMultiSelectionMenu(QMenu *const menu);
|
||||
|
||||
void deleteDocuments(std::vector<BsonTreeItem*> items, bool force);
|
||||
void deleteDocuments(std::vector<BsonTreeItem*> const& items, bool force);
|
||||
void handleDeleteCommand();
|
||||
|
||||
public Q_SLOTS:
|
||||
@@ -60,13 +61,21 @@ namespace Robomongo
|
||||
void handle(InsertDocumentResponse *event);
|
||||
void handle(RemoveDocumentResponse *event);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCopyNameDocument();
|
||||
void onCopyPathDocument();
|
||||
|
||||
private:
|
||||
MainWindow* mainWindow() const;
|
||||
|
||||
QAction *_deleteDocumentAction;
|
||||
QAction *_deleteDocumentsAction;
|
||||
QAction *_editDocumentAction;
|
||||
QAction *_viewDocumentAction;
|
||||
QAction *_insertDocumentAction;
|
||||
QAction *_copyValueAction;
|
||||
QAction *_copyValueNameAction;
|
||||
QAction *_copyValuePathAction;
|
||||
QAction *_copyTimestampAction;
|
||||
QAction *_copyJsonAction;
|
||||
const MongoQueryInfo _queryInfo;
|
||||
|
||||