Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86509495f3 | ||
|
|
086e6b7d21 | ||
|
|
f47afbddc8 | ||
|
|
14f545ff45 | ||
|
|
bf09a3d9c6 | ||
|
|
93cadb5a6b | ||
|
|
0dd68201f6 | ||
|
|
ba646c4ac0 | ||
|
|
46c50d2aa7 | ||
|
|
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 |
@@ -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,77 +1,187 @@
|
||||
|
||||
Latest Version:
|
||||
Download latest version:
|
||||
https://robomongo.org/download
|
||||
|
||||
Robo 3T 1.4.2 (Oct, 2020)
|
||||
Fixes:
|
||||
- Fix broken paging in DocumentDB (#1694)
|
||||
|
||||
Robo 3T 1.4.1 (Sep, 2020)
|
||||
Fixes:
|
||||
- Force light mode on macOS (#1761, #1768, #1771)
|
||||
- Fix broken macOS native theme/look (#1766)
|
||||
- Fix broken Windows native theme/look
|
||||
|
||||
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
|
||||
|
||||
Robomongo 1.x:
|
||||
Major Features:
|
||||
- Replica set support.
|
||||
|
||||
New Features:
|
||||
- Update Notifications Bar
|
||||
- Welcome Tab
|
||||
- New operation logging for almost all operations.
|
||||
- Welcome Wizard
|
||||
|
||||
Major Fixes/Improvements:
|
||||
- Improved error handling (no double error windows) for almost all operations.
|
||||
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/
|
||||
|
||||
* What's new in 1.0 (21 Apr , 2017)
|
||||
New Features:
|
||||
- Update Notifications Bar
|
||||
- Welcome Tab
|
||||
- Welcome Wizard
|
||||
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:
|
||||
- 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)
|
||||
|
||||
* What's new in 1.0-RC1 (1 Feb, 2017)
|
||||
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.
|
||||
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:
|
||||
@@ -95,9 +205,7 @@ Robomongo 0.9:
|
||||
#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)
|
||||
|
||||
|
||||
"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/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
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
|
||||
@@ -6,11 +6,15 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
|
||||
# Project version
|
||||
set(PROJECT_VERSION_MAJOR "1")
|
||||
set(PROJECT_VERSION_MINOR "0")
|
||||
set(PROJECT_VERSION_PATCH "0")
|
||||
set(PROJECT_VERSION_MINOR "4")
|
||||
set(PROJECT_VERSION_PATCH "2")
|
||||
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)
|
||||
@@ -33,16 +37,33 @@ 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/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 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,82 +1,76 @@
|
||||
About Robomongo [](https://gitter.im/paralect/robomongo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
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.
|
||||
|
||||
What's new in latest Robomongo 1.0?
|
||||
====================================
|
||||
Latest release of Robomongo 1.0 includes:
|
||||
- Update Notifications Bar
|
||||
- Welcome Tab
|
||||
- Welcome Wizard
|
||||
- Replica set name configurable on UI
|
||||
- Fixes to avoid same replica set name problem
|
||||
- Fixes to solve various problems regarding Data and Timestamp data types
|
||||
|
||||
Blog: http://blog.robomongo.org/robomongo-1-0/
|
||||
Blog: http://blog.robomongo.org/robo-3t-1-4/
|
||||
Download: https://robomongo.org/download
|
||||
Watch: [Robomongo Youtube channel](https://www.youtube.com/channel/UCM_7WAseRWeeiBikExppstA)
|
||||
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
|
||||
|
||||
What's Planned for the Next Releases?
|
||||
**Embedded MongoDB shell history:**
|
||||
Robo 3T 1.3 upgraded to MongoDB 4.0
|
||||
Robo 3T 1.1 upgraded to MongoDB 3.4
|
||||
Robo 3T 0.9 upgraded to MongoDB 3.2
|
||||
Robo 3T 0.8.x embeds 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?
|
||||
====================================
|
||||
|
||||
We are currently working towards [Robomongo 2.0 milestone](https://github.com/paralect/robomongo/milestone/21).
|
||||
|
||||
Currently in progress:
|
||||
- MongoDB 3.4 Support
|
||||
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)
|
||||
|
||||
Plans for Future:
|
||||
- User Roles
|
||||
- Support execution of multiple simultaneous queries [#1161](https://github.com/paralect/robomongo/issues/1161)
|
||||
- Selectable mongodb engines [#1249](https://github.com/paralect/robomongo/issues/1249)
|
||||
- Enhancements for stability, running without crashes ([Stability Milestone](https://github.com/paralect/robomongo/milestone/15))
|
||||
- More Documentation
|
||||
- Unit Tests
|
||||
- Refactoring Debug Log module
|
||||
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
|
||||
===============
|
||||
|
||||
| MongoDB Versions |
|
||||
| :-------------------- |
|
||||
| 3.2 |
|
||||
| 3.0 |
|
||||
| 2.6 |
|
||||
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 Cloud Platforms|
|
||||
| :------------ |
|
||||
| MongoDB Atlas |
|
||||
| Compose |
|
||||
| mLab |
|
||||
| ObjectRocket |
|
||||
| Amazon EC2 |
|
||||
| MongoDB Versions | MongoDB Cloud Platforms |
|
||||
| :-------------------- | :-------------------- |
|
||||
| 4.2 | Mongo Atlas |
|
||||
| 4.0 |
|
||||
| 3.6 |
|
||||
|
||||
| Windows | Mac | Linux |
|
||||
|:---------------------- | :---------------| :---------------------------|
|
||||
| Windows 64-bit 10 | Mac OS X 10.11 | Linux Ubuntu 16.04 64-bit* |
|
||||
Windows 64-bit 8.1 | Mac OS X 10.10 | Linux Ubuntu 14.04 64-bit* |
|
||||
| Windows 64-bit 7 | | Linux CentOS 7 64-bit* |
|
||||
| | | Linux CentOS 6 64-bit* |
|
||||
|
||||
\* latest stable build
|
||||
| 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 1.0**](http://blog.robomongo.org/robomongo-1-0/).
|
||||
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:
|
||||
|
||||
@@ -84,13 +78,6 @@ You can:
|
||||
|
||||
- [Join developer discussion on Gitter](https://gitter.im/paralect/robomongo)
|
||||
|
||||
Build
|
||||
=====
|
||||
|
||||
The wiki contains prerequisites and instructions to [Build Robomongo](https://github.com/paralect/robomongo/wiki).
|
||||
|
||||
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).
|
||||
|
||||
Contribute!
|
||||
===========
|
||||
|
||||
@@ -104,8 +91,9 @@ This project is powered by open source volunteers, so we have a limited amount o
|
||||
### Code Contributions
|
||||
|
||||
Code contributions are always welcome! Just try to follow our pre-commit checks and coding style:
|
||||
- [Robomongo Code Quality](https://github.com/paralect/robomongo/wiki/Robomongo-Code-Quality)
|
||||
- [Robomongo Coding Style](https://github.com/paralect/robomongo/wiki/Robomongo-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.
|
||||
|
||||
@@ -128,7 +116,7 @@ There are a number of issues we could use help with reproducing. They are marked
|
||||
License
|
||||
=======
|
||||
|
||||
Copyright 2014-2017 [3T Software Labs Ltd](https://studio3t.com/). All rights reserved.
|
||||
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,12 @@
|
||||
#!/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 cmake --build . "${@:2}" -- -j8
|
||||
# Hint: Use "--use-analyzer /usr/local/opt/llvm/bin/clang++" after "-v"
|
||||
@@ -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,14 @@
|
||||
#!/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 cmake -D "CMAKE_PREFIX_PATH=$PREFIX_PATH" -D "CMAKE_BUILD_TYPE=$BUILD_TYPE" -D "CMAKE_INSTALL_PREFIX=$INSTALL_PREFIX" "${@:2}" $PROJECT_DIR
|
||||
# Hint: Use "--use-analyzer /usr/local/opt/llvm/bin/clang++" after "-v"
|
||||
@@ -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" %*
|
||||
@@ -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
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
# 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"
|
||||
@@ -22,12 +21,7 @@ find_path(
|
||||
|
||||
# Find OpenSSL version
|
||||
#-------------------------------------------
|
||||
|
||||
if(SYSTEM_WINDOWS)
|
||||
set (OPENSSL_INCLUDE_DIR "${OpenSSL_DIR}/inc32")
|
||||
else()
|
||||
set (OPENSSL_INCLUDE_DIR "${OpenSSL_DIR}/include")
|
||||
endif()
|
||||
set (OPENSSL_INCLUDE_DIR "${OpenSSL_DIR}/include")
|
||||
|
||||
function(from_hex HEX DEC)
|
||||
string(TOUPPER "${HEX}" HEX)
|
||||
@@ -106,33 +100,30 @@ 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}/inc32"
|
||||
IMPORTED_IMPLIB "${OpenSSL_DIR}/out32dll/ssleay32.lib"
|
||||
)
|
||||
set_target_properties(crypto PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/inc32"
|
||||
IMPORTED_IMPLIB "${OpenSSL_DIR}/out32dll/libeay32.lib"
|
||||
)
|
||||
elseif(SYSTEM_MACOSX)
|
||||
set_target_properties(ssl PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_LOCATION "${OpenSSL_DIR}/libssl.dylib"
|
||||
IMPORTED_IMPLIB "${OpenSSL_DIR}/libssl.lib"
|
||||
)
|
||||
set_target_properties(crypto PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_LOCATION "${OpenSSL_DIR}/libcrypto.dylib"
|
||||
)
|
||||
elseif(SYSTEM_LINUX)
|
||||
set_target_properties(ssl PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_LOCATION "${OpenSSL_DIR}/libssl.so"
|
||||
)
|
||||
set_target_properties(crypto PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${OpenSSL_DIR}/include"
|
||||
IMPORTED_LOCATION "${OpenSSL_DIR}/libcrypto.so"
|
||||
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,17 +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("| Qt5 Network: ${Qt5Network_VERSION} ${Qt5Network_DIR}")
|
||||
message("| Qt5 Xml: ${Qt5Xml_VERSION} ${Qt5Xml_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("|")
|
||||
@@ -20,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("")
|
||||
|
||||
@@ -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 .)
|
||||
@@ -60,14 +62,14 @@ install(
|
||||
if(SYSTEM_WINDOWS)
|
||||
install(
|
||||
FILES
|
||||
"${OpenSSL_DIR}/out32dll/ssleay32.dll"
|
||||
"${OpenSSL_DIR}/out32dll/libeay32.dll"
|
||||
"${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.0.0.dylib"
|
||||
"${OpenSSL_DIR}/libcrypto.1.0.0.dylib"
|
||||
"${OpenSSL_DIR}/libssl.1.1.dylib"
|
||||
"${OpenSSL_DIR}/libcrypto.1.1.dylib"
|
||||
DESTINATION ${lib_dir}/lib)
|
||||
elseif(SYSTEM_LINUX)
|
||||
install(
|
||||
@@ -98,12 +100,18 @@ install(
|
||||
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(
|
||||
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(
|
||||
@@ -115,12 +123,18 @@ elseif(SYSTEM_MACOSX)
|
||||
install(
|
||||
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
|
||||
|
||||
@@ -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})
|
||||
@@ -35,9 +35,9 @@ set(CPACK_STRIP_FILES ON)
|
||||
|
||||
# Additional information
|
||||
set(CPACK_PACKAGE_VENDOR "3T Software Labs Ltd")
|
||||
set(CPACK_PACKAGE_CONTACT robomongo@3t.io)
|
||||
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")
|
||||
|
||||
@@ -15,13 +15,13 @@ elseif(SYSTEM_WINDOWS)
|
||||
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 "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/paralect/robomongo")
|
||||
set(PROJECT_GITHUB_ISSUES "www.github.com/paralect/robomongo/issues")
|
||||
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,6 +1,10 @@
|
||||
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,6 +1,10 @@
|
||||
Building Robomongo (Mac OS X and Linux)
|
||||
==================
|
||||
|
||||
**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
|
||||
-------------
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
Building Robomongo (Windows)
|
||||
==============================
|
||||
|
||||
**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
|
||||
-------------
|
||||
|
||||
|
||||
@@ -12,26 +12,30 @@ Runtime dependencies that are not privided by platforms but required by Robomong
|
||||
Diagnostic of dependencies
|
||||
--------------------------
|
||||
|
||||
#### Linux
|
||||
### Windows
|
||||
|
||||
a. View dependencies of executable or shared library:
|
||||
GUI: http://dependencywalker.com/
|
||||
|
||||
### Linux
|
||||
|
||||
#### a. View dependencies of executable or shared library:
|
||||
|
||||
$ ldd robomongo
|
||||
$ readelf -d robomongo
|
||||
|
||||
b. View dependency tree of executable or shared library:
|
||||
#### 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:
|
||||
#### 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`
|
||||
|
||||
d. Enable extensive logging for run-time shared library search
|
||||
#### d. Enable extensive logging for run-time shared library search
|
||||
|
||||
$ export LD_DEBUG=files
|
||||
$ bin/robomongo
|
||||
@@ -39,7 +43,7 @@ d. Enable extensive logging for run-time shared library search
|
||||
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`
|
||||
#### e. Modify RPATH using `chrpath` and the dynamic linker and RPATH using paths `patchelf`
|
||||
|
||||
$ patchelf --set-rpath '$ORIGIN/../lib' robo
|
||||
|
||||
@@ -51,7 +55,57 @@ More:
|
||||
https://linux.die.net/man/1/chrpath
|
||||
http://www.programering.com/a/MTOwcDNwATU.html // examples
|
||||
|
||||
#### Mac OS X
|
||||
#### 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:
|
||||
|
||||
@@ -65,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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ IDI_ICON1 ICON "@windows_icon@"
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "3T Software Labs Ltd\0"
|
||||
VALUE "FileDescription", "Robomongo, MongoDB management tool\0"
|
||||
VALUE "FileDescription", "Robo 3T, MongoDB management tool\0"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "LegalCopyright", "Copyright 3T Software Labs Ltd, 2014 - 2017\0"
|
||||
VALUE "ProductName", "Robomongo\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 |
@@ -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()
|
||||
@@ -28,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
|
||||
@@ -56,8 +53,10 @@ set(SOURCES
|
||||
core/mongodb/ReplicaSet.cpp
|
||||
core/settings/SettingsManager.cpp
|
||||
core/AppRegistry.cpp
|
||||
utils/string_operations.cpp
|
||||
utils/StringOperations.cpp
|
||||
utils/common.cpp
|
||||
utils/SimpleCrypt.cpp
|
||||
utils/RoboCrypt.cpp
|
||||
|
||||
# Isolated Scope #3
|
||||
gui/GuiRegistry.cpp
|
||||
@@ -79,18 +78,20 @@ set(SOURCES
|
||||
# Isolated scope #4
|
||||
gui/dialogs/PreferencesDialog.cpp
|
||||
gui/dialogs/ConnectionsDialog.cpp
|
||||
gui/dialogs/CreateConnectionDialog.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
|
||||
@@ -141,7 +142,6 @@ set(SOURCES
|
||||
gui/resources/gui.qrc
|
||||
)
|
||||
|
||||
|
||||
# Robomongo target
|
||||
add_executable(robomongo MACOSX_BUNDLE WIN32 app/main.cpp ${SOURCES})
|
||||
|
||||
@@ -156,12 +156,45 @@ target_link_libraries(robomongo
|
||||
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}"
|
||||
@@ -172,8 +205,16 @@ target_compile_definitions(robomongo
|
||||
PROJECT_GITHUB_ISSUES="${PROJECT_GITHUB_ISSUES}"
|
||||
PROJECT_VERSION="${PROJECT_VERSION}"
|
||||
PROJECT_VERSION_SHORT="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
PROJECT_QT_VERSION="${Qt5Core_VERSION}"
|
||||
PROJECT_NAME_LOWERCASE="${PROJECT_NAME_LOWERCASE}")
|
||||
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
|
||||
@@ -184,27 +225,26 @@ 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.3tsoftwarelabs.robomongo"
|
||||
MACOSX_BUNDLE_INFO_STRING "Robomongo ${PROJECT_VERSION}. Copyright 3T Software Labs Ltd, 2014 - 2017"
|
||||
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}"
|
||||
@@ -214,16 +254,14 @@ elseif(SYSTEM_MACOSX)
|
||||
elseif(SYSTEM_LINUX)
|
||||
set_target_properties(robomongo PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN/../lib"
|
||||
OUTPUT_NAME "robomongo")
|
||||
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,17 +6,22 @@
|
||||
// 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)
|
||||
{
|
||||
@@ -39,6 +44,18 @@ int main(int argc, char *argv[], char** envp)
|
||||
|
||||
// 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);
|
||||
@@ -55,27 +72,40 @@ int main(int argc, char *argv[], char** envp)
|
||||
#ifdef Q_OS_MAC
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
|
||||
|
||||
// EULA License Agreement
|
||||
auto const settingsManager = Robomongo::AppRegistry::instance().settingsManager();
|
||||
if (!settingsManager->acceptedEulaVersions().contains(PROJECT_VERSION)) {
|
||||
Robomongo::EulaDialog eulaDialog;
|
||||
if (eulaDialog.exec() == QDialog::Rejected) {
|
||||
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
|
||||
settingsManager->addAcceptedEulaVersion(PROJECT_VERSION);
|
||||
settingsManager->save();
|
||||
}
|
||||
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 mainWindow;
|
||||
mainWindow.show();
|
||||
|
||||
for(auto const& msgAndSeverity : Robomongo::RoboCrypt::roboCryptLogs())
|
||||
Robomongo::LOG_MSG(msgAndSeverity.first, msgAndSeverity.second);
|
||||
|
||||
int rc = app.exec();
|
||||
rbm_ssh_cleanup();
|
||||
return rc;
|
||||
|
||||
@@ -31,6 +31,7 @@ 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)
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
#include "robomongo/core/EventError.h"
|
||||
|
||||
#include "robomongo/utils/string_operations.h"
|
||||
#include "robomongo/utils/StringOperations.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Robomongo
|
||||
|
||||
const char *p = s.c_str();
|
||||
for (size_t i = 0; i < bytes; i++) {
|
||||
data[i] = mongo::fromHex(p);
|
||||
data[i] = mongo::fromHex(p).getValue();
|
||||
p += 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +1,8 @@
|
||||
#include "robomongo/core/domain/App.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "robomongo/core/domain/MongoServer.h"
|
||||
#include "robomongo/core/domain/MongoShell.h"
|
||||
@@ -35,6 +37,9 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
App::~App()
|
||||
{}
|
||||
|
||||
App::App(EventBus *const bus) : QObject(),
|
||||
_bus(bus), _lastServerHandle(0) {
|
||||
_bus->subscribe(this, EstablishSshConnectionResponse::Type);
|
||||
@@ -42,14 +47,68 @@ namespace Robomongo
|
||||
_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;
|
||||
}
|
||||
|
||||
bool App::openServer(ConnectionSettings *connection, ConnectionType type) {
|
||||
/**
|
||||
* 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 SECONDARY or do not have
|
||||
// ssh settings enabled, continue without SSH Tunnel
|
||||
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(connSettings->sshSettings()->host()))
|
||||
.arg(connSettings->sshSettings()->port()), mongo::logger::LogSeverity::Info());
|
||||
|
||||
ConnectionSettings* settingsCopy = connSettings->clone();
|
||||
SshTunnelWorker* sshWorker = new SshTunnelWorker(settingsCopy);
|
||||
_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() &&
|
||||
@@ -97,67 +156,43 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
openServerInternal(connection, type);
|
||||
_servers.push_back(move(openServerInternal(connection, type)));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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::openServerInternal(ConnectionSettings* connSettings, ConnectionType type) {
|
||||
++_lastServerHandle;
|
||||
|
||||
if (type == ConnectionPrimary)
|
||||
_bus->publish(new ConnectingEvent(this));
|
||||
|
||||
// When connection is SECONDARY or do not have
|
||||
// ssh settings enabled, continue without SSH Tunnel
|
||||
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(connSettings->sshSettings()->host()))
|
||||
.arg(connSettings->sshSettings()->port()), mongo::logger::LogSeverity::Info());
|
||||
|
||||
ConnectionSettings* settingsCopy = connSettings->clone();
|
||||
SshTunnelWorker* sshWorker = new SshTunnelWorker(settingsCopy);
|
||||
_bus->send(sshWorker, new EstablishSshConnectionRequest(this, _lastServerHandle, sshWorker, settingsCopy, type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes MongoServer connection and frees all resources, owned
|
||||
* by MongoServer. Finally, specified MongoServer will also be deleted.
|
||||
*/
|
||||
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());
|
||||
}
|
||||
|
||||
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({})");
|
||||
openShell(collection->database()->server(), 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)
|
||||
);
|
||||
}
|
||||
|
||||
void App::openShell(MongoServer *server, const QString &script, const std::string &dbName,
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition, const QString &filePathToSave)
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = server->connectionRecord();
|
||||
|
||||
if (!dbName.empty())
|
||||
connection->setDefaultDatabase(dbName);
|
||||
|
||||
openShell(server, connection, ScriptInfo(script, execute, cursorPosition, shellName, filePathToSave));
|
||||
openShell(server, connection,
|
||||
ScriptInfo(script, execute, dbName, cursorPosition, shellName, filePathToSave)
|
||||
);
|
||||
}
|
||||
|
||||
void App::openShell(MongoDatabase *database, const QString &script,
|
||||
@@ -166,22 +201,23 @@ namespace Robomongo
|
||||
{
|
||||
ConnectionSettings *connection = database->server()->connectionRecord();
|
||||
connection->setDefaultDatabase(database->name());
|
||||
openShell(database->server(), connection, ScriptInfo(script, execute, cursorPosition,
|
||||
shellName, filePathToSave));
|
||||
openShell(database->server(), connection, ScriptInfo(script, execute, database->name(),
|
||||
cursorPosition, shellName, filePathToSave));
|
||||
}
|
||||
|
||||
void App::openShell(MongoServer* server, ConnectionSettings* connection, const ScriptInfo &scriptInfo)
|
||||
{
|
||||
MongoServer *serverClone = openServerInternal(connection, ConnectionSecondary);
|
||||
auto serverClone{ openServerInternal(connection, ConnectionSecondary) };
|
||||
if (!serverClone || !server)
|
||||
return;
|
||||
|
||||
MongoShell *shell = new MongoShell(serverClone, scriptInfo);
|
||||
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);
|
||||
_shells.push_back(shell);
|
||||
_bus->publish(new OpeningShellEvent(this, shell));
|
||||
_bus->subscribe(server, ReplicaSetRefreshed::Type, shell.get());
|
||||
_bus->publish(new OpeningShellEvent(this, shell.get()));
|
||||
shell->execute();
|
||||
_shells.push_back(move(shell));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -191,45 +227,16 @@ 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(int serverHandle, ConnectionSettings* connSettings, ConnectionType type,
|
||||
int localport)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
MongoServer *server = new MongoServer(serverHandle, connSettingsClone, type);
|
||||
_servers.push_back(server);
|
||||
|
||||
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;
|
||||
_shells.erase(itr);
|
||||
}
|
||||
|
||||
void App::handle(EstablishSshConnectionResponse *event) {
|
||||
@@ -242,26 +249,31 @@ namespace Robomongo
|
||||
|
||||
LOG_MSG(QString("SSH tunnel created successfully"), mongo::logger::LogSeverity::Info());
|
||||
|
||||
continueOpenServer(event->serverHandle, event->settings, event->connectionType, event->localport);
|
||||
_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::RBM_ERROR) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Error());
|
||||
} else if (event->level == LogEvent::RBM_WARN) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Warning());
|
||||
} else if (event->level == LogEvent::RBM_INFO) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Info());
|
||||
} else if (event->level == LogEvent::RBM_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->serverHandle, event->connectionType, event->error().errorMessage(),
|
||||
ConnectionFailedEvent::SshChannel));
|
||||
_bus->publish(
|
||||
new ConnectionFailedEvent(this, event->serverHandle, event->connectionType,
|
||||
event->error().errorMessage(), ConnectionFailedEvent::SshChannel)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -287,7 +299,7 @@ namespace Robomongo
|
||||
|
||||
s << std::endl << "Enter your PEM key passphrase (will never be stored):";
|
||||
|
||||
QString userInput = QInputDialog::getText(NULL, tr("SSL Authentication"),
|
||||
QString userInput = QInputDialog::getText(NULL, tr("TLS Authentication"),
|
||||
QtUtils::toQString(s.str()),
|
||||
QLineEdit::Password, "", &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();
|
||||
|
||||
@@ -63,19 +61,20 @@ namespace Robomongo
|
||||
void openShell(MongoCollection *collection, const QString &filePathToSave = 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());
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &file = QString());
|
||||
|
||||
void openShell(MongoDatabase *database, const QString &script,
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &filePathToSave = QString());
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(),
|
||||
const QString &filePathToSave = QString());
|
||||
|
||||
/**
|
||||
* @brief Open new shell using explorer's MongoServer (ExplorerServerTreeItem's _server)
|
||||
*/
|
||||
void openShell(MongoServer* server, ConnectionSettings* connSettings, const ScriptInfo &scriptInfo);
|
||||
|
||||
MongoServersContainerType getServers() const { return _servers; };
|
||||
auto const& getServers() const { return _servers; };
|
||||
|
||||
/**
|
||||
* @brief Closes MongoShell and frees all resources, owned by specified MongoShell.
|
||||
@@ -83,7 +82,8 @@ namespace Robomongo
|
||||
*/
|
||||
void closeShell(MongoShell *shell);
|
||||
|
||||
void fireConnectionFailedEvent(int serverHandle, ConnectionType type, std::string errormsg, ConnectionFailedEvent::Reason reason);
|
||||
void fireConnectionFailedEvent(int serverHandle, ConnectionType type, std::string errormsg,
|
||||
ConnectionFailedEvent::Reason reason);
|
||||
|
||||
int getLastServerHandle() const { return _lastServerHandle; };
|
||||
|
||||
@@ -93,8 +93,10 @@ namespace Robomongo
|
||||
void handle(LogEvent *event);
|
||||
|
||||
private:
|
||||
MongoServer *openServerInternal(ConnectionSettings* connSettings, ConnectionType type);
|
||||
MongoServer *continueOpenServer(int serverHandle, ConnectionSettings* connSettings, ConnectionType type, 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
|
||||
@@ -106,12 +108,12 @@ namespace Robomongo
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -81,39 +81,35 @@ namespace Robomongo
|
||||
_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->worker(), new CreateUserRequest(this, _name, user, overwrite));
|
||||
_bus->send(_server->worker(), new CreateUserRequest(this, _name, user));
|
||||
}
|
||||
|
||||
void MongoDatabase::dropUser(const mongo::OID &id, std::string const& userName)
|
||||
void MongoDatabase::dropUser(std::string const& userName)
|
||||
{
|
||||
_bus->send(_server->worker(), new DropUserRequest(this, _name, id, userName));
|
||||
_bus->send(_server->worker(), new DropUserRequest(this, _name, userName));
|
||||
}
|
||||
|
||||
void MongoDatabase::createFunction(const MongoFunction &fun)
|
||||
{
|
||||
_bus->send(_server->worker(), 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->worker(), 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->worker(), new DropFunctionRequest(this, _name, name));
|
||||
_bus->send(_server->worker(), new DropFunctionRequest(this, _name, _server->version(), name));
|
||||
}
|
||||
|
||||
void MongoDatabase::handle(LoadCollectionNamesResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
if (_server->connectionRecord()->isReplicaSet()) // replica set
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
else // single server
|
||||
_bus->publish(new MongoDatabaseCollectionListLoadedEvent(this, event->error()));
|
||||
|
||||
_bus->publish(new MongoDatabaseCollectionListLoadedEvent(this, event->error()));
|
||||
genericEventErrorHandler(event, "Failed to refresh 'Collections'.", _bus, this);
|
||||
return;
|
||||
}
|
||||
@@ -154,10 +150,10 @@ namespace Robomongo
|
||||
void MongoDatabase::handle(LoadUsersResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
_bus->publish(new MongoDatabaseUsersLoadedEvent(this, event->error()));
|
||||
|
||||
if (_server->connectionRecord()->isReplicaSet()) // replica set
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
else // single server
|
||||
_bus->publish(new MongoDatabaseUsersLoadedEvent(this, event->error()));
|
||||
|
||||
genericEventErrorHandler(event, "Failed to refresh 'Users'.", _bus, this);
|
||||
return;
|
||||
@@ -170,10 +166,10 @@ namespace Robomongo
|
||||
void MongoDatabase::handle(LoadFunctionsResponse *event)
|
||||
{
|
||||
if (event->isError()) {
|
||||
_bus->publish(new MongoDatabaseFunctionsLoadedEvent(this, event->error()));
|
||||
|
||||
if (_server->connectionRecord()->isReplicaSet()) // replica set
|
||||
handleIfReplicaSetUnreachable(event);
|
||||
else // single server
|
||||
_bus->publish(new MongoDatabaseFunctionsLoadedEvent(this, event->error()));
|
||||
|
||||
genericEventErrorHandler(event, "Failed to refresh 'Functions'.", _bus, this);
|
||||
return;
|
||||
|
||||
@@ -62,8 +62,8 @@ namespace Robomongo
|
||||
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, std::string const& userName);
|
||||
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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#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
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "robomongo/core/domain/MongoQueryInfo.h"
|
||||
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
|
||||
@@ -13,13 +13,17 @@
|
||||
#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/string_operations.h"
|
||||
#include "robomongo/utils/StringOperations.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace Robomongo {
|
||||
R_REGISTER_EVENT(MongoServerLoadingDatabasesEvent)
|
||||
|
||||
MongoServer::MongoServer(int handle, ConnectionSettings *settings, ConnectionType connectionType) : QObject(),
|
||||
MongoServer::MongoServer(int handle, ConnectionSettings *settings, ConnectionType connectionType)
|
||||
: QObject(),
|
||||
_version(0.0f),
|
||||
_connectionType(connectionType),
|
||||
_worker(nullptr),
|
||||
@@ -217,6 +221,16 @@ namespace Robomongo {
|
||||
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(RefreshReplicaSetFolderResponse *event)
|
||||
@@ -233,10 +247,8 @@ namespace Robomongo {
|
||||
|
||||
clearDatabases();
|
||||
|
||||
for (auto const& dbname : event->databaseNames) {
|
||||
MongoDatabase *db = new MongoDatabase(this, dbname);
|
||||
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(),
|
||||
@@ -246,6 +258,7 @@ namespace Robomongo {
|
||||
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()) {
|
||||
@@ -263,11 +276,10 @@ namespace Robomongo {
|
||||
_bus->publish(new InsertDocumentResponse(this, event->error()));
|
||||
LOG_MSG("Document inserted.", mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MongoServer::handle(RemoveDocumentResponse *event)
|
||||
{
|
||||
{
|
||||
if (event->removeCount == RemoveDocumentCount::MULTI && event->index > 0)
|
||||
return;
|
||||
|
||||
@@ -280,6 +292,7 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
if (event->isError()) {
|
||||
hideProgressBar();
|
||||
if (_connSettings->isReplicaSet() &&
|
||||
EventError::SetPrimaryUnreachable == event->error().errorCode()) {
|
||||
auto refreshEvent = ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo());
|
||||
@@ -339,6 +352,11 @@ namespace Robomongo {
|
||||
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)
|
||||
{
|
||||
@@ -444,7 +462,7 @@ namespace Robomongo {
|
||||
auto reason = ConnectionFailedEvent::SslConnection;
|
||||
ss.clear();
|
||||
ss << "Cannot connect to the MongoDB at " << connectionRecord()->getFullAddress()
|
||||
<< ".\n\nError:\n" << "SSL connection failure: " << event->error().errorMessage();
|
||||
<< ".\n\nError:\n" << "TLS connection failure: " << event->error().errorMessage();
|
||||
_app->fireConnectionFailedEvent(_handle, _connectionType, ss.str(), reason);
|
||||
}
|
||||
else
|
||||
@@ -469,4 +487,16 @@ namespace Robomongo {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -105,6 +105,8 @@ namespace Robomongo
|
||||
|
||||
void handle(ReplicaSetRefreshed *event);
|
||||
|
||||
void changeWorkerShellTimeout(int newTimeout);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void handle(EstablishConnectionResponse *event);
|
||||
void handle(RefreshReplicaSetFolderResponse *event);
|
||||
@@ -120,6 +122,7 @@ namespace Robomongo
|
||||
bool expanded);
|
||||
void updateReplicaSetSettings(EstablishConnectionResponse* event);
|
||||
void handleConnectionFailure(EstablishConnectionResponse* event);
|
||||
void hideProgressBar() const;
|
||||
|
||||
MongoWorker *_worker;
|
||||
std::unique_ptr<ConnectionSettings> _connSettings;
|
||||
|
||||
@@ -12,19 +12,20 @@
|
||||
|
||||
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->worker(), new ExecuteScriptRequest(this, query(), dbName));
|
||||
eventBus()->send(_server->worker(), new ExecuteScriptRequest(this, query(), dbName));
|
||||
LOG_MSG(_scriptInfo.script(), mongo::logger::LogSeverity::Info());
|
||||
}
|
||||
|
||||
@@ -33,31 +34,36 @@ 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->worker(), 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->worker(), 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->worker(), 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->worker(), new AutocompleteRequest(this, prefix, autocompletionMode));
|
||||
|
||||
eventBus()->send(_server->worker(),
|
||||
new AutocompleteRequest(this, prefix, autocompletionMode)
|
||||
);
|
||||
}
|
||||
|
||||
void MongoShell::stop()
|
||||
@@ -84,39 +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()) {
|
||||
if (_server->connectionRecord()->isReplicaSet()) {
|
||||
AppRegistry::instance().bus()->publish(
|
||||
new ReplicaSetRefreshed(this, event->error(), event->error().replicaSetInfo()));
|
||||
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutedEvent(this, event->error()));
|
||||
return;
|
||||
}
|
||||
else { // single server
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutedEvent(this, event->error()));
|
||||
return;
|
||||
}
|
||||
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());
|
||||
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,76 @@
|
||||
#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);
|
||||
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 = "") :
|
||||
_error(error), _errorMessage(errorMsg) { }
|
||||
MongoShellExecResult(bool error, std::string const& errorMsg = "", bool timeoutReached = false) :
|
||||
_error(error), _errorMessage(errorMsg), _timeoutReached(timeoutReached) { }
|
||||
|
||||
std::vector<MongoShellResult> results() const { return _results; }
|
||||
std::vector<MongoShellResult> const& results() const { return _results; }
|
||||
std::string currentServer() const { return _currentServer; }
|
||||
void setCurrentServer(std::string const& server) { _currentServer = server; }
|
||||
std::string currentDatabase() const { return _currentDatabase; }
|
||||
@@ -45,6 +78,7 @@ namespace Robomongo
|
||||
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;
|
||||
@@ -54,5 +88,6 @@ namespace Robomongo
|
||||
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"
|
||||
@@ -138,8 +142,9 @@ 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;
|
||||
@@ -220,12 +225,14 @@ namespace Robomongo
|
||||
RemoveDocumentCount::MULTI;
|
||||
_shell->server()->removeDocuments(query, _queryInfo._info._ns, removeCount, index);
|
||||
++index;
|
||||
mainWindow()->showQueryWidgetProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
void Notifier::handle(InsertDocumentResponse *event)
|
||||
{
|
||||
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()) {
|
||||
@@ -235,11 +242,12 @@ namespace Robomongo
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -249,8 +257,10 @@ namespace Robomongo
|
||||
if (!(event->removeCount == RemoveDocumentCount::MULTI && event->index > 0))
|
||||
QMessageBox::warning(NULL, "Database Error", QString::fromStdString(event->error().errorMessage()));
|
||||
}
|
||||
else // Success
|
||||
_shell->query(0, _queryInfo);
|
||||
else { // Success
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
_shell->query(0, _queryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void Notifier::onCopyNameDocument()
|
||||
@@ -300,6 +310,16 @@ namespace Robomongo
|
||||
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)
|
||||
@@ -358,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +417,7 @@ namespace Robomongo
|
||||
json, true, dynamic_cast<QWidget*>(_observer));
|
||||
|
||||
editor->setWindowTitle("View Document");
|
||||
editor->exec();
|
||||
editor->show();
|
||||
}
|
||||
|
||||
void Notifier::onInsertDocument()
|
||||
@@ -420,6 +438,7 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
class MainWindow;
|
||||
class MongoShell;
|
||||
class BsonTreeItem;
|
||||
class InsertDocumentResponse;
|
||||
@@ -65,6 +66,8 @@ namespace Robomongo
|
||||
void onCopyPathDocument();
|
||||
|
||||
private:
|
||||
MainWindow* mainWindow() const;
|
||||
|
||||
QAction *_deleteDocumentAction;
|
||||
QAction *_deleteDocumentsAction;
|
||||
QAction *_editDocumentAction;
|
||||
|
||||
@@ -62,10 +62,11 @@ namespace
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
ScriptInfo::ScriptInfo(const QString &script, bool execute, const CursorPosition &position,
|
||||
const QString &title, const QString &filePath) :
|
||||
ScriptInfo::ScriptInfo(const QString &script, bool execute, const std::string &dbname,
|
||||
const CursorPosition &position, const QString &title, const QString &filePath) :
|
||||
_script(script),
|
||||
_execute(execute),
|
||||
_dbname(dbname),
|
||||
_title(title),
|
||||
_cursor(position),
|
||||
_filePath(filePath) {}
|
||||
|
||||
@@ -9,12 +9,14 @@ namespace Robomongo
|
||||
class ScriptInfo
|
||||
{
|
||||
public:
|
||||
ScriptInfo(const QString &script, bool execute = false,
|
||||
ScriptInfo(const QString &script, bool execute = false, const std::string &dbname = "",
|
||||
const CursorPosition &position = CursorPosition(),
|
||||
const QString &title = QString(), const QString &filePath = QString());
|
||||
|
||||
bool execute() const { return _execute; }
|
||||
void setExecutable(bool execute) { _execute = execute; }
|
||||
QString script() const { return _script; }
|
||||
std::string dbname() const { return _dbname; }
|
||||
const QString &title() const { return _title; }
|
||||
const CursorPosition &cursor() const { return _cursor; }
|
||||
void setScript(const QString &script) { _script = script; }
|
||||
@@ -26,7 +28,8 @@ namespace Robomongo
|
||||
|
||||
private:
|
||||
QString _script;
|
||||
const bool _execute;
|
||||
std::string _dbname;
|
||||
bool _execute;
|
||||
const QString _title;
|
||||
const CursorPosition _cursor;
|
||||
QString _filePath;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//#include <third_party/js-1.7/jsstr.h>
|
||||
|
||||
#include <mongo/util/assert_util.h>
|
||||
#include <mongo/util/exit_code.h>
|
||||
#include <mongo/scripting/engine.h>
|
||||
|
||||
// v0.9
|
||||
@@ -23,12 +24,14 @@
|
||||
|
||||
#include <mongo/shell/shell_utils.h>
|
||||
#include <mongo/base/string_data.h>
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
#include <pcrecpp.h>
|
||||
|
||||
#include "robomongo/core/events/MongoEvents.h"
|
||||
#include "robomongo/core/settings/ConnectionSettings.h"
|
||||
#include "robomongo/core/settings/CredentialSettings.h"
|
||||
#include "robomongo/core/domain/MongoDocument.h"
|
||||
#include "robomongo/core/utils/Logger.h"
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
|
||||
namespace
|
||||
@@ -50,7 +53,6 @@ namespace
|
||||
namespace mongo {
|
||||
extern bool isShell;
|
||||
void logProcessDetailsForLogRotate() {}
|
||||
void exitCleanly(ExitCode code) {}
|
||||
}
|
||||
|
||||
namespace Robomongo
|
||||
@@ -91,19 +93,18 @@ namespace Robomongo
|
||||
<< _connection->primaryCredential()->userPassword() << "')";
|
||||
|
||||
{
|
||||
mongo::shell_utils::_dbConnect = ss.str();
|
||||
mongo::shell_utils::_dbAuth = "(function() { \nDB.prototype._defaultGssapiServiceName = \"mongodb\";\n}())";
|
||||
mongo::shell_utils::dbConnect = ss.str();
|
||||
|
||||
// v0.9
|
||||
// mongo::isShell = true;
|
||||
|
||||
mongo::ScriptEngine::setConnectCallback( mongo::shell_utils::onConnect );
|
||||
mongo::ScriptEngine::setup();
|
||||
mongo::globalScriptEngine->setScopeInitCallback(mongo::shell_utils::initScope);
|
||||
mongo::globalScriptEngine->enableJIT(true);
|
||||
mongo::ScriptEngine::setup();
|
||||
mongo::getGlobalScriptEngine()->setScopeInitCallback(mongo::shell_utils::initScope);
|
||||
mongo::getGlobalScriptEngine()->enableJIT(true);
|
||||
|
||||
_scope.reset(mongo::globalScriptEngine->newScope());
|
||||
_engine = mongo::globalScriptEngine;
|
||||
_scope.reset(mongo::getGlobalScriptEngine()->newScope());
|
||||
_engine = mongo::getGlobalScriptEngine();
|
||||
|
||||
// Load '.mongorc.js' from user's home directory
|
||||
if (isLoadMongoRcJs) {
|
||||
@@ -137,7 +138,7 @@ namespace Robomongo
|
||||
|
||||
// Cache result of original "DB.autocomplete"
|
||||
// Cache invalidated by the invalidateDbCollectionsCache() method.
|
||||
std::string cacheAutocompletion =
|
||||
std::string const cacheAutocompletion =
|
||||
"__robomongoAutocompletionCache = null;"
|
||||
"DB.autocompleteCached = function(obj) { "
|
||||
" if (__robomongoAutocompletionCache == null) {"
|
||||
@@ -148,10 +149,26 @@ namespace Robomongo
|
||||
|
||||
_scope->exec(cacheAutocompletion, "", false, false, false);
|
||||
|
||||
// Capture aggregate parameters: pipeline, options
|
||||
std::string const aggregateInterceptor =
|
||||
"__robomongoAggregateUsed = false;"
|
||||
"__robomongoAggregate = DBCollection.prototype.aggregate;"
|
||||
"__robomongoAggregatePipeline = null;"
|
||||
"__robomongoAggregateOptions = null;"
|
||||
"DBCollection.prototype.aggregate = function(pipeline, options) { "
|
||||
" __robomongoAggregateUsed = true;"
|
||||
" __robomongoAggregatePipeline = pipeline;"
|
||||
" __robomongoAggregateOptions = options;"
|
||||
" return __robomongoAggregate.call(this, pipeline, options);"
|
||||
"}";
|
||||
|
||||
_scope->exec(aggregateInterceptor, "", false, false, false);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
MongoShellExecResult ScriptEngine::exec(const std::string &originalScript, const std::string &dbName)
|
||||
MongoShellExecResult ScriptEngine::exec(const std::string &originalScript, const std::string &dbName,
|
||||
AggrInfo aggrInfo /* = AggrInfo() */)
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
@@ -160,6 +177,9 @@ namespace Robomongo
|
||||
return MongoShellExecResult(true, "Connection error. Uninitialized mongo scope.");
|
||||
}
|
||||
|
||||
// robomongo shell timeout
|
||||
bool timeoutReached = false;
|
||||
|
||||
/*
|
||||
* Replace all commands ('show dbs', 'use db' etc.) with call
|
||||
* to shellHelper('show', 'dbs') and so on.
|
||||
@@ -179,17 +199,14 @@ namespace Robomongo
|
||||
std::string error;
|
||||
bool result = statementize(stdstr, statements, error);
|
||||
|
||||
if (!result && statements.size() == 0) {
|
||||
if (!result && statements.size() == 0)
|
||||
statements.push_back("print(__robomongoResult.error)");
|
||||
}
|
||||
|
||||
std::vector<MongoShellResult> results;
|
||||
|
||||
use(dbName);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = statements.begin(); it != statements.end(); ++it)
|
||||
{
|
||||
std::string statement = *it;
|
||||
for (auto const& statement : statements) {
|
||||
// clear global objects
|
||||
__objects.clear();
|
||||
__type = "";
|
||||
@@ -205,23 +222,27 @@ namespace Robomongo
|
||||
_scope->exec( "__robomongoLastRes = __lastres__; shellPrintHelper( __lastres__ );",
|
||||
"(shell2)" , true , true , false, _timeoutSec * 1000);
|
||||
}
|
||||
else { // failed to run script
|
||||
failed = true;
|
||||
}
|
||||
else // failed to run script
|
||||
failed = true;
|
||||
|
||||
qint64 elapsed = timer.elapsed();
|
||||
qint64 elapsed = timer.elapsed(); // milliseconds
|
||||
|
||||
if (elapsed > _timeoutSec * 1000)
|
||||
timeoutReached = true;
|
||||
|
||||
std::string logs = __logs.str();
|
||||
std::string answer = logs.c_str();
|
||||
std::string type = __type.c_str();
|
||||
|
||||
if (failed)
|
||||
if (failed && !timeoutReached)
|
||||
return MongoShellExecResult(true, answer);
|
||||
|
||||
std::vector<MongoDocumentPtr> docs = MongoDocument::fromBsonObj(__objects);
|
||||
|
||||
if (!answer.empty() || docs.size() > 0)
|
||||
results.push_back(prepareResult(type, answer, docs, elapsed));
|
||||
results.push_back(
|
||||
prepareResult(type, answer, docs, elapsed, statement, aggrInfo)
|
||||
);
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << "error:" << e.what() << std::endl;
|
||||
@@ -229,7 +250,7 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
return prepareExecResult(results);
|
||||
return prepareExecResult(results, timeoutReached);
|
||||
}
|
||||
|
||||
void ScriptEngine::interrupt()
|
||||
@@ -311,14 +332,17 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
MongoShellResult ScriptEngine::prepareResult(const std::string &type, const std::string &output,
|
||||
const std::vector<MongoDocumentPtr> &objects, qint64 elapsedms)
|
||||
const std::vector<MongoDocumentPtr> &objects, qint64 elapsedms,
|
||||
const std::string &statement, AggrInfo aggrInfo /*= AggrInfo()*/)
|
||||
{
|
||||
const char *script =
|
||||
"__robomongoQuery = false; \n"
|
||||
"__robomongoIsAggregate = false; \n"
|
||||
"__robomongoDbName = '[invalid database]'; \n"
|
||||
"__robomongoServerAddress = '[invalid connection]'; \n"
|
||||
"__robomongoCollectionName = '[invalid collection]'; \n"
|
||||
"if (typeof __robomongoLastRes == 'object' && __robomongoLastRes != null && __robomongoLastRes instanceof DBQuery) { \n"
|
||||
"if (typeof __robomongoLastRes == 'object' && __robomongoLastRes != null \n"
|
||||
" && __robomongoLastRes instanceof DBQuery) { \n"
|
||||
" __robomongoQuery = true; \n"
|
||||
" __robomongoDbName = __robomongoLastRes._db.getName();\n "
|
||||
" __robomongoServerAddress = __robomongoLastRes._mongo.host; \n"
|
||||
@@ -330,16 +354,27 @@ namespace Robomongo
|
||||
" __robomongoBatchSize = __robomongoLastRes._batchSize; \n"
|
||||
" __robomongoOptions = __robomongoLastRes._options; \n"
|
||||
" __robomongoSpecial = __robomongoLastRes._special; \n"
|
||||
"} \n";
|
||||
"} \n"
|
||||
"else if (typeof __robomongoLastRes == 'object' && __robomongoLastRes != null \n"
|
||||
" && __robomongoLastRes instanceof DBCommandCursor \n"
|
||||
" && __robomongoAggregateUsed) { \n"
|
||||
" __robomongoAggregateUsed = false; \n"
|
||||
" __robomongoIsAggregate = true; \n"
|
||||
" __robomongoDbName = __robomongoLastRes._db.getName();\n "
|
||||
" __robomongoServerAddress = __robomongoLastRes._db._mongo.host; \n"
|
||||
" __robomongoCollectionName = __robomongoLastRes._collName; \n"
|
||||
"} \n"
|
||||
;
|
||||
|
||||
_scope->exec(script, "(getresultinfo)", false, false, false);
|
||||
|
||||
bool isQuery = _scope->getBoolean("__robomongoQuery");
|
||||
bool const isQuery = _scope->getBoolean("__robomongoQuery");
|
||||
bool const isAggregate = _scope->getBoolean("__robomongoIsAggregate");
|
||||
|
||||
if (isQuery) {
|
||||
std::string serverAddress = getString("__robomongoServerAddress");
|
||||
std::string dbName = getString("__robomongoDbName");
|
||||
std::string collectionName = getString("__robomongoCollectionName");
|
||||
|
||||
mongo::BSONObj query = _scope->getObject("__robomongoQuery");
|
||||
mongo::BSONObj fields = _scope->getObject("__robomongoFields");
|
||||
|
||||
@@ -350,15 +385,32 @@ namespace Robomongo
|
||||
|
||||
bool special = _scope->getBoolean("__robomongoSpecial");
|
||||
|
||||
MongoQueryInfo info = MongoQueryInfo(CollectionInfo(serverAddress, dbName, collectionName),
|
||||
query, fields, limit, skip, batchSize, options, special);
|
||||
return MongoShellResult(type, output, objects, info, elapsedms);
|
||||
MongoQueryInfo const info{ CollectionInfo(serverAddress, dbName, collectionName),
|
||||
query, fields, limit, skip, batchSize, options, special };
|
||||
return MongoShellResult(type, output, objects, info, statement, elapsedms);
|
||||
}
|
||||
else if (isAggregate) {
|
||||
std::string const serverAddress = getString("__robomongoServerAddress");
|
||||
std::string const dbName = getString("__robomongoDbName");
|
||||
std::string const collectionName = getString("__robomongoCollectionName");
|
||||
mongo::BSONObj const pipeline = _scope->getObject("__robomongoAggregatePipeline");
|
||||
mongo::BSONObj const options = _scope->getObject("__robomongoAggregateOptions");
|
||||
|
||||
return MongoShellResult(type, output, objects, MongoQueryInfo(), elapsedms);
|
||||
// This query can be paging of an original aggr. query, we store the original/unpaged
|
||||
// pipeline object here.
|
||||
mongo::BSONObj const origPipeline = aggrInfo.isValid ? aggrInfo.pipeline : pipeline;
|
||||
int const skip = aggrInfo.isValid ? aggrInfo.skip : 0;
|
||||
int const batchSize = aggrInfo.isValid ? aggrInfo.batchSize : 50;
|
||||
int const resultIndex = aggrInfo.isValid ? aggrInfo.resultIndex : -1;
|
||||
|
||||
AggrInfo const newAggrInfo { collectionName, skip, batchSize, origPipeline, options, resultIndex };
|
||||
return MongoShellResult(type, output, objects, MongoQueryInfo(), statement, elapsedms, newAggrInfo);
|
||||
}
|
||||
return MongoShellResult(type, output, objects, MongoQueryInfo(), statement, elapsedms);
|
||||
}
|
||||
|
||||
MongoShellExecResult ScriptEngine::prepareExecResult(const std::vector<MongoShellResult> &results)
|
||||
MongoShellExecResult ScriptEngine::prepareExecResult(const std::vector<MongoShellResult> &results,
|
||||
bool timeoutReached /* = false */)
|
||||
{
|
||||
const char *script =
|
||||
"__robomongoServerAddress = '[invalid connection]'; \n"
|
||||
@@ -380,7 +432,7 @@ namespace Robomongo
|
||||
std::string dbName = getString("__robomongoDbName");
|
||||
bool dbIsValid = _scope->getBoolean("__robomongoDbIsValid");
|
||||
|
||||
return MongoShellExecResult(results, serverName, serverIsValid, dbName, dbIsValid);
|
||||
return MongoShellExecResult(results, serverName, serverIsValid, dbName, dbIsValid, timeoutReached);
|
||||
}
|
||||
|
||||
std::string ScriptEngine::getString(const char *fieldName)
|
||||
@@ -388,12 +440,12 @@ namespace Robomongo
|
||||
return _scope->getString(fieldName);
|
||||
}
|
||||
|
||||
bool ScriptEngine::statementize(const std::string &script, std::vector<std::string> &outList, std::string &outError)
|
||||
bool ScriptEngine::statementize(
|
||||
const std::string &script, std::vector<std::string> &outVec, std::string &outError)
|
||||
{
|
||||
QString qScript = QtUtils::toQString(script);
|
||||
_scope->setString("__robomongoEsprima", script.c_str());
|
||||
|
||||
mongo::StringData data(
|
||||
mongo::StringData const data {
|
||||
"var __robomongoResult = {};"
|
||||
"try {"
|
||||
"__robomongoResult.result = esprima.parse(__robomongoEsprima, { range: true, loc : true });"
|
||||
@@ -401,36 +453,31 @@ namespace Robomongo
|
||||
"__robomongoResult.error = e.name + ': ' + e.message;"
|
||||
"}"
|
||||
"__robomongoResult;"
|
||||
);
|
||||
};
|
||||
|
||||
bool res2 = _scope->exec(data, "(esprima2)", false, true, false);
|
||||
mongo::BSONObj obj = _scope->getObject("__lastres__");
|
||||
if(!_scope->exec(data, "(esprima2)", false, true, false)) {
|
||||
sendLog(this, LogEvent::RBM_ERROR, "ScriptEngine: Scope failed. Resetting scope.");
|
||||
_scope->reset();
|
||||
sendLog(this, LogEvent::RBM_INFO, "ScriptEngine: Scope reset complete.");
|
||||
_scope->exec(data, "(esprima2)", false, true, false);
|
||||
}
|
||||
|
||||
mongo::BSONObj const obj = _scope->getObject("__lastres__");
|
||||
if (obj.hasField("error")) {
|
||||
outError = obj.getField("error");
|
||||
return false;
|
||||
}
|
||||
|
||||
mongo::BSONObj result = obj.getField("result").Obj();
|
||||
std::vector<mongo::BSONElement> v = result.getField("body").Array();
|
||||
for (std::vector<mongo::BSONElement>::iterator it = v.begin(); it != v.end(); ++it)
|
||||
for (auto const& bsonElem : obj.getField("result").Obj().getField("body").Array())
|
||||
{
|
||||
mongo::BSONObj item = (*it).Obj();
|
||||
mongo::BSONObj loc = item.getField("loc").Obj();
|
||||
mongo::BSONObj start = loc.getField("start").Obj();
|
||||
mongo::BSONObj end = loc.getField("end").Obj();
|
||||
mongo::BSONObj const item = bsonElem.Obj();
|
||||
std::vector<mongo::BSONElement> const range = item.getField("range").Array();
|
||||
auto const from = static_cast<int>(range.at(0).number());
|
||||
auto const till = static_cast<int>(range.at(1).number());
|
||||
|
||||
int startLine = start.getIntField("line");
|
||||
int startColumn = start.getIntField("column");
|
||||
int endLine = end.getIntField("line");
|
||||
int endColumn = end.getIntField("column");
|
||||
|
||||
std::vector<mongo::BSONElement> range = item.getField("range").Array();
|
||||
int from = (int) range.at(0).number();
|
||||
int till = (int) range.at(1).number();
|
||||
|
||||
std::string statement = QtUtils::toStdString(qScript.mid(from, till - from));
|
||||
outList.push_back(statement);
|
||||
QString const qScript = QtUtils::toQString(script);
|
||||
std::string statement = qScript.mid(from, till - from).toStdString();
|
||||
outVec.push_back(statement);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -457,3 +504,4 @@ namespace Robomongo
|
||||
return QtUtils::toStdString(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <mongo/scripting/engine.h>
|
||||
//#include <third_party/js-1.7/jsparse.h>
|
||||
@@ -11,15 +12,17 @@ namespace Robomongo
|
||||
{
|
||||
class ConnectionSettings;
|
||||
|
||||
class ScriptEngine
|
||||
class ScriptEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptEngine(ConnectionSettings *connection, int timeoutSec);
|
||||
~ScriptEngine();
|
||||
|
||||
void init(bool isLoadMongoJs, const std::string& serverAddr = "", const std::string& dbName = "");
|
||||
MongoShellExecResult exec(const std::string &script, const std::string &dbName = std::string());
|
||||
MongoShellExecResult exec(const std::string &script, const std::string &dbName = std::string(),
|
||||
AggrInfo aggrInfo = AggrInfo());
|
||||
void interrupt();
|
||||
|
||||
void use(const std::string &dbName);
|
||||
@@ -31,20 +34,26 @@ namespace Robomongo
|
||||
|
||||
bool failedScope() const { return _failedScope; }
|
||||
|
||||
void changeTimeout(int newTimeout) { _timeoutSec = newTimeout; }
|
||||
|
||||
private:
|
||||
ConnectionSettings *_connection;
|
||||
|
||||
MongoShellResult prepareResult(const std::string &type, const std::string &output, const std::vector<MongoDocumentPtr> &objects, qint64 elapsedms);
|
||||
MongoShellExecResult prepareExecResult(const std::vector<MongoShellResult> &results);
|
||||
MongoShellResult prepareResult(const std::string &type, const std::string &output,
|
||||
const std::vector<MongoDocumentPtr> &objects, qint64 elapsedms,
|
||||
const std::string &statement, AggrInfo aggrInfo = AggrInfo());
|
||||
|
||||
MongoShellExecResult prepareExecResult(
|
||||
const std::vector<MongoShellResult> &results, bool timeoutReached = false);
|
||||
|
||||
std::string loadFile(const QString &path, bool throwOnError);
|
||||
|
||||
std::string getString(const char *fieldName);
|
||||
|
||||
bool statementize(const std::string &script, std::vector<std::string> &outList, std::string &outError);
|
||||
bool statementize(
|
||||
const std::string &script, std::vector<std::string> &outVec, std::string &outError);
|
||||
|
||||
int _timeoutSec;
|
||||
mongo::ScriptEngine *_engine;
|
||||
std::unique_ptr<mongo::Scope> _scope;
|
||||
std::unique_ptr<mongo::Scope> _scope; // MozJSProxyScope
|
||||
bool _failedScope = false;
|
||||
QMutex _mutex;
|
||||
bool _initialized;
|
||||
|
||||
@@ -17,10 +17,10 @@ namespace Robomongo
|
||||
R_REGISTER_EVENT(LoadUsersRequest)
|
||||
R_REGISTER_EVENT(LoadCollectionIndexesRequest)
|
||||
R_REGISTER_EVENT(LoadCollectionIndexesResponse)
|
||||
R_REGISTER_EVENT(EnsureIndexRequest)
|
||||
R_REGISTER_EVENT(AddEditIndexRequest)
|
||||
R_REGISTER_EVENT(AddEditIndexResponse)
|
||||
R_REGISTER_EVENT(DropCollectionIndexRequest)
|
||||
R_REGISTER_EVENT(DeleteCollectionIndexResponse)
|
||||
R_REGISTER_EVENT(EditIndexRequest)
|
||||
R_REGISTER_EVENT(DropCollectionIndexResponse)
|
||||
R_REGISTER_EVENT(LoadUsersResponse)
|
||||
R_REGISTER_EVENT(LoadFunctionsRequest)
|
||||
R_REGISTER_EVENT(LoadFunctionsResponse)
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QEvent>
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
|
||||
#include "robomongo/core/domain/MongoShellResult.h"
|
||||
#include "robomongo/core/domain/CursorPosition.h"
|
||||
#include "robomongo/core/domain/MongoUser.h"
|
||||
#include "robomongo/core/domain/MongoFunction.h"
|
||||
#include "robomongo/core/events/MongoEventsInfo.h"
|
||||
#include "robomongo/core/domain/MongoAggregateInfo.h"
|
||||
#include "robomongo/core/Event.h"
|
||||
#include "robomongo/core/Enums.h"
|
||||
#include "robomongo/core/mongodb/ReplicaSet.h"
|
||||
@@ -223,58 +225,80 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
public:
|
||||
LoadCollectionIndexesResponse(QObject *sender, const std::vector<EnsureIndexInfo> &indexes) :
|
||||
LoadCollectionIndexesResponse(QObject *sender, const std::vector<IndexInfo> &indexes) :
|
||||
Event(sender), _indexes(indexes) {}
|
||||
|
||||
LoadCollectionIndexesResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
std::vector<EnsureIndexInfo> indexes() const { return _indexes; }
|
||||
std::vector<IndexInfo> indexes() const { return _indexes; }
|
||||
private:
|
||||
std::vector<EnsureIndexInfo> _indexes;
|
||||
std::vector<IndexInfo> _indexes;
|
||||
};
|
||||
|
||||
class EnsureIndexRequest : public Event
|
||||
class AddEditIndexRequest : public Event
|
||||
{
|
||||
R_EVENT
|
||||
EnsureIndexRequest(QObject *sender, const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo) : Robomongo::Event(sender), oldInfo_(oldInfo), newInfo_(newInfo) {}
|
||||
const EnsureIndexInfo &oldInfo() const
|
||||
AddEditIndexRequest(QObject *sender, const IndexInfo &oldInfo, const IndexInfo &newInfo)
|
||||
: Robomongo::Event(sender), oldInfo_(oldInfo), newInfo_(newInfo) {}
|
||||
const IndexInfo &oldInfo() const
|
||||
{
|
||||
return oldInfo_;
|
||||
}
|
||||
const EnsureIndexInfo &newInfo() const
|
||||
const IndexInfo &newInfo() const
|
||||
{
|
||||
return newInfo_;
|
||||
}
|
||||
private:
|
||||
const EnsureIndexInfo oldInfo_;
|
||||
const EnsureIndexInfo newInfo_;
|
||||
const IndexInfo oldInfo_;
|
||||
const IndexInfo newInfo_;
|
||||
};
|
||||
|
||||
struct AddEditIndexResponse : public Event
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
AddEditIndexResponse(QObject *sender, const IndexInfo &oldIndex, const IndexInfo &newIndex)
|
||||
: Event(sender), oldIndex_(oldIndex), newIndex_(newIndex)
|
||||
{}
|
||||
|
||||
AddEditIndexResponse(QObject *sender, const EventError &error,
|
||||
const IndexInfo &oldIndex, const IndexInfo &newIndex)
|
||||
: Event(sender, error), oldIndex_(oldIndex), newIndex_(newIndex)
|
||||
{}
|
||||
|
||||
const IndexInfo oldIndex_;
|
||||
const IndexInfo newIndex_;
|
||||
};
|
||||
|
||||
class DropCollectionIndexRequest : public Event
|
||||
{
|
||||
R_EVENT
|
||||
public:
|
||||
DropCollectionIndexRequest(QObject *sender, const MongoCollectionInfo &collection, const std::string &name) :
|
||||
Event(sender),
|
||||
_collection(collection),
|
||||
_name(name) {}
|
||||
DropCollectionIndexRequest(QObject *sender, const MongoCollectionInfo &collection,
|
||||
const std::string &index)
|
||||
: Event(sender), _collection(collection), _index(index)
|
||||
{}
|
||||
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
std::string name() const { return _name; }
|
||||
std::string index() const { return _index; }
|
||||
private:
|
||||
const MongoCollectionInfo _collection;
|
||||
std::string _name;
|
||||
std::string _index; // todo: rename to index
|
||||
};
|
||||
|
||||
class DeleteCollectionIndexResponse: public Event
|
||||
class DropCollectionIndexResponse: public Event
|
||||
{
|
||||
R_EVENT
|
||||
public:
|
||||
DeleteCollectionIndexResponse(QObject *sender, const MongoCollectionInfo &collection, const std::string &index) :
|
||||
Event(sender), _collection(collection), _index(index) {}
|
||||
DropCollectionIndexResponse(QObject *sender, const MongoCollectionInfo &collection,
|
||||
const std::string &index)
|
||||
: Event(sender), _collection(collection), _index(index)
|
||||
{}
|
||||
|
||||
DeleteCollectionIndexResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
DropCollectionIndexResponse(QObject *sender, const EventError &error,
|
||||
const std::string &index)
|
||||
: Event(sender, error), _index(index)
|
||||
{}
|
||||
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
std::string index() const { return _index; }
|
||||
@@ -283,21 +307,6 @@ namespace Robomongo
|
||||
std::string _index;
|
||||
};
|
||||
|
||||
class EditIndexRequest : public Event
|
||||
{
|
||||
R_EVENT
|
||||
public:
|
||||
EditIndexRequest(QObject *sender, const MongoCollectionInfo &collection, const std::string &oldIndex, const std::string &newIndex) :
|
||||
Event(sender), _collection(collection), _oldIndex(oldIndex), _newIndex(newIndex) {}
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
std::string oldIndex() const { return _oldIndex; }
|
||||
std::string newIndex() const { return _newIndex; }
|
||||
private:
|
||||
const MongoCollectionInfo _collection;
|
||||
std::string _oldIndex;
|
||||
std::string _newIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Load Users
|
||||
*/
|
||||
@@ -726,20 +735,17 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
|
||||
public:
|
||||
CreateUserRequest(QObject *sender, const std::string &database, const MongoUser &user, bool overwrite = false) :
|
||||
CreateUserRequest(QObject *sender, const std::string &database, const MongoUser &user) :
|
||||
Event(sender),
|
||||
_database(database),
|
||||
_user(user),
|
||||
_overwrite(overwrite) {}
|
||||
_user(user) {}
|
||||
|
||||
std::string database() const { return _database; }
|
||||
MongoUser user() const { return _user; }
|
||||
bool overwrite() const { return _overwrite; }
|
||||
|
||||
private:
|
||||
std::string _database;
|
||||
MongoUser _user;
|
||||
bool _overwrite;
|
||||
};
|
||||
|
||||
struct CreateUserResponse : public Event
|
||||
@@ -765,17 +771,14 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
|
||||
public:
|
||||
DropUserRequest(QObject *sender, const std::string &database, const mongo::OID &id,
|
||||
std::string const& username) :
|
||||
Event(sender), _database(database), _id(id), _username(username) {}
|
||||
DropUserRequest(QObject *sender, const std::string &database, std::string const& username) :
|
||||
Event(sender), _database(database), _username(username) {}
|
||||
|
||||
std::string database() const { return _database; }
|
||||
mongo::OID id() const { return _id; }
|
||||
std::string username() const { return _username; }
|
||||
|
||||
private:
|
||||
std::string _database;
|
||||
mongo::OID _id;
|
||||
std::string const _username;
|
||||
};
|
||||
|
||||
@@ -802,21 +805,25 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
|
||||
public:
|
||||
CreateFunctionRequest(QObject *sender, const std::string &database, const MongoFunction &function,
|
||||
const std::string &existingFunctionName = std::string(), bool overwrite = false) :
|
||||
CreateFunctionRequest(QObject *sender, const std::string &database, float dbVersion,
|
||||
const MongoFunction &function, const std::string &existingFunctionName = std::string(),
|
||||
bool overwrite = false) :
|
||||
Event(sender),
|
||||
_database(database),
|
||||
_dbVersion(dbVersion),
|
||||
_existingFunctionName(existingFunctionName),
|
||||
_function(function),
|
||||
_overwrite(overwrite) {}
|
||||
|
||||
std::string database() const { return _database; }
|
||||
float dbVersion() const { return _dbVersion; }
|
||||
std::string existingFunctionName() const { return _existingFunctionName; }
|
||||
MongoFunction function() const { return _function; }
|
||||
bool overwrite() const { return _overwrite; }
|
||||
|
||||
private:
|
||||
std::string _database;
|
||||
float const _dbVersion = 0.0f;
|
||||
std::string _existingFunctionName;
|
||||
MongoFunction _function;
|
||||
bool _overwrite;
|
||||
@@ -846,16 +853,20 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
|
||||
public:
|
||||
DropFunctionRequest(QObject *sender, const std::string &database, const std::string &funcName) :
|
||||
DropFunctionRequest(QObject *sender, const std::string &database, float dbVersion,
|
||||
const std::string &funcName) :
|
||||
Event(sender),
|
||||
_database(database),
|
||||
_dbVersion(dbVersion),
|
||||
_functionName(funcName) {}
|
||||
|
||||
std::string database() const { return _database; }
|
||||
float dbVersion() const { return _dbVersion; }
|
||||
std::string functionName() const { return _functionName; }
|
||||
|
||||
private:
|
||||
std::string _database;
|
||||
float const _dbVersion = 0.0f;
|
||||
std::string _functionName;
|
||||
};
|
||||
|
||||
@@ -950,33 +961,39 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
ExecuteScriptRequest(QObject *sender, const std::string &script, const std::string &dbName, int take = 0, int skip = 0) :
|
||||
ExecuteScriptRequest(QObject *sender, const std::string &script, const std::string &dbName,
|
||||
AggrInfo aggrInfo = AggrInfo(), int take = 0, int skip = 0) :
|
||||
Event(sender),
|
||||
script(script),
|
||||
databaseName(dbName),
|
||||
aggrInfo(aggrInfo),
|
||||
take(take),
|
||||
skip(skip) {}
|
||||
skip(skip)
|
||||
{}
|
||||
|
||||
std::string script;
|
||||
std::string databaseName;
|
||||
int take; //
|
||||
int skip;
|
||||
AggrInfo const aggrInfo;
|
||||
};
|
||||
|
||||
class ExecuteScriptResponse : public Event
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
ExecuteScriptResponse(QObject *sender, const MongoShellExecResult &result, bool empty) :
|
||||
Event(sender),
|
||||
result(result),
|
||||
empty(empty) { }
|
||||
ExecuteScriptResponse(QObject *sender, const MongoShellExecResult &result, bool empty,
|
||||
bool timeoutReached = false) :
|
||||
Event(sender), result(result), empty(empty), _timeoutReached(timeoutReached) {}
|
||||
|
||||
ExecuteScriptResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
ExecuteScriptResponse(QObject *sender, const EventError &error, bool timeoutReached = false) :
|
||||
Event(sender, error), _timeoutReached(timeoutReached) {}
|
||||
|
||||
bool timeoutReached() const { return _timeoutReached; }
|
||||
|
||||
MongoShellExecResult result;
|
||||
bool empty;
|
||||
bool const _timeoutReached = false;
|
||||
};
|
||||
|
||||
class ConnectingEvent : public Event
|
||||
@@ -1087,20 +1104,21 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
|
||||
public:
|
||||
ScriptExecutedEvent(QObject *sender, const MongoShellExecResult &result, bool empty) :
|
||||
Event(sender),
|
||||
_result(result),
|
||||
_empty(empty) { }
|
||||
ScriptExecutedEvent(QObject *sender, const MongoShellExecResult &result, bool empty,
|
||||
bool timeoutReached = false) :
|
||||
Event(sender), _result(result), _empty(empty), _timeoutReached(timeoutReached) {}
|
||||
|
||||
ScriptExecutedEvent(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
ScriptExecutedEvent(QObject *sender, const EventError &error, bool timeoutReached = false) :
|
||||
Event(sender, error), _timeoutReached(timeoutReached) {}
|
||||
|
||||
MongoShellExecResult result() const { return _result; }
|
||||
bool empty() const { return _empty; }
|
||||
bool timeoutReached() const { return _timeoutReached; }
|
||||
|
||||
private:
|
||||
MongoShellExecResult _result;
|
||||
bool _empty;
|
||||
bool const _timeoutReached = false;
|
||||
};
|
||||
|
||||
class ScriptExecutingEvent : public Event
|
||||
@@ -1237,13 +1255,44 @@ namespace Robomongo
|
||||
RBM_DEBUG = 100 // log as much as possible
|
||||
};
|
||||
|
||||
LogEvent(QObject *sender, const std::string& message, LogLevel level) :
|
||||
Event(sender),
|
||||
message(message),
|
||||
level(level) {}
|
||||
LogEvent(QObject *sender, const std::string& message, LogLevel level,
|
||||
bool const informUser = false)
|
||||
: Event(sender), message(message), level(level), informUser(informUser)
|
||||
{}
|
||||
|
||||
std::string severity() const {
|
||||
switch (level) {
|
||||
case RBM_ERROR : return "Error";
|
||||
case RBM_WARN : return "Warning";
|
||||
case RBM_INFO : return "Info";
|
||||
case RBM_DEBUG : return "Debug";
|
||||
default: return "Undefined";
|
||||
}
|
||||
}
|
||||
|
||||
QMessageBox::Icon qMessageBoxIcon() const {
|
||||
switch (level) {
|
||||
case RBM_ERROR: return QMessageBox::Icon::Critical;
|
||||
case RBM_WARN: return QMessageBox::Icon::Warning;
|
||||
case RBM_INFO: return QMessageBox::Icon::Information;
|
||||
case RBM_DEBUG: return QMessageBox::Icon::Information;
|
||||
default: return QMessageBox::Icon::Information;
|
||||
}
|
||||
}
|
||||
|
||||
mongo::logger::LogSeverity mongoLogSeverity() const {
|
||||
switch (level) {
|
||||
case RBM_ERROR: return mongo::logger::LogSeverity::Error();
|
||||
case RBM_WARN: return mongo::logger::LogSeverity::Warning();
|
||||
case RBM_INFO: return mongo::logger::LogSeverity::Info();
|
||||
case RBM_DEBUG: return mongo::logger::LogSeverity::Log();
|
||||
default: return mongo::logger::LogSeverity::Info();
|
||||
}
|
||||
}
|
||||
|
||||
std::string message;
|
||||
LogLevel level;
|
||||
bool const informUser = false;
|
||||
};
|
||||
|
||||
class StopScriptRequest : public Event
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
EnsureIndexInfo::EnsureIndexInfo(const MongoCollectionInfo &collection, const std::string &name, const std::string &request,
|
||||
bool isUnique, bool isBackGround, bool isDropDuplicates, bool isSparce, int expireAfter,
|
||||
IndexInfo::IndexInfo(
|
||||
const MongoCollectionInfo &collection, const std::string &name, const std::string &keys,
|
||||
bool isUnique, bool isBackGround, bool isSparce, int expireAfter,
|
||||
const std::string &defaultLanguage, const std::string &languageOverride, const std::string &textWeights) :
|
||||
_name(name),
|
||||
_collection(collection),
|
||||
_request(request),
|
||||
_keys(keys),
|
||||
_unique(isUnique),
|
||||
_backGround(isBackGround),
|
||||
_dropDups(isDropDuplicates),
|
||||
_sparse(isSparce),
|
||||
_ttl(expireAfter),
|
||||
_defaultLanguage(defaultLanguage),
|
||||
@@ -21,14 +21,17 @@ namespace Robomongo
|
||||
_address(),
|
||||
_databases(),
|
||||
_version(0.0f),
|
||||
_dbVersionStr(),
|
||||
_uuid(uuid)
|
||||
{}
|
||||
|
||||
ConnectionInfo::ConnectionInfo(const std::string &address, const std::vector<std::string> &databases,
|
||||
float version, const std::string& storageEngine, std::string const& uuid) :
|
||||
float version, const std::string& dbVersionStr, const std::string& storageEngine,
|
||||
std::string const& uuid) :
|
||||
_address(address),
|
||||
_databases(databases),
|
||||
_version(version),
|
||||
_dbVersionStr(dbVersionStr),
|
||||
_storageEngineType(storageEngine),
|
||||
_uuid(uuid)
|
||||
{}
|
||||
|
||||
@@ -4,15 +4,14 @@
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
struct EnsureIndexInfo
|
||||
struct IndexInfo
|
||||
{
|
||||
EnsureIndexInfo(
|
||||
IndexInfo(
|
||||
const MongoCollectionInfo &collection,
|
||||
const std::string &name = std::string(),
|
||||
const std::string &request = std::string(),
|
||||
bool isUnique = false,
|
||||
bool isBackGround = false,
|
||||
bool isDropDuplicates = false,
|
||||
bool isSparce = false,
|
||||
int expireAfter = -1,
|
||||
const std::string &defaultLanguage = std::string(),
|
||||
@@ -21,10 +20,9 @@ namespace Robomongo
|
||||
|
||||
MongoCollectionInfo _collection;
|
||||
std::string _name;
|
||||
std::string _request;
|
||||
std::string _keys;
|
||||
bool _unique;
|
||||
bool _backGround;
|
||||
bool _dropDups;
|
||||
bool _sparse;
|
||||
int _ttl;
|
||||
std::string _defaultLanguage;
|
||||
@@ -36,10 +34,12 @@ namespace Robomongo
|
||||
{
|
||||
ConnectionInfo(std::string const& uuid);
|
||||
ConnectionInfo(const std::string &address, const std::vector<std::string> &databases, float version,
|
||||
const std::string& storageEngine, std::string const& uuid);
|
||||
const std::string& dbVersionStr, const std::string& storageEngine,
|
||||
std::string const& uuid);
|
||||
const std::string _address;
|
||||
const std::vector<std::string> _databases;
|
||||
const float _version;
|
||||
const std::string _dbVersionStr;
|
||||
const std::string _storageEngineType;
|
||||
std::string const _uuid;
|
||||
};
|
||||
|
||||
@@ -8,28 +8,28 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
Robomongo::EnsureIndexInfo makeEnsureIndexInfoFromBsonObj(
|
||||
Robomongo::IndexInfo makeIndexInfoFromBsonObj(
|
||||
const Robomongo::MongoCollectionInfo &collection,
|
||||
const mongo::BSONObj &obj)
|
||||
{
|
||||
using namespace Robomongo::BsonUtils;
|
||||
Robomongo::EnsureIndexInfo info(collection);
|
||||
info._name = getField<mongo::String>(obj, "name");
|
||||
mongo::BSONObj keyObj = getField<mongo::Object>(obj, "key");
|
||||
if (keyObj.isValid()) {
|
||||
info._request = jsonString(keyObj, mongo::TenGen, 1, Robomongo::DefaultEncoding, Robomongo::Utc);
|
||||
}
|
||||
info._unique = getField<mongo::Bool>(obj, "unique");
|
||||
info._backGround = getField<mongo::Bool>(obj, "background");
|
||||
info._dropDups = getField<mongo::Bool>(obj, "dropDups");
|
||||
info._sparse = getField<mongo::Bool>(obj, "sparse");
|
||||
Robomongo::IndexInfo info(collection);
|
||||
info._name = obj.getStringField("name");
|
||||
mongo::BSONObj keyObj = obj.getObjectField("key");
|
||||
if (keyObj.isValid())
|
||||
info._keys = jsonString(keyObj, mongo::TenGen, 1, Robomongo::DefaultEncoding, Robomongo::Utc);
|
||||
|
||||
info._unique = obj.getBoolField("unique");
|
||||
info._backGround = obj.getBoolField("background");
|
||||
info._sparse = obj.getBoolField("sparse");
|
||||
info._ttl = obj.getIntField("expireAfterSeconds");
|
||||
info._defaultLanguage = getField<mongo::String>(obj, "default_language");
|
||||
info._languageOverride = getField<mongo::String>(obj, "language_override");
|
||||
mongo::BSONObj weightsObj = getField<mongo::Object>(obj, "weights");
|
||||
if (weightsObj.isValid()) {
|
||||
info._textWeights = jsonString(weightsObj, mongo::TenGen, 1, Robomongo::DefaultEncoding, Robomongo::Utc);
|
||||
}
|
||||
info._defaultLanguage = obj.getStringField("default_language");
|
||||
info._languageOverride = obj.getStringField("language_override");
|
||||
mongo::BSONObj weightsObj = obj.getObjectField("weights");
|
||||
if (weightsObj.isValid())
|
||||
info._textWeights = jsonString(weightsObj, mongo::TenGen, 1, Robomongo::DefaultEncoding,
|
||||
Robomongo::Utc);
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
@@ -39,20 +39,21 @@ namespace Robomongo
|
||||
MongoClient::MongoClient(mongo::DBClientBase *const dbclient) :
|
||||
_dbclient(dbclient) { }
|
||||
|
||||
std::vector<std::string> MongoClient::getCollectionNames(const std::string &dbname) const
|
||||
std::vector<std::string> MongoClient::getCollectionNamesWithDbname(const std::string &dbname) const
|
||||
{
|
||||
typedef std::list<std::string> cont_string_t;
|
||||
cont_string_t dbs = _dbclient->getCollectionNames(dbname);
|
||||
std::list<mongo::BSONObj> collList = _dbclient->getCollectionInfos(dbname);
|
||||
|
||||
std::vector<std::string> stringList;
|
||||
for (cont_string_t::const_iterator i = dbs.begin(); i != dbs.end(); i++) {
|
||||
stringList.push_back(*i);
|
||||
}
|
||||
std::sort(stringList.begin(), stringList.end());
|
||||
return stringList;
|
||||
std::vector<std::string> collNames;
|
||||
for (auto const& coll : collList)
|
||||
collNames.push_back(dbname + '.' + coll.getStringField("name")); // todo: verify
|
||||
|
||||
std::sort(collNames.begin(), collNames.end());
|
||||
return collNames;
|
||||
}
|
||||
|
||||
|
||||
// Warning:
|
||||
// Use string version dbVersionStr(), version number is corrupted after conversion to float
|
||||
// Todo: Remove this function
|
||||
float MongoClient::getVersion() const
|
||||
{
|
||||
float result = 0.0f;
|
||||
@@ -63,6 +64,14 @@ namespace Robomongo
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string MongoClient::dbVersionStr() const
|
||||
{
|
||||
mongo::BSONObj resultObj;
|
||||
_dbclient->runCommand("db", BSON("buildInfo" << "1"), resultObj);
|
||||
std::string const resultStr = BsonUtils::getField<mongo::String>(resultObj, "version");
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
std::string MongoClient::getStorageEngineType() const
|
||||
{
|
||||
mongo::BSONObj resultObj;
|
||||
@@ -72,93 +81,89 @@ namespace Robomongo
|
||||
|
||||
std::vector<std::string> MongoClient::getDatabaseNames() const
|
||||
{
|
||||
typedef std::list<std::string> cont_string_t;
|
||||
cont_string_t dbs = _dbclient->getDatabaseNames();
|
||||
std::vector<std::string> dbNames;
|
||||
for (cont_string_t::const_iterator i = dbs.begin(); i != dbs.end(); ++i) {
|
||||
dbNames.push_back(*i);
|
||||
}
|
||||
std::list<std::string> const& dbs = _dbclient->getDatabaseNames();
|
||||
std::vector<std::string> dbNames = {dbs.begin(), dbs.end()};
|
||||
std::sort(dbNames.begin(), dbNames.end());
|
||||
return dbNames;
|
||||
}
|
||||
|
||||
std::vector<MongoUser> MongoClient::getUsers(const std::string &dbName)
|
||||
{
|
||||
MongoNamespace ns(dbName, "system.users");
|
||||
std::vector<MongoUser> users;
|
||||
mongo::BSONObjBuilder cmd;
|
||||
cmd.append("usersInfo", 1);
|
||||
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor(_dbclient->query(ns.toString(), mongo::Query()));
|
||||
mongo::BSONObj result;
|
||||
if (!_dbclient->runCommand(dbName, cmd.done(), result)) {
|
||||
std::string errStr = result.getStringField("errmsg");
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
// Cursor may be NULL, it means we have connectivity problem
|
||||
if (!cursor)
|
||||
throw mongo::DBException("Network error while attempting to load list of users", 0);
|
||||
|
||||
float ver = getVersion();
|
||||
while (cursor->more()) {
|
||||
mongo::BSONObj bsonObj = cursor->next();
|
||||
MongoUser user(ver, bsonObj);
|
||||
users.push_back(user);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
|
||||
std::vector<MongoUser> users;
|
||||
for (auto const& usr : result.getField("users").Array())
|
||||
users.push_back(MongoUser(getVersion(), usr.embeddedObject()));
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
void MongoClient::createUser(const std::string &dbName, const MongoUser &user, bool overwrite)
|
||||
void MongoClient::createUser(const std::string &dbName, const MongoUser &user)
|
||||
{
|
||||
MongoNamespace ns(dbName, "system.users");
|
||||
mongo::BSONObj obj = user.toBson();
|
||||
|
||||
if (!overwrite) { // create new user
|
||||
_dbclient->insert(ns.toString(), obj);
|
||||
}
|
||||
else { // update existing user
|
||||
mongo::BSONElement id = obj.getField("_id");
|
||||
mongo::BSONObjBuilder builder;
|
||||
builder.append(id);
|
||||
mongo::BSONObj bsonQuery = builder.obj();
|
||||
mongo::Query query(bsonQuery);
|
||||
|
||||
_dbclient->update(ns.toString(), query, obj, true, false);
|
||||
mongo::BSONObjBuilder cmd;
|
||||
cmd.append("createUser", user.name());
|
||||
cmd.append("pwd", user.password());
|
||||
|
||||
mongo::BSONArrayBuilder roles;
|
||||
auto const& rolesStrs = user.roles();
|
||||
for (auto const& roleStr : rolesStrs) {
|
||||
mongo::BSONObjBuilder role;
|
||||
role.append("role", roleStr).append("db", user.userSource());
|
||||
roles.append(role.done());
|
||||
}
|
||||
cmd.appendArray("roles", roles.done());
|
||||
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
mongo::BSONObj result;
|
||||
if (!_dbclient->runCommand(dbName, cmd.done(), result)) {
|
||||
std::string errStr = result.getStringField("errmsg");
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
|
||||
void MongoClient::dropUser(const std::string &dbName, const mongo::OID &id)
|
||||
void MongoClient::dropUser(const std::string &dbName, const std::string &user)
|
||||
{
|
||||
MongoNamespace ns(dbName, "system.users");
|
||||
mongo::BSONObjBuilder cmd;
|
||||
cmd.append("dropUser", user);
|
||||
|
||||
mongo::BSONObjBuilder builder;
|
||||
builder.append("_id", id);
|
||||
mongo::BSONObj bsonQuery = builder.obj();
|
||||
mongo::Query query(bsonQuery);
|
||||
mongo::BSONObj result;
|
||||
if (!_dbclient->runCommand(dbName, cmd.done(), result)) {
|
||||
std::string errStr = result.getStringField("errmsg");
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
_dbclient->remove(ns.toString(), query, true);
|
||||
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MongoFunction> MongoClient::getFunctions(const std::string &dbName)
|
||||
std::vector<MongoFunction> MongoClient::getFunctions(const std::string &dbName) const
|
||||
{
|
||||
MongoNamespace ns(dbName, "system.js");
|
||||
std::vector<MongoFunction> functions;
|
||||
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor(_dbclient->query(ns.toString(), mongo::Query().sort("_id")));
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor(
|
||||
_dbclient->query(mongo::NamespaceString(dbName, "system.js"), mongo::Query().sort("_id")));
|
||||
|
||||
// Cursor may be NULL, it means we have connectivity problem
|
||||
if (!cursor)
|
||||
throw mongo::DBException("Network error while attempting to load list of functions.", 0);
|
||||
throw std::runtime_error("Network error while attempting to load list of functions.");
|
||||
|
||||
while (cursor->more()) {
|
||||
mongo::BSONObj bsonObj = cursor->next();
|
||||
|
||||
try {
|
||||
MongoFunction user(bsonObj);
|
||||
functions.push_back(user);
|
||||
MongoFunction func(bsonObj);
|
||||
functions.push_back(func);
|
||||
} catch (const std::exception &) {
|
||||
// skip invalid docs
|
||||
}
|
||||
@@ -166,89 +171,77 @@ namespace Robomongo
|
||||
return functions;
|
||||
}
|
||||
|
||||
std::vector<EnsureIndexInfo> MongoClient::getIndexes(const MongoCollectionInfo &collection) const
|
||||
std::vector<IndexInfo> MongoClient::getIndexes(const MongoCollectionInfo &collection) const
|
||||
{
|
||||
std::vector<EnsureIndexInfo> result;
|
||||
std::vector<IndexInfo> result;
|
||||
std::list<mongo::BSONObj> indexes = _dbclient->getIndexSpecs(collection.ns().toString());
|
||||
|
||||
// std::unique_ptr<mongo::DBClientCursor> cursor(_dbclient->getIndexSpecs(collection.ns().toString()));
|
||||
|
||||
for (std::list<mongo::BSONObj>::iterator it = indexes.begin(); it != indexes.end(); ++it) {
|
||||
mongo::BSONObj bsonObj = *it;
|
||||
result.push_back(makeEnsureIndexInfoFromBsonObj(collection, bsonObj));
|
||||
result.push_back(makeIndexInfoFromBsonObj(collection, bsonObj));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MongoClient::ensureIndex(const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo) const
|
||||
void MongoClient::addEditIndex(const IndexInfo &oldInfo, const IndexInfo &newInfo) const
|
||||
{
|
||||
std::string ns = newInfo._collection.ns().toString();
|
||||
bool const editIndex = !oldInfo._name.empty();
|
||||
|
||||
// v0.9
|
||||
// mongo::BSONObj keys = mongo::Robomongo::fromjson(newInfo._request);
|
||||
|
||||
mongo::BSONObj keys = mongo::Robomongo::fromjson(newInfo._request);
|
||||
mongo::BSONObjBuilder toSave;
|
||||
bool cache = true;
|
||||
int version = -1;
|
||||
|
||||
toSave.append( "ns" , ns );
|
||||
toSave.append( "key" , keys );
|
||||
|
||||
std::string cacheKey(ns);
|
||||
cacheKey += "--";
|
||||
|
||||
|
||||
if ( newInfo._name != "" ) {
|
||||
toSave.append( "name" , newInfo._name );
|
||||
cacheKey += newInfo._name;
|
||||
}
|
||||
else {
|
||||
std::string nn = _dbclient->genIndexName(keys);
|
||||
toSave.append( "name" , nn );
|
||||
cacheKey += nn;
|
||||
}
|
||||
|
||||
if (version >= 0)
|
||||
toSave.append("v", version);
|
||||
|
||||
if (oldInfo._unique != newInfo._unique)
|
||||
toSave.appendBool("unique", newInfo._unique);
|
||||
|
||||
if (oldInfo._backGround != newInfo._backGround)
|
||||
toSave.appendBool("background", newInfo._backGround);
|
||||
|
||||
if (oldInfo._dropDups != newInfo._dropDups)
|
||||
toSave.appendBool("dropDups", newInfo._dropDups);
|
||||
|
||||
if (oldInfo._sparse != newInfo._sparse)
|
||||
toSave.appendBool("sparse", newInfo._sparse);
|
||||
|
||||
if (oldInfo._defaultLanguage != newInfo._defaultLanguage)
|
||||
toSave.append("default_language", newInfo._defaultLanguage);
|
||||
|
||||
if (oldInfo._languageOverride != newInfo._languageOverride)
|
||||
toSave.append("language_override", newInfo._languageOverride);
|
||||
|
||||
if (oldInfo._textWeights != newInfo._textWeights)
|
||||
toSave.append("weights", newInfo._textWeights);
|
||||
|
||||
/* if ( _seenIndexes.count( cacheKey ) )
|
||||
return 0;
|
||||
|
||||
if ( cache )
|
||||
_seenIndexes.insert( cacheKey );*/
|
||||
|
||||
if (oldInfo._ttl != newInfo._ttl)
|
||||
toSave.append("expireAfterSeconds", newInfo._ttl);
|
||||
|
||||
MongoNamespace namesp(newInfo._collection.ns().databaseName(), "system.indexes");
|
||||
mongo::BSONObj obj = toSave.obj();
|
||||
if (!oldInfo._name.empty())
|
||||
// 1.Step: Drop Index (if this is an Edit Index action).
|
||||
// MongoDB docs: To modify an existing index, you need to drop and recreate the index.
|
||||
std::string const ns = newInfo._collection.ns().toString();
|
||||
if (editIndex)
|
||||
_dbclient->dropIndex(ns, oldInfo._name);
|
||||
|
||||
_dbclient->insert(namesp.toString().c_str(), obj);
|
||||
// 2.Step: Add/Edit Index
|
||||
auto const createIndexSpec = [](IndexInfo const& indexInfo) {
|
||||
mongo::IndexSpec indexSpec;
|
||||
indexSpec.name(indexInfo._name);
|
||||
indexSpec.addKeys(mongo::Robomongo::fromjson(indexInfo._keys));
|
||||
|
||||
mongo::BSONObjBuilder optionsBuilder;
|
||||
|
||||
auto const addIfTrue = [&](auto const& keyValuePair) {
|
||||
if (keyValuePair.second)
|
||||
optionsBuilder.appendBool(keyValuePair.first, true);
|
||||
};
|
||||
|
||||
addIfTrue(std::pair{ "unique", indexInfo._unique });
|
||||
addIfTrue(std::pair{ "background", indexInfo._backGround });
|
||||
addIfTrue(std::pair{ "sparse", indexInfo._sparse });
|
||||
|
||||
if (!indexInfo._defaultLanguage.empty())
|
||||
optionsBuilder.append("default_language", indexInfo._defaultLanguage);
|
||||
|
||||
if (!indexInfo._languageOverride.empty())
|
||||
optionsBuilder.append("language_override", indexInfo._languageOverride);
|
||||
|
||||
if (!mongo::Robomongo::fromjson(indexInfo._textWeights).isEmpty())
|
||||
optionsBuilder.append("weights", mongo::Robomongo::fromjson(indexInfo._textWeights));
|
||||
|
||||
if (indexInfo._ttl > 0)
|
||||
optionsBuilder.append("expireAfterSeconds", indexInfo._ttl);
|
||||
|
||||
indexSpec.addOptions(optionsBuilder.obj());
|
||||
return indexSpec;
|
||||
};
|
||||
|
||||
try {
|
||||
_dbclient->createIndex(ns, createIndexSpec(newInfo));
|
||||
}
|
||||
catch (std::exception const& /*ex*/) { // Logging of "ex" is done in upper scope
|
||||
if (editIndex) {
|
||||
// If we are here, index that is being edited, must have already been dropped and
|
||||
// creation of new index failed. So, we try to at least recover the dropped (old) index
|
||||
_dbclient->createIndex(ns, createIndexSpec(oldInfo));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
std::string const errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw std::runtime_error(errorStr);
|
||||
}
|
||||
|
||||
void MongoClient::renameIndexFromCollection(const MongoCollectionInfo &collection, const std::string &oldIndexName, const std::string &newIndexName) const
|
||||
@@ -312,7 +305,7 @@ namespace Robomongo
|
||||
_dbclient->insert(ns.toString(), obj);
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
throw std::runtime_error(errorStr/* , 0 */);
|
||||
} else { // this is update
|
||||
|
||||
std::string name = fun.name();
|
||||
@@ -326,7 +319,7 @@ namespace Robomongo
|
||||
_dbclient->update(ns.toString(), query, obj, true, false);
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
throw std::runtime_error(errorStr);
|
||||
} else { // update function name (remove & insert)
|
||||
_dbclient->insert(ns.toString(), obj);
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
@@ -340,7 +333,7 @@ namespace Robomongo
|
||||
_dbclient->remove(ns.toString(), query, true);
|
||||
}
|
||||
else {
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
throw std::runtime_error(errorStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,7 +351,7 @@ namespace Robomongo
|
||||
_dbclient->remove(ns.toString(), query, true);
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
throw std::runtime_error(errorStr);
|
||||
}
|
||||
|
||||
void MongoClient::createDatabase(const std::string &dbName)
|
||||
@@ -368,12 +361,11 @@ namespace Robomongo
|
||||
* This will create <dbName> database for us.
|
||||
* Finally we are dropping just created temporary collection.
|
||||
*/
|
||||
|
||||
MongoNamespace ns(dbName, "temp");
|
||||
|
||||
// If <dbName>.temp already exists, stop.
|
||||
if (_dbclient->exists(ns.toString()))
|
||||
throw mongo::DBException(dbName + ".temp already exists.", 0);
|
||||
throw std::runtime_error(dbName + ".temp already exists.");
|
||||
|
||||
// Building { _id : "temp" } document
|
||||
mongo::BSONObjBuilder builder;
|
||||
@@ -384,7 +376,7 @@ namespace Robomongo
|
||||
_dbclient->insert(ns.toString(), obj);
|
||||
std::string errorStr = _dbclient->getLastError();
|
||||
if (!errorStr.empty())
|
||||
throw mongo::DBException(errorStr, 0);
|
||||
throw std::runtime_error(errorStr);
|
||||
|
||||
// Drop temp collection
|
||||
_dbclient->dropCollection(ns.toString());
|
||||
@@ -392,13 +384,13 @@ namespace Robomongo
|
||||
|
||||
void MongoClient::dropDatabase(const std::string &dbName)
|
||||
{
|
||||
mongo::BSONObj result;
|
||||
if (!_dbclient->dropDatabase(dbName, &result)) {
|
||||
std::string errStr = result.getStringField("errmsg");
|
||||
mongo::BSONObj info;
|
||||
if (!_dbclient->dropDatabase(dbName, mongo::WriteConcernOptions(), &info)) { // todo: do we catch errorStr via info - test it??
|
||||
std::string errStr = info.toString();
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
throw mongo::DBException(errStr, 0);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,11 +422,11 @@ namespace Robomongo
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
throw mongo::DBException(errStr, 0);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw mongo::DBException("Collection with same name already exists.", 0);
|
||||
throw std::runtime_error("Collection with same name already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,14 +446,13 @@ namespace Robomongo
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
throw mongo::DBException(errStr, 0);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
|
||||
void MongoClient::duplicateCollection(const MongoNamespace &ns, const std::string &newCollectionName)
|
||||
{
|
||||
MongoNamespace sourceCollection(ns);
|
||||
MongoNamespace newCollection(ns.databaseName(), newCollectionName);
|
||||
MongoNamespace const newCollection(ns.databaseName(), newCollectionName);
|
||||
|
||||
if (!_dbclient->exists(newCollection.toString())) {
|
||||
mongo::BSONObj result;
|
||||
@@ -473,18 +464,20 @@ namespace Robomongo
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
throw mongo::DBException(errStr, 0);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw mongo::DBException("Collection with same name already exists.", 0);
|
||||
throw std::runtime_error("Collection with same name already exists.");
|
||||
}
|
||||
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor(_dbclient->query(sourceCollection.toString(), mongo::Query()));
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor {
|
||||
_dbclient->query(mongo::NamespaceString(ns.databaseName(), ns.collectionName()), mongo::Query())
|
||||
};
|
||||
|
||||
// Cursor may be NULL, it means we have connectivity problem
|
||||
if (!cursor)
|
||||
throw mongo::DBException("Network error while attempting to run query", 0);
|
||||
throw std::runtime_error("Network error while attempting to run query");
|
||||
|
||||
while (cursor->more()) {
|
||||
mongo::BSONObj bsonObj = cursor->next();
|
||||
@@ -498,11 +491,14 @@ namespace Robomongo
|
||||
if (!_dbclient->exists(to.toString()))
|
||||
_dbclient->createCollection(to.toString());
|
||||
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor(fromServ->query(from.toString(), mongo::Query()));
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor{fromServ->query(
|
||||
mongo::NamespaceString(from.databaseName(), from.collectionName()),
|
||||
mongo::Query())
|
||||
};
|
||||
|
||||
// Cursor may be NULL, it means we have connectivity problem
|
||||
if (!cursor)
|
||||
throw mongo::DBException("Network error while attempting to run query", 0);
|
||||
throw std::runtime_error("Network error while attempting to run query");
|
||||
|
||||
while (cursor->more()) {
|
||||
mongo::BSONObj bsonObj = cursor->next();
|
||||
@@ -513,17 +509,17 @@ namespace Robomongo
|
||||
void MongoClient::dropCollection(const MongoNamespace &ns)
|
||||
{
|
||||
if (_dbclient->exists(ns.toString())) {
|
||||
mongo::BSONObj result;
|
||||
if (!_dbclient->dropCollection(ns.toString(), &result)) {
|
||||
std::string errStr = result.getStringField("errmsg");
|
||||
mongo::BSONObj info;
|
||||
if (!_dbclient->dropCollection(ns.toString(), mongo::WriteConcernOptions(), &info)) {
|
||||
std::string errStr = info.toString();
|
||||
if (errStr.empty())
|
||||
errStr = "Failed to get error message.";
|
||||
|
||||
throw mongo::DBException(errStr, 0);
|
||||
throw std::runtime_error(errStr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw mongo::DBException("Collection does not exist.", 0);
|
||||
throw std::runtime_error("Collection does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -547,7 +543,7 @@ namespace Robomongo
|
||||
|
||||
void MongoClient::removeDocuments(const MongoNamespace &ns, mongo::Query query, bool justOne /*= true*/)
|
||||
{
|
||||
_dbclient->remove(ns.toString(), query, justOne);
|
||||
_dbclient->remove(ns.toString(), query, justOne);
|
||||
checkLastErrorAndThrow(ns.databaseName());
|
||||
}
|
||||
|
||||
@@ -563,12 +559,14 @@ namespace Robomongo
|
||||
return docs;
|
||||
|
||||
std::unique_ptr<mongo::DBClientCursor> cursor = _dbclient->query(
|
||||
ns.toString(), info._query, info._limit, info._skip,
|
||||
info._fields.nFields() ? &info._fields : 0, info._options, info._batchSize);
|
||||
mongo::NamespaceString(ns.databaseName(), ns.collectionName()),
|
||||
info._query, info._limit, info._skip, info._fields.nFields() ? &info._fields : 0,
|
||||
info._options, info._batchSize
|
||||
);
|
||||
|
||||
// DBClientBase::query may return nullptr
|
||||
if (!cursor)
|
||||
throw mongo::DBException("Network error while attempting to run query", 0);
|
||||
throw std::runtime_error("Network error while attempting to run query");
|
||||
|
||||
while (cursor->more()) {
|
||||
mongo::BSONObj bsonObj = cursor->next();
|
||||
@@ -618,12 +616,10 @@ namespace Robomongo
|
||||
|
||||
void MongoClient::checkLastErrorAndThrow(const std::string &db)
|
||||
{
|
||||
std::string lastError = _dbclient->getLastError(db);
|
||||
|
||||
// Nothing to do when there is no error
|
||||
std::string const lastError = _dbclient->getLastError(db);
|
||||
if (lastError.empty())
|
||||
return;
|
||||
|
||||
throw mongo::DBException(lastError, mongo::ErrorCodes::InternalError);
|
||||
throw std::runtime_error(lastError/*, mongo::ErrorCodes::InternalError*/);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
#include <mongo/bson/bsonobj.h>
|
||||
|
||||
#include "robomongo/core/Core.h"
|
||||
@@ -16,19 +16,20 @@ namespace Robomongo
|
||||
public:
|
||||
MongoClient(mongo::DBClientBase *const scopedConnection);
|
||||
|
||||
std::vector<std::string> getCollectionNames(const std::string &dbname) const;
|
||||
std::vector<std::string> getCollectionNamesWithDbname(const std::string &dbname) const;
|
||||
std::vector<std::string> getDatabaseNames() const;
|
||||
float getVersion() const;
|
||||
std::string dbVersionStr() const;
|
||||
std::string getStorageEngineType() const;
|
||||
|
||||
std::vector<MongoUser> getUsers(const std::string &dbName);
|
||||
void createUser(const std::string &dbName, const MongoUser &user, bool overwrite);
|
||||
void dropUser(const std::string &dbName, const mongo::OID &id);
|
||||
void createUser(const std::string &dbName, const MongoUser &user);
|
||||
void dropUser(const std::string &dbName, const std::string &user);
|
||||
|
||||
std::vector<MongoFunction> getFunctions(const std::string &dbName);
|
||||
std::vector<EnsureIndexInfo> getIndexes(const MongoCollectionInfo &collection) const;
|
||||
std::vector<MongoFunction> getFunctions(const std::string &dbName) const;
|
||||
std::vector<IndexInfo> getIndexes(const MongoCollectionInfo &collection) const;
|
||||
void dropIndexFromCollection(const MongoCollectionInfo &collection, const std::string &indexName) const;
|
||||
void ensureIndex(const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo) const;
|
||||
void addEditIndex(const IndexInfo &oldInfo, const IndexInfo &newInfo) const;
|
||||
|
||||
void renameIndexFromCollection(const MongoCollectionInfo &collection, const std::string &oldIndexName,
|
||||
const std::string &newIndexName) const;
|
||||
|
||||
@@ -23,20 +23,15 @@ namespace Robomongo
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum { pingTimeMs = 60 * 1000 };
|
||||
|
||||
typedef std::vector<std::string> DatabasesContainerType;
|
||||
using DBClientReplicaSet = std::unique_ptr<mongo::DBClientReplicaSet>;
|
||||
using DBClientConnection = std::unique_ptr<mongo::DBClientConnection>;
|
||||
|
||||
public:
|
||||
explicit MongoWorker(ConnectionSettings *connection, bool isLoadMongoRcJs, int batchSize,
|
||||
int mongoTimeoutSec, int shellTimeoutSec, QObject *parent = NULL);
|
||||
double mongoTimeoutSec, int shellTimeoutSec, QObject *parent = nullptr);
|
||||
|
||||
~MongoWorker();
|
||||
void interrupt();
|
||||
void stopAndDelete();
|
||||
|
||||
void changeTimeout(int newTimeout);
|
||||
|
||||
protected Q_SLOTS:
|
||||
|
||||
void init();
|
||||
@@ -79,20 +74,15 @@ namespace Robomongo
|
||||
void handle(LoadCollectionIndexesRequest *event);
|
||||
|
||||
/**
|
||||
* @brief Load indexes in collection
|
||||
* @brief Add/edit indexes in collection
|
||||
*/
|
||||
void handle(EnsureIndexRequest *event);
|
||||
void handle(AddEditIndexRequest *event);
|
||||
|
||||
/**
|
||||
* @brief delete index from collection
|
||||
*/
|
||||
void handle(DropCollectionIndexRequest *event);
|
||||
|
||||
/**
|
||||
* @brief Edit index
|
||||
*/
|
||||
void handle(EditIndexRequest *event);
|
||||
|
||||
/**
|
||||
* @brief Load list of all JS functions
|
||||
*/
|
||||
@@ -117,6 +107,7 @@ namespace Robomongo
|
||||
* @brief Execute javascript
|
||||
*/
|
||||
void handle(ExecuteScriptRequest *event);
|
||||
void retry(ExecuteScriptRequest *event);
|
||||
void handle(StopScriptRequest *event);
|
||||
|
||||
void handle(AutocompleteRequest *event);
|
||||
@@ -126,9 +117,9 @@ namespace Robomongo
|
||||
void handle(CreateCollectionRequest *event);
|
||||
void handle(DropCollectionRequest *event);
|
||||
void handle(RenameCollectionRequest *event);
|
||||
void handle(DuplicateCollectionRequest *event);
|
||||
void handle(CopyCollectionToDiffServerRequest *event);
|
||||
|
||||
void handle(DuplicateCollectionRequest *event);
|
||||
void handle(CopyCollectionToDiffServerRequest *event); // todo: unused? remove
|
||||
|
||||
void handle(CreateUserRequest *event);
|
||||
void handle(DropUserRequest *event);
|
||||
|
||||
@@ -139,15 +130,19 @@ namespace Robomongo
|
||||
virtual void timerEvent(QTimerEvent *);
|
||||
|
||||
private:
|
||||
// Added after Mongo 4.0 to fix connection failures seen after a first edit/add/remove doc. operation
|
||||
void restartReplicaSetConnection();
|
||||
|
||||
/**
|
||||
* @brief Send event to this MongoWorker
|
||||
*/
|
||||
void send(Event *event);
|
||||
|
||||
DatabasesContainerType getDatabaseNamesSafe();
|
||||
std::vector<std::string> getDatabaseNamesSafe(EstablishConnectionRequest* event = nullptr);
|
||||
std::string getAuthBase() const;
|
||||
|
||||
mongo::DBClientBase *getConnection(bool mayReturnNull = false);
|
||||
// Returns a pair of DBClientBase* connection and error string
|
||||
std::pair<mongo::DBClientBase*, std::string> getConnection(bool mayReturnNull = false);
|
||||
MongoClient *getClient();
|
||||
|
||||
/**
|
||||
@@ -168,15 +163,8 @@ namespace Robomongo
|
||||
|
||||
/**
|
||||
*@brief Update Replica Set related parameters/settings.
|
||||
* Warning: Using parameter 'refresh' as false might return incorrect cached values for status
|
||||
* of secondary members.
|
||||
* @param refresh : If true it will be deep scan of replica set status which
|
||||
* might take quite some time. If false, it will be quick scan
|
||||
* which might return incorrect cached values for status of secondary members.
|
||||
* Use false only to achieve quick first connection, in all other cases true
|
||||
* should be used.
|
||||
*/
|
||||
ReplicaSet getReplicaSetInfo(bool refresh = true) const;
|
||||
ReplicaSet getReplicaSetInfo() const;
|
||||
|
||||
std::string connectAndGetReplicaSetName() const;
|
||||
|
||||
@@ -195,12 +183,11 @@ namespace Robomongo
|
||||
|
||||
std::unique_ptr<ScriptEngine> _scriptEngine;
|
||||
|
||||
bool _isAdmin;
|
||||
const bool _isLoadMongoRcJs;
|
||||
const int _batchSize;
|
||||
int _timerId;
|
||||
int _dbAutocompleteCacheTimerId;
|
||||
int _mongoTimeoutSec;
|
||||
double _mongoTimeoutSec;
|
||||
int _shellTimeoutSec;
|
||||
QAtomicInteger<int> _isQuiting;
|
||||
|
||||
@@ -217,4 +204,4 @@ namespace Robomongo
|
||||
std::unordered_set<std::string> _createdDbs;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mongo/util/net/hostandport.h>
|
||||
#include <vector>
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
@@ -15,8 +16,11 @@ namespace Robomongo
|
||||
ReplicaSet() {};
|
||||
|
||||
std::string const setName;
|
||||
mongo::HostAndPort const primary;
|
||||
std::vector<std::pair<std::string, bool>> const membersAndHealths; // pair: {HostNameAndPort, Health}
|
||||
mongo::HostAndPort const primary;
|
||||
std::string const errorStr;
|
||||
|
||||
// pair: {HostNameAndPort, Health}
|
||||
std::vector<std::pair<std::string, bool>> const membersAndHealths;
|
||||
// todo: make first element of pair type HostnameAndPort
|
||||
};
|
||||
}
|
||||
@@ -49,6 +49,8 @@ namespace Robomongo
|
||||
_replicaSetSettings(new ReplicaSetSettings(uri)),
|
||||
_clone(isClone)
|
||||
{
|
||||
// Disabling unfinished feature : Export / Import to / from MongoURI
|
||||
/*
|
||||
if (!uri.getServers().empty()) {
|
||||
_host = uri.getServers().front().host();
|
||||
_port = uri.getServers().front().port();
|
||||
@@ -69,6 +71,7 @@ namespace Robomongo
|
||||
credential->setEnabled(true);
|
||||
}
|
||||
addCredential(credential);
|
||||
*/
|
||||
}
|
||||
|
||||
void ConnectionSettings::fromVariant(const QVariantMap &map) {
|
||||
@@ -166,9 +169,8 @@ namespace Robomongo
|
||||
map.insert("serverPort", serverPort());
|
||||
map.insert("defaultDatabase", QtUtils::toQString(defaultDatabase()));
|
||||
map.insert("isReplicaSet", isReplicaSet());
|
||||
if (isReplicaSet()) {
|
||||
if (isReplicaSet())
|
||||
map.insert("replicaSet", _replicaSetSettings->toVariant());
|
||||
}
|
||||
|
||||
#ifdef MONGO_SSL
|
||||
SSLInfo infl = _info.sslInfo();
|
||||
@@ -176,12 +178,10 @@ namespace Robomongo
|
||||
map.insert("sslPemKeyFile", QtUtils::toQString(infl._sslPEMKeyFile));
|
||||
#endif
|
||||
QVariantList list;
|
||||
for (QList<CredentialSettings *>::const_iterator it = _credentials.begin(); it != _credentials.end(); ++it) {
|
||||
CredentialSettings *credential = *it;
|
||||
list.append(credential->toVariant());
|
||||
}
|
||||
for (auto const& cred : _credentials)
|
||||
list.append(cred->toVariant());
|
||||
|
||||
map.insert("credentials", list);
|
||||
|
||||
map.insert("ssh", _sshSettings->toVariant());
|
||||
map.insert("ssl", _sslSettings->toVariant());
|
||||
map.insert("uuid", _uuid);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include <mongo/client/dbclient_base.h>
|
||||
#include <mongo/client/mongo_uri.h>
|
||||
#include <mongo/util/net/hostandport.h>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "robomongo/core/settings/CredentialSettings.h"
|
||||
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
#include "robomongo/utils/RoboCrypt.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
@@ -9,17 +10,25 @@ namespace Robomongo
|
||||
_userPassword(),
|
||||
_databaseName(),
|
||||
_mechanism(),
|
||||
_enabled(false)
|
||||
_enabled(false),
|
||||
_useManuallyVisibleDbs(false),
|
||||
_manuallyVisibleDbs()
|
||||
{
|
||||
|
||||
}
|
||||
CredentialSettings::CredentialSettings(const QVariantMap &map) :
|
||||
_userName(QtUtils::toStdString(map.value("userName").toString())),
|
||||
_userPassword(QtUtils::toStdString(map.value("userPassword").toString())),
|
||||
_databaseName(QtUtils::toStdString(map.value("databaseName").toString())),
|
||||
_mechanism(QtUtils::toStdString(map.value("mechanism").toString())),
|
||||
_useManuallyVisibleDbs(map.value("useManuallyVisibleDbs").toBool()),
|
||||
_manuallyVisibleDbs(QtUtils::toStdString(map.value("manuallyVisibleDbs").toString())),
|
||||
_enabled(map.value("enabled").toBool())
|
||||
{
|
||||
// From version Robo 1.3 "userPasswordEncrypted" is used instead of "userPassword" in config. file
|
||||
if(map.contains("userPassword")) // Robo 1.2 and below
|
||||
_userPassword = map.value("userPassword").toString().toStdString();
|
||||
else if(map.contains("userPasswordEncrypted")) // From Robo 1.3
|
||||
_userPassword = RoboCrypt::decrypt(map.value("userPasswordEncrypted").toString().toStdString());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,10 +44,13 @@ namespace Robomongo
|
||||
{
|
||||
QVariantMap map;
|
||||
map.insert("userName", QtUtils::toQString(userName()));
|
||||
map.insert("userPassword", QtUtils::toQString(userPassword()));
|
||||
map.insert("userPasswordEncrypted", userPassword().empty() ? "" :
|
||||
QtUtils::toQString(RoboCrypt::encrypt(userPassword())));
|
||||
map.insert("databaseName", QtUtils::toQString(databaseName()));
|
||||
map.insert("mechanism", QtUtils::toQString(mechanism()));
|
||||
map.insert("useManuallyVisibleDbs", _useManuallyVisibleDbs);
|
||||
map.insert("manuallyVisibleDbs", QtUtils::toQString(_manuallyVisibleDbs));
|
||||
map.insert("enabled", enabled());
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace Robomongo
|
||||
void setDatabaseName(const std::string &databaseName) { _databaseName = databaseName; }
|
||||
|
||||
/**
|
||||
* @brief Authentication mechanism (SCRAM-SHA-1 or MONGODB-CR)
|
||||
* @brief Authentication mechanism (SCRAM-SHA-1, SCRAM-SHA-256 or MONGODB-CR)
|
||||
*/
|
||||
std::string mechanism() const { return _mechanism.empty() ? "SCRAM-SHA-1" : _mechanism; }
|
||||
void setMechanism(const std::string &mechanism) { _mechanism = mechanism; }
|
||||
@@ -53,11 +53,19 @@ namespace Robomongo
|
||||
bool enabled() const { return _enabled; }
|
||||
void setEnabled(bool enabled) { _enabled = enabled; }
|
||||
|
||||
bool useManuallyVisibleDbs() const { return _useManuallyVisibleDbs; }
|
||||
void setUseManuallyVisibleDbs(bool enabled) { _useManuallyVisibleDbs = enabled; }
|
||||
|
||||
std::string manuallyVisibleDbs() const { return _manuallyVisibleDbs; }
|
||||
void setManuallyVisibleDbs(std::string const& dbs) { _manuallyVisibleDbs = dbs; }
|
||||
|
||||
private:
|
||||
std::string _userName;
|
||||
std::string _userPassword;
|
||||
std::string _userPassword; // clear text password (decrypted)
|
||||
std::string _databaseName;
|
||||
std::string _mechanism; // authentication mechanism (MONGODB-CR or SCRAM-SHA-1)
|
||||
std::string _mechanism; // authentication mechanism (SCRAM-SHA-1, SCRAM-SHA-256 or MONGODB-CR)
|
||||
bool _useManuallyVisibleDbs;
|
||||
std::string _manuallyVisibleDbs;
|
||||
|
||||
/**
|
||||
* @brief Flag, indecating whether we should use this
|
||||
|
||||
@@ -6,19 +6,7 @@
|
||||
#include <QUuid>
|
||||
#include <QJsonArray>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
// Todo:
|
||||
// Warning:
|
||||
// Currently, this include statement should be maintained manually.
|
||||
// The Qt version must be updated if Qt is upgraded. Otherwise it might cause build error.
|
||||
// The correct path will be: PROJECT_QT_VERSION/QtGui/private/qzipreader_p.h
|
||||
// Details:
|
||||
// Ideally, private class inside qzipreader_p.h should not be used since it is not
|
||||
// a publicly/officially supported API by Qt. It is used here since we are doing a
|
||||
// a very lightweight zip operation which is unzipping a zip archive with one, small file.
|
||||
// The alternative is including QuaZip and Zlib third party libraries into CMAKE project and
|
||||
// building, and using them which might be time consuming.
|
||||
#include <5.7.0/QtGui/private/qzipreader_p.h>
|
||||
#include <QDirIterator>
|
||||
|
||||
#include <parser.h>
|
||||
#include <serializer.h>
|
||||
@@ -32,14 +20,24 @@
|
||||
#include "robomongo/core/utils/StdUtils.h"
|
||||
#include "robomongo/gui/AppStyle.h"
|
||||
#include "robomongo/utils/common.h"
|
||||
#include "robomongo/utils/qzip/qzipreader_p.h"
|
||||
#include "robomongo/utils/RoboCrypt.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
// 3T config files
|
||||
auto const Studio3T_PropertiesDat = QString("%1/.3T/studio-3t/properties.dat").arg(QDir::homePath());
|
||||
auto const DataMongodb_PropertiesDat = QString("%1/.3T/data-man-mongodb/properties.dat").arg(QDir::homePath());
|
||||
auto const MongoChefPro_PropertiesDat = QString("%1/.3T/mongochef-pro/properties.dat").arg(QDir::homePath());
|
||||
auto const MongoChefEnt_PropertiesDat = QString("%1/.3T/mongochef-enterprise/properties.dat").arg(QDir::homePath());
|
||||
auto const Studio3T_PropertiesDat {
|
||||
QString("%1/.3T/studio-3t/properties.dat").arg(QDir::homePath())
|
||||
};
|
||||
auto const DataMongodb_PropertiesDat {
|
||||
QString("%1/.3T/data-man-mongodb/properties.dat").arg(QDir::homePath())
|
||||
};
|
||||
auto const MongoChefPro_PropertiesDat {
|
||||
QString("%1/.3T/mongochef-pro/properties.dat").arg(QDir::homePath())
|
||||
};
|
||||
auto const MongoChefEnt_PropertiesDat {
|
||||
QString("%1/.3T/mongochef-enterprise/properties.dat").arg(QDir::homePath())
|
||||
};
|
||||
|
||||
const std::vector<std::pair<QString, QString>> S_3T_ZipFile_And_ConfigFile_List
|
||||
{
|
||||
@@ -50,46 +48,49 @@ namespace Robomongo
|
||||
};
|
||||
|
||||
// Extract zipFile and find the value of "anonymousID" field in propFile
|
||||
QString extractAnonymousID(QString const& zipFile, QString const& propfile);
|
||||
QString extractAnonymousIDFromZip(QString const& zipFile, QString const& propfile);
|
||||
|
||||
// Extract "anonymousID" from a config file
|
||||
QString extractAnonymousID(QString const& configFile);
|
||||
|
||||
/**
|
||||
* @brief Version of schema
|
||||
*/
|
||||
const QString SchemaVersion = "2.0";
|
||||
|
||||
}
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Robomongo config. files
|
||||
*/
|
||||
const auto CONFIG_FILE_0_8_5 = QString("%1/.config/robomongo/robomongo.json").arg(QDir::homePath());
|
||||
const auto CONFIG_FILE_0_9 = QString("%1/.config/robomongo/0.9/robomongo.json").arg(QDir::homePath());
|
||||
const auto CONFIG_FILE_1_0_RC1 = QString("%1/.config/robomongo/1.0/robomongo.json").arg(QDir::homePath());
|
||||
// Change of path due to re-branding to 3T
|
||||
const auto CONFIG_FILE_1_0_0 = QString("%1/.3T/robomongo/1.0.0/robomongo.json").arg(QDir::homePath());
|
||||
|
||||
struct ConfigFileAndImportFunction
|
||||
{
|
||||
ConfigFileAndImportFunction(QString const& configFile, std::function<bool()> importFunction)
|
||||
: file(configFile), import(importFunction) {}
|
||||
|
||||
QString file;
|
||||
std::function<bool()> import;
|
||||
const auto CONFIG_FILE_0_8_5 {
|
||||
QString("%1/.config/robomongo/robomongo.json").arg(QDir::homePath())
|
||||
};
|
||||
const auto CONFIG_FILE_1_0_RC1 {
|
||||
QString("%1/.config/robomongo/1.0/robomongo.json").arg(QDir::homePath())
|
||||
};
|
||||
const auto CONFIG_FILE_1_1_0_BETA {
|
||||
QString("%1/.3T/robomongo/1.1.0-Beta/robomongo.json").arg(QDir::homePath())
|
||||
};
|
||||
|
||||
// Warning: Config. file and import function of a new release must be placed as first element of
|
||||
// vector initializer list below in order.
|
||||
std::vector<ConfigFileAndImportFunction> const SettingsManager::_configFilesAndImportFunctions
|
||||
/**
|
||||
* @brief Robomongo config. files of old versions
|
||||
*/
|
||||
// Important: In order to import connections from a version, config. file path must
|
||||
// be defined and placed into the vector initializer list below in order.
|
||||
std::vector<QString> const SettingsManager::_configFilesOfOldVersions
|
||||
{
|
||||
ConfigFileAndImportFunction(CONFIG_FILE_1_0_RC1, SettingsManager::importConnectionsFrom_1_0_RC1_to_1_0_0),
|
||||
ConfigFileAndImportFunction(CONFIG_FILE_0_9, SettingsManager::importConnectionsFrom_0_9_to_1_0_RC1),
|
||||
ConfigFileAndImportFunction(CONFIG_FILE_0_8_5, SettingsManager::importConnectionsFrom_0_8_5_to_0_9)
|
||||
QString("%1/.3T/robo-3t/1.4.1/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_4_1
|
||||
QString("%1/.3T/robo-3t/1.4.0/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_4_0
|
||||
QString("%1/.3T/robo-3t/1.3.1/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_3_1
|
||||
QString("%1/.3T/robo-3t/1.3.0/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_3_0_BETA
|
||||
QString("%1/.3T/robo-3t/1.2.1/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_2_1
|
||||
QString("%1/.3T/robo-3t/1.2.0/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_2_0_BETA
|
||||
QString("%1/.3T/robo-3t/1.1.1/robo3t.json").arg(QDir::homePath()), // CONFIG_FILE_1_1_1
|
||||
CONFIG_FILE_1_1_0_BETA, // CONFIG_FILE_1_1_0_BETA
|
||||
QString("%1/.3T/robomongo/1.0.0/robomongo.json").arg(QDir::homePath()), // CONFIG_FILE_1_0_0
|
||||
CONFIG_FILE_1_0_RC1, // CONFIG_FILE_1_0_RC1
|
||||
QString("%1/.config/robomongo/0.9/robomongo.json").arg(QDir::homePath()), // CONFIG_FILE_0_9
|
||||
CONFIG_FILE_0_8_5 // CONFIG_FILE_0_8_5
|
||||
};
|
||||
|
||||
std::vector<ConnectionSettings*> SettingsManager::_connections;
|
||||
|
||||
// Temporarily disabling Recent Connections feature
|
||||
// std::vector<RecentConnection> SettingsManager::_recentConnections;
|
||||
|
||||
@@ -112,8 +113,12 @@ namespace Robomongo
|
||||
_textFontPointSize(-1),
|
||||
_mongoTimeoutSec(10),
|
||||
_shellTimeoutSec(15),
|
||||
_imported(false)
|
||||
_imported(false)
|
||||
{
|
||||
if (!QDir().mkpath(ConfigDir))
|
||||
LOG_MSG("ERROR: Could not create settings path: " + ConfigDir, mongo::logger::LogSeverity::Error());
|
||||
|
||||
RoboCrypt::initKey();
|
||||
if (!load()) { // if load fails (probably due to non-existing config. file or directory)
|
||||
save(); // create empty settings file
|
||||
load(); // try loading again for the purpose of import from previous Robomongo versions
|
||||
@@ -157,12 +162,7 @@ namespace Robomongo
|
||||
*/
|
||||
bool SettingsManager::save()
|
||||
{
|
||||
QVariantMap map = convertToMap();
|
||||
|
||||
if (!QDir().mkpath(ConfigDir)) {
|
||||
LOG_MSG("ERROR: Could not create settings path: " + ConfigDir, mongo::logger::LogSeverity::Error());
|
||||
return false;
|
||||
}
|
||||
QVariantMap const& map = convertToMap();
|
||||
|
||||
QFile f(ConfigFilePath);
|
||||
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
@@ -222,6 +222,13 @@ namespace Robomongo
|
||||
_minimizeToTray = map.contains("minimizeToTray") ? map.value("minimizeToTray").toBool() : false;
|
||||
_lineNumbers = map.contains("lineNumbers") ? map.value("lineNumbers").toBool() : false;
|
||||
_imported = map.contains("imported") ? map.value("imported").toBool() : false;
|
||||
_programExitedNormally = map.contains("programExitedNormally") ?
|
||||
map.value("programExitedNormally").toBool() : true;
|
||||
|
||||
_disableHttpsFeatures = map.contains("disableHttpsFeatures") ?
|
||||
map.value("disableHttpsFeatures").toBool() : false;
|
||||
|
||||
_debugMode = map.contains("debugMode") ? map.value("debugMode").toBool() : false;
|
||||
|
||||
// 4. Load TimeZone
|
||||
int timeZone = map.value("timeZone").toInt();
|
||||
@@ -235,6 +242,9 @@ namespace Robomongo
|
||||
if (map.contains("acceptedEulaVersions"))
|
||||
_acceptedEulaVersions = map.value("acceptedEulaVersions").toStringList().toSet();
|
||||
|
||||
if (map.contains("dbVersionsConnected"))
|
||||
_dbVersionsConnected = map.value("dbVersionsConnected").toStringList().toSet();
|
||||
|
||||
// Load anonymousID
|
||||
_anonymousID = getOrCreateAnonymousID(map);
|
||||
|
||||
@@ -358,6 +368,13 @@ namespace Robomongo
|
||||
|
||||
map.insert("acceptedEulaVersions", arr.toVariantList());
|
||||
|
||||
// x. Save unique set of db versions connected
|
||||
QJsonArray dbVersionsArr;
|
||||
for (auto const& version : _dbVersionsConnected)
|
||||
dbVersionsArr.push_back(version);
|
||||
|
||||
map.insert("dbVersionsConnected", dbVersionsArr.toVariantList());
|
||||
|
||||
// 9. Save batchSize
|
||||
map.insert("batchSize", _batchSize);
|
||||
map.insert("checkForUpdates", _checkForUpdates);
|
||||
@@ -396,7 +413,10 @@ namespace Robomongo
|
||||
map.insert("imported", _imported);
|
||||
map.insert("anonymousID", _anonymousID);
|
||||
map.insert("cacheData", _cacheData);
|
||||
|
||||
map.insert("programExitedNormally", _programExitedNormally);
|
||||
map.insert("disableHttpsFeatures", _disableHttpsFeatures);
|
||||
map.insert("debugMode", _debugMode);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -411,18 +431,62 @@ namespace Robomongo
|
||||
anonymousID = id.toString();
|
||||
}
|
||||
|
||||
// Search and import "anonymousID" from other Studio 3T config files
|
||||
for (auto const& zipFileAndConfigFile : S_3T_ZipFile_And_ConfigFile_List) {
|
||||
if (!anonymousID.isEmpty())
|
||||
break;
|
||||
|
||||
QUuid const& id = extractAnonymousID(zipFileAndConfigFile.first, zipFileAndConfigFile.second);
|
||||
QUuid const& id = extractAnonymousIDFromZip(zipFileAndConfigFile.first, zipFileAndConfigFile.second);
|
||||
if (!id.isNull())
|
||||
anonymousID = id.toString();
|
||||
}
|
||||
|
||||
// Search and import "anonymousID" from other Robo 3T old config files starting from latest
|
||||
for (auto const& oldConfigFile : _configFilesOfOldVersions) {
|
||||
if (!anonymousID.isEmpty())
|
||||
break;
|
||||
|
||||
// Don't import from 1.1-Beta due to a problem where Beta might have redundantly created new UUID
|
||||
if (oldConfigFile == CONFIG_FILE_1_1_0_BETA)
|
||||
continue;
|
||||
|
||||
// Stop searching in 1_0_RC1 or older versions, "anonymousID" is introduced in version 1.0
|
||||
if (oldConfigFile == CONFIG_FILE_1_0_RC1)
|
||||
break;
|
||||
|
||||
anonymousID = extractAnonymousID(oldConfigFile);
|
||||
}
|
||||
|
||||
// Search and import "anonymousID" from any other (ideally newer version) Robo 3T config files
|
||||
if (anonymousID.isEmpty()) {
|
||||
auto const dir1 = QString("%1/.3T/robo-3t").arg(QDir::homePath());
|
||||
QDirIterator iter1 { dir1, QStringList() << "robo*.json", QDir::Files,
|
||||
QDirIterator::Subdirectories };
|
||||
while (iter1.hasNext()) {
|
||||
anonymousID = extractAnonymousID(iter1.next());
|
||||
if (!anonymousID.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
if (anonymousID.isEmpty()) {
|
||||
auto const dir2 = QString("%1/.3T/robomongo").arg(QDir::homePath());
|
||||
QDirIterator iter2 { dir2, QStringList() << "robo*.json", QDir::Files,
|
||||
QDirIterator::Subdirectories };
|
||||
while (iter2.hasNext()) {
|
||||
anonymousID = extractAnonymousID(iter2.next());
|
||||
if (!anonymousID.isEmpty())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find/import any, create a new anonymousID
|
||||
if (anonymousID.isEmpty())
|
||||
anonymousID = QUuid::createUuid().toString();
|
||||
|
||||
anonymousID.remove('{');
|
||||
anonymousID.remove('}');
|
||||
|
||||
return anonymousID;
|
||||
}
|
||||
|
||||
@@ -516,21 +580,21 @@ namespace Robomongo
|
||||
|
||||
void SettingsManager::importConnections()
|
||||
{
|
||||
// Skip when settings already imported
|
||||
// Do not import if already imported
|
||||
if (_imported)
|
||||
return;
|
||||
|
||||
// Find and import 'only' from the latest version
|
||||
for (auto const& configFileAndImportFunction : _configFilesAndImportFunctions) {
|
||||
if (QFile::exists(configFileAndImportFunction.file)) {
|
||||
configFileAndImportFunction.import();
|
||||
// Find and import 'only' from the latest version to current version
|
||||
for (auto const& configFile : _configFilesOfOldVersions) {
|
||||
if (QFile::exists(configFile)) {
|
||||
importConnectionsFromOldVersion(configFile);
|
||||
setImported(true); // Mark as imported
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingsManager::importConnectionsFrom_0_8_5_to_0_9()
|
||||
bool SettingsManager::importConnectionsFrom_0_8_5()
|
||||
{
|
||||
// Load old configuration file (used till version 0.8.5)
|
||||
|
||||
@@ -570,7 +634,7 @@ namespace Robomongo
|
||||
ssh->setPrivateKeyFile(QtUtils::toStdString(vconn.value("sshPrivateKey").toString()));
|
||||
ssh->setPassphrase(QtUtils::toStdString(vconn.value("sshPassphrase").toString()));
|
||||
|
||||
int auth = vconn.value("sshAuthMethod").toInt();
|
||||
int const auth = vconn.value("sshAuthMethod").toInt();
|
||||
ssh->setEnabled(auth == 1 || auth == 2);
|
||||
ssh->setAuthMethod(auth == 2 ? "publickey" : "password");
|
||||
}
|
||||
@@ -588,10 +652,12 @@ namespace Robomongo
|
||||
QVariantMap vcred = (*itcred).toMap();
|
||||
|
||||
auto cred = new CredentialSettings();
|
||||
cred->setUserName(QtUtils::toStdString(vcred.value("userName").toString()));
|
||||
cred->setUserPassword(QtUtils::toStdString(vcred.value("userPassword").toString()));
|
||||
cred->setDatabaseName(QtUtils::toStdString(vcred.value("databaseName").toString()));
|
||||
cred->setUserName(vcred.value("userName").toString().toStdString());
|
||||
cred->setUserPassword(vcred.value("userPassword").toString().toStdString());
|
||||
cred->setDatabaseName(vcred.value("databaseName").toString().toStdString());
|
||||
cred->setMechanism("MONGODB-CR");
|
||||
cred->setUseManuallyVisibleDbs(vcred.value("useManuallyVisibleDbs").toBool());
|
||||
cred->setManuallyVisibleDbs(vcred.value("manuallyVisibleDbs").toString().toStdString());
|
||||
cred->setEnabled(vcred.value("enabled").toBool());
|
||||
|
||||
conn->addCredential(cred);
|
||||
@@ -637,18 +703,13 @@ namespace Robomongo
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SettingsManager::importConnectionsFrom_0_9_to_1_0_RC1()
|
||||
{
|
||||
return importConnectionsFromOldVersion(CONFIG_FILE_0_9);
|
||||
}
|
||||
|
||||
bool SettingsManager::importConnectionsFrom_1_0_RC1_to_1_0_0()
|
||||
{
|
||||
return importConnectionsFromOldVersion(CONFIG_FILE_1_0_RC1);
|
||||
}
|
||||
|
||||
bool SettingsManager::importConnectionsFromOldVersion(QString const& oldConfigFilePath)
|
||||
{
|
||||
if (oldConfigFilePath == CONFIG_FILE_0_8_5) {
|
||||
importConnectionsFrom_0_8_5();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!QFile::exists(oldConfigFilePath))
|
||||
return false;
|
||||
|
||||
@@ -687,7 +748,7 @@ namespace Robomongo
|
||||
return count;
|
||||
}
|
||||
|
||||
QString extractAnonymousID(QString const& zipFile, QString const& propfile)
|
||||
QString extractAnonymousIDFromZip(QString const& zipFile, QString const& propfile)
|
||||
{
|
||||
QZipReader zipReader(zipFile);
|
||||
if (!zipReader.exists() || !zipReader.isReadable())
|
||||
@@ -708,4 +769,31 @@ namespace Robomongo
|
||||
return QString("");
|
||||
}
|
||||
|
||||
QString extractAnonymousID(QString const& configFilePath)
|
||||
{
|
||||
if (!QFile::exists(configFilePath))
|
||||
return QString("");
|
||||
|
||||
QFile oldConfigFile(configFilePath);
|
||||
if (!oldConfigFile.open(QIODevice::ReadOnly))
|
||||
return QString("");
|
||||
|
||||
bool ok = false;
|
||||
QJson::Parser parser;
|
||||
QVariantMap const& map = parser.parse(oldConfigFile.readAll(), &ok).toMap();
|
||||
if (!ok)
|
||||
return QString("");
|
||||
|
||||
QString anonymousID;
|
||||
if (map.contains("anonymousID")) {
|
||||
QUuid const& id = map.value("anonymousID").toString();
|
||||
if (!id.isNull())
|
||||
anonymousID = id.toString();
|
||||
}
|
||||
|
||||
anonymousID.remove('{');
|
||||
anonymousID.remove('}');
|
||||
|
||||
return anonymousID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
#include <QVariantMap>
|
||||
#include <QSet>
|
||||
#include <QDir>
|
||||
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "robomongo/core/Enums.h"
|
||||
|
||||
namespace Robomongo
|
||||
@@ -13,14 +16,14 @@ namespace Robomongo
|
||||
struct ConfigFileAndImportFunction;
|
||||
|
||||
// Current cache directory
|
||||
QString const CacheDir = QString("%1/.3T/robomongo/%2/cache/").arg(QDir::homePath())
|
||||
.arg(PROJECT_VERSION);
|
||||
auto const CacheDir = QString("%1/.3T/robo-3t/%2/cache/").arg(QDir::homePath())
|
||||
.arg(PROJECT_VERSION);
|
||||
// Current config file
|
||||
QString const ConfigFilePath = QString("%1/.3T/robomongo/%2/robomongo.json").arg(QDir::homePath())
|
||||
.arg(PROJECT_VERSION);
|
||||
auto const ConfigFilePath = QString("%1/.3T/robo-3t/%2/robo3t.json").arg(QDir::homePath())
|
||||
.arg(PROJECT_VERSION);
|
||||
// Current config file directory
|
||||
QString const ConfigDir = QString("%1/.3T/robomongo/%2/").arg(QDir::homePath())
|
||||
.arg(PROJECT_VERSION);
|
||||
auto const ConfigDir = QString("%1/.3T/robo-3t/%2/").arg(QDir::homePath())
|
||||
.arg(PROJECT_VERSION);
|
||||
/* Temporarily disabling Recent Connections feature
|
||||
struct RecentConnection
|
||||
{
|
||||
@@ -158,6 +161,11 @@ namespace Robomongo
|
||||
void addAcceptedEulaVersion(QString const& version) { _acceptedEulaVersions.insert(version); }
|
||||
QSet<QString> const& acceptedEulaVersions() const { return _acceptedEulaVersions; }
|
||||
|
||||
QSet<QString>::iterator addDbVersionConnected(QString const& version) {
|
||||
return _dbVersionsConnected.insert(version);
|
||||
}
|
||||
QSet<QString> const& dbVersionsConnected() const { return _dbVersionsConnected; }
|
||||
|
||||
void setCheckForUpdates(bool checkForUpdates) { _checkForUpdates = checkForUpdates; }
|
||||
bool checkForUpdates() const { return _checkForUpdates; }
|
||||
|
||||
@@ -176,6 +184,8 @@ namespace Robomongo
|
||||
int mongoTimeoutSec() const { return _mongoTimeoutSec; }
|
||||
int shellTimeoutSec() const { return _shellTimeoutSec; }
|
||||
|
||||
void setShellTimeoutSec(int newValue) { _shellTimeoutSec = std::abs(newValue); }
|
||||
|
||||
// True when settings from previous versions of Robomongo are imported
|
||||
void setImported(bool imported) { _imported = imported; }
|
||||
bool imported() const { return _imported; }
|
||||
@@ -185,6 +195,13 @@ namespace Robomongo
|
||||
void addCacheData(QString const& key, QVariant const& value);
|
||||
QVariant cacheData(QString const& key) const;
|
||||
|
||||
void setProgramExitedNormally(bool value) { _programExitedNormally = value; }
|
||||
bool programExitedNormally() const { return _programExitedNormally; }
|
||||
|
||||
// Designed to be set only by human users
|
||||
bool disableHttpsFeatures() const { return _disableHttpsFeatures; }
|
||||
bool debugMode() const { return _debugMode; }
|
||||
|
||||
/**
|
||||
* Returns number of imported connections
|
||||
*/
|
||||
@@ -214,9 +231,7 @@ namespace Robomongo
|
||||
// Imports connections from oldConfigFilePath into current config file
|
||||
static bool importConnectionsFromOldVersion(QString const& oldConfigFilePath);
|
||||
|
||||
static bool importConnectionsFrom_0_8_5_to_0_9();
|
||||
static bool importConnectionsFrom_0_9_to_1_0_RC1();
|
||||
static bool importConnectionsFrom_1_0_RC1_to_1_0_0();
|
||||
static bool importConnectionsFrom_0_8_5();
|
||||
|
||||
/**
|
||||
* @brief Version of settings schema currently loaded
|
||||
@@ -233,7 +248,11 @@ namespace Robomongo
|
||||
bool _minimizeToTray;
|
||||
bool _lineNumbers;
|
||||
bool _disableConnectionShortcuts;
|
||||
bool _programExitedNormally = true;
|
||||
bool _disableHttpsFeatures = false;
|
||||
bool _debugMode = false;
|
||||
QSet<QString> _acceptedEulaVersions;
|
||||
QSet<QString> _dbVersionsConnected;
|
||||
int _batchSize;
|
||||
bool _checkForUpdates = true;
|
||||
QString _currentStyle;
|
||||
@@ -268,8 +287,8 @@ namespace Robomongo
|
||||
|
||||
ToolbarSettingsContainerType _toolbars;
|
||||
|
||||
// List of config. file absolute paths and related import functions.
|
||||
// List of config. file absolute paths of old versions
|
||||
// Must be updated with care and with every new version. Details on cpp file.
|
||||
static const std::vector<ConfigFileAndImportFunction> _configFilesAndImportFunctions;
|
||||
static std::vector<QString> const _configFilesOfOldVersions;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "robomongo/core/settings/SshSettings.h"
|
||||
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
#include "robomongo/utils/RoboCrypt.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
@@ -23,10 +24,12 @@ namespace Robomongo
|
||||
map.insert("host", QtUtils::toQString(host()));
|
||||
map.insert("port", port());
|
||||
map.insert("userName", QtUtils::toQString(userName()));
|
||||
map.insert("userPassword", QtUtils::toQString(userPassword()));
|
||||
map.insert("userPasswordEncrypted", userPassword().empty() ? "" :
|
||||
QtUtils::toQString(RoboCrypt::encrypt(userPassword())));
|
||||
map.insert("privateKeyFile", QtUtils::toQString(privateKeyFile()));
|
||||
map.insert("publicKeyFile", QtUtils::toQString(publicKeyFile()));
|
||||
map.insert("passphrase", QtUtils::toQString(passphrase()));
|
||||
map.insert("passphraseEncrypted", passphrase().empty() ? "" :
|
||||
QtUtils::toQString(RoboCrypt::encrypt(passphrase())));
|
||||
map.insert("method", QtUtils::toQString(authMethod()));
|
||||
map.insert("enabled", enabled());
|
||||
map.insert("askPassword", askPassword());
|
||||
@@ -37,10 +40,22 @@ namespace Robomongo
|
||||
setHost(QtUtils::toStdString(map.value("host").toString()));
|
||||
setPort(map.value("port").toInt());
|
||||
setUserName(QtUtils::toStdString(map.value("userName").toString()));
|
||||
setUserPassword(QtUtils::toStdString(map.value("userPassword").toString()));
|
||||
|
||||
// From version Robo 1.3 "userPasswordEncrypted" is used instead of "userPassword" in config. file
|
||||
if (map.contains("userPassword")) // Robo 1.2 and below
|
||||
setUserPassword((map.value("userPassword").toString().toStdString()));
|
||||
else if (map.contains("userPasswordEncrypted")) // From Robo 1.3
|
||||
setUserPassword(RoboCrypt::decrypt((map.value("userPasswordEncrypted").toString().toStdString())));
|
||||
|
||||
setPrivateKeyFile(QtUtils::toStdString(map.value("privateKeyFile").toString()));
|
||||
setPublicKeyFile(QtUtils::toStdString(map.value("publicKeyFile").toString()));
|
||||
setPassphrase(QtUtils::toStdString(map.value("passphrase").toString()));
|
||||
|
||||
// From version Robo 1.3 "passphraseEncrypted" is used instead of "passphrase" in config. file
|
||||
if (map.contains("passphrase")) // Robo 1.2 and below
|
||||
setPassphrase((map.value("passphrase").toString().toStdString()));
|
||||
else if (map.contains("passphraseEncrypted")) // From Robo 1.3
|
||||
setPassphrase(RoboCrypt::decrypt((map.value("passphraseEncrypted").toString().toStdString())));
|
||||
|
||||
setAuthMethod(QtUtils::toStdString(map.value("method").toString()));
|
||||
setEnabled(map.value("enabled").toBool());
|
||||
setAskPassword(map.value("askPassword").toBool());
|
||||
|
||||