1 // Copyright (C) 2013 James Turner - zakalawe@mac.com
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 //
17
18 #include <simgear_config.h>
19
20 #include <simgear/io/HTTPClient.hxx>
21 #include <simgear/package/Catalog.hxx>
22 #include <simgear/package/Package.hxx>
23 #include <simgear/package/Install.hxx>
24 #include <simgear/package/Root.hxx>
25 #include <simgear/misc/sg_dir.hxx>
26
27 #include <iostream>
28 #include <cstring>
29
30 using namespace simgear;
31 using namespace std;
32
33 bool keepRunning = true;
34
35 class MyDelegate : public pkg::Delegate
36 {
37 public:
catalogRefreshed(pkg::CatalogRef aCatalog,StatusCode aReason)38 virtual void catalogRefreshed(pkg::CatalogRef aCatalog, StatusCode aReason)
39 {
40 if (aReason == STATUS_REFRESHED) {
41 if (aCatalog.ptr() == NULL) {
42 cout << "refreshed all catalogs" << endl;
43 } else {
44 cout << "refreshed catalog " << aCatalog->url() << endl;
45 }
46 } else if (aReason == STATUS_IN_PROGRESS) {
47 cout << "started refresh of " << aCatalog->url() << endl;
48 } else {
49 cerr << "failed refresh of " << aCatalog->url() << ":" << aReason << endl;
50 }
51 }
52
startInstall(pkg::InstallRef aInstall)53 virtual void startInstall(pkg::InstallRef aInstall)
54 {
55 _lastPercent = 999;
56 cout << "starting install of " << aInstall->package()->name() << endl;
57 }
58
installProgress(pkg::InstallRef aInstall,unsigned int bytes,unsigned int total)59 virtual void installProgress(pkg::InstallRef aInstall, unsigned int bytes, unsigned int total)
60 {
61 size_t percent = (static_cast<size_t>(bytes) * 100) / total;
62 if (percent == _lastPercent) {
63 return;
64 }
65
66 _lastPercent = percent;
67 cout << percent << "%" << endl;
68 }
69
finishInstall(pkg::InstallRef aInstall,StatusCode aReason)70 virtual void finishInstall(pkg::InstallRef aInstall, StatusCode aReason)
71 {
72 if (aReason == STATUS_SUCCESS) {
73 cout << "done install of " << aInstall->package()->name() << endl;
74 } else {
75 cerr << "failed install of " << aInstall->package()->name() << endl;
76 }
77 }
78
79 private:
80 size_t _lastPercent;
81
82 };
83
printRating(pkg::Package * pkg,const std::string & aRating,const std::string & aLabel)84 void printRating(pkg::Package* pkg, const std::string& aRating, const std::string& aLabel)
85 {
86 SGPropertyNode* ratings = pkg->properties()->getChild("rating");
87 cout << "\t" << aLabel << ":" << ratings->getIntValue(aRating) << endl;
88 }
89
printPackageInfo(pkg::Package * pkg)90 void printPackageInfo(pkg::Package* pkg)
91 {
92 cout << "Package:" << pkg->catalog()->id() << "." << pkg->id() << endl;
93 cout << "Revision:" << pkg->revision() << endl;
94 cout << "Name:" << pkg->name() << endl;
95 cout << "Description:" << pkg->description() << endl;
96 cout << "Long description:\n" << pkg->getLocalisedProp("long-description") << endl << endl;
97
98 if (pkg->properties()->hasChild("author")) {
99 cout << "Authors:" << endl;
100 for (auto author : pkg->properties()->getChildren("author")) {
101 if (author->hasChild("name")) {
102 cout << "\t" << author->getStringValue("name") << endl;
103
104 } else {
105 // simple author structure
106 cout << "\t" << author->getStringValue() << endl;
107 }
108
109
110 }
111
112 cout << endl;
113 }
114
115 cout << "Ratings:" << endl;
116 printRating(pkg, "fdm", "Flight-model ");
117 printRating(pkg, "cockpit", "Cockpit ");
118 printRating(pkg, "model", "3D model ");
119 printRating(pkg, "systems", "Aircraft systems");
120 }
121
main(int argc,char ** argv)122 int main(int argc, char** argv)
123 {
124 sglog().setLogLevels( SG_ALL, SG_INFO );
125
126 HTTP::Client* http = new HTTP::Client();
127
128 SGPath rootPath = SGPath::fromEnv("SG_PKG_ROOT", Dir::current().path());
129 pkg::Root* root = new pkg::Root(rootPath, "2019.1.1");
130
131 MyDelegate dlg;
132 root->addDelegate(&dlg);
133
134 cout << "Package root is:" << rootPath << endl;
135 cout << "have " << root->catalogs().size() << " catalog(s)" << endl;
136
137 root->setHTTPClient(http);
138
139 if (!strcmp(argv[1], "add")) {
140 std::string url(argv[2]);
141 pkg::Catalog::createFromUrl(root, url);
142 } else if (!strcmp(argv[1], "refresh")) {
143 root->refresh(true);
144 } else if (!strcmp(argv[1], "install")) {
145 pkg::PackageRef pkg = root->getPackageById(argv[2]);
146 if (!pkg) {
147 cerr << "unknown package:" << argv[2] << endl;
148 return EXIT_FAILURE;
149 }
150
151 if (pkg->isInstalled()) {
152 cout << "package " << pkg->id() << " is already installed at " << pkg->install()->path() << endl;
153 return EXIT_SUCCESS;
154 }
155
156 pkg::CatalogRef catalog = pkg->catalog();
157 cout << "Will install:" << pkg->id() << " from " << catalog->id() <<
158 "(" << catalog->description() << ")" << endl;
159 pkg->install();
160 } else if (!strcmp(argv[1], "uninstall") || !strcmp(argv[1], "remove")) {
161 pkg::PackageRef pkg = root->getPackageById(argv[2]);
162 if (!pkg) {
163 cerr << "unknown package:" << argv[2] << endl;
164 return EXIT_FAILURE;
165 }
166
167 if (!pkg->isInstalled()) {
168 cerr << "package " << argv[2] << " not installed" << endl;
169 return EXIT_FAILURE;
170 }
171
172 cout << "Will uninstall:" << pkg->id() << endl;
173 pkg->install()->uninstall();
174 } else if (!strcmp(argv[1], "update-all")) {
175 pkg::PackageList updates = root->packagesNeedingUpdate();
176 for (auto p : updates) {
177 root->scheduleToUpdate(p->install());
178 }
179 } else if (!strcmp(argv[1], "list-updated")) {
180 pkg::PackageList updates = root->packagesNeedingUpdate();
181 if (updates.empty()) {
182 cout << "no packages with updates" << endl;
183 return EXIT_SUCCESS;
184 }
185
186 cout << updates.size() << " packages have updates" << endl;
187 for (auto p : updates) {
188 cout << "\t" << p->id() << " " << p->getLocalisedProp("name") << endl;
189 }
190 } else if (!strcmp(argv[1], "info")) {
191 pkg::PackageRef pkg = root->getPackageById(argv[2]);
192 if (!pkg) {
193 cerr << "unknown package:" << argv[2] << endl;
194 return EXIT_FAILURE;
195 }
196
197 printPackageInfo(pkg);
198 } else {
199 cerr << "unknown command:" << argv[1] << endl;
200 return EXIT_FAILURE;
201 }
202
203 while (http->hasActiveRequests()) {
204 http->update();
205 }
206
207 return EXIT_SUCCESS;
208 }
209