-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
206 lines (190 loc) · 8.66 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <iostream>
#include <args.hxx>
#include <InstallEngine.h>
#include <UninstallEngine.h>
#include <DependencyEngine.h>
#include <config.h>
#include <debug.h>
#include "LocalFolderRepository.h"
#include "RepositoryEngine.h"
int main_bvpm_repo(int argc, char** argv) {
args::ArgumentParser parser("BVPM is a simple package manager. It can install, uninstall, and query the version number of packages.", "This is the repo manager. Use it to add, remove, or update packages to a BVPM repository.");
args::HelpFlag help(parser, "help", "Display this help menu", { 'h', "help" });
args::Group flag_group(parser, "You must choose one of these:", args::Group::Validators::Xor);
args::Flag add(flag_group, "add", "Add package file to repo", {'a', "add"});
args::Flag remove(flag_group, "remove", "Remove package from repo", {'r', "remove"});
args::Flag query(flag_group, "query", "Query packages in repo", {'q', "query"});
args::ValueFlag<std::string> repository_arg(parser, "repository", "Path to repository folder", {'r', "repository"}, args::Options::Required);
args::PositionalList<std::string> packages(parser, "packages", "Packages/Package files", args::Options::Required);
try {
parser.ParseCLI(argc, argv);
} catch(args::Help&) {
std::cout << parser;
exit(0);
} catch(args::ParseError& e) {
std::cerr << "Failed parsing arguments: " << e.what() << std::endl;
std::cout << parser;
exit(1);
} catch(args::ValidationError& e) {
std::string error;
if(std::string(e.what()) == "Group validation failed somewhere!") {
// Hacky workaround to give a decent error message
error = "You must pass -a, -r or -q";
} else {
error = e.what();
}
std::cerr << "Failed validating arguments: " << error << std::endl;
std::cout << parser;
exit(1);
}
const std::string& repository = repository_arg.Get();
PRINT_DEBUG("repository path: " << repository << std::endl);
LocalFolderRepository repo("repository", repository);
if(add.Get()) {
for(const std::string& package : packages) {
std::cout << "Adding package file " << package << " to repository" << std::endl;
repo.addPackageFileToRepository(package);
}
} else if(remove.Get()) {
for(const std::string& package : packages) {
std::cout << "Removing package " << package << " from repository" << std::endl;
repo.removePackageFromRepository(package);
}
} else if(query.Get()) {
std::cerr << "TODO" << std::endl;
exit(-1);
}
return 0;
}
int main(int argc, char** argv) {
// If we are running as bvpm-repo, then we call a different main function
if(argc && std::string(argv[0]) == "bvpm-repo") {
return main_bvpm_repo(argc, argv);
}
args::ArgumentParser parser("BVPM is a simple package manager. It can install, uninstall, and query the version number of packages.", "To install a package, do: bvpm -i PACKAGE_FILE");
args::HelpFlag help(parser, "help", "Display this help menu", { 'h', "help" });
args::Group flag_group(parser, "You must choose one of these:", args::Group::Validators::Xor);
args::Flag install(flag_group, "install", "Install packages", {'i', "install"});
args::Flag uninstall(flag_group, "uninstall", "Uninstall packages", {'u', "uninstall"});
args::Flag query(flag_group, "query", "Query package versions", {'q', "query"});
args::Group only_for_query(parser, "Only for -q:", args::Group::Validators::DontCare);
args::Flag query_all(only_for_query, "query-all", "List all packages", {"query-all"}, false);
args::Flag dont_ask_for_permission(parser, "yes", "Skip asking for permission to perform actions", {'y', "yes"});
args::Flag assume_inputs_are_files(parser, "files", "Assume that packages to install point directly to bvp files", {"files"});
args::Flag ignore_dependencies(parser, "ignore-dependencies", "Do not account for dependencies", {"ignore-dependencies"});
args::ValueFlag<std::string> install_root_arg(parser, "install-root", "Root folder to install to", {"install-root"}, "/");
args::ValueFlag<std::string> config_file_arg(parser, "config-file", "Path to BVPM config file", {"config-file"}, "/etc/bvpm/bvpm.cfg");
args::PositionalList<std::string> packages(parser, "packages", "Packages to install");
try {
parser.ParseCLI(argc, argv);
if(packages->empty() && !query_all) {
std::cerr << "Failed parsing arguments: missing packages list!\n";
std::cout << parser;
exit(1);
}
} catch(args::Help&) {
std::cout << parser;
exit(0);
} catch(args::ParseError& e) {
std::cerr << "Failed parsing arguments: " << e.what() << std::endl;
std::cout << parser;
exit(1);
} catch(args::ValidationError& e) {
std::string error;
if(std::string(e.what()) == "Group validation failed somewhere!") {
// Hacky workaround to give a decent error message
error = "You must pass -i, -u or -q";
} else {
error = e.what();
}
std::cerr << "Failed validating arguments: " << error << std::endl;
std::cout << parser;
exit(1);
}
const std::string& install_root = install_root_arg.Get();
const std::string& config_file = config_file_arg.Get();
// Attempt to read config file
// The config file is always read from the install root
ConfigFile config = Config::readConfigFile(config_file);
if(config.values["failed"] == "true") {
std::cout << "failed to read config file " << config_file << std::endl;
exit(-1);
}
// Check arguments
PRINT_DEBUG("install root: " << install_root << std::endl);
if(install) {
InstallEngine installEngine(install_root, config);
if(assume_inputs_are_files.Get()) {
for (const std::string& package: packages) {
if (!installEngine.AddPackageFile(std::string(package))) {
exit(-1);
}
}
} else {
for (const std::string& package: packages) {
if (!installEngine.AddPackage(std::string(package))) {
exit(-1);
}
}
}
if(installEngine.empty()) {
std::cout << "error: no packages selected" << std::endl;
exit(-1);
}
if(!installEngine.VerifyPossible()) {
std::cout << "Failed to resolve dependencies during install stage; are there problems with the repositories? Bailing!" << std::endl;
exit(-1);
}
if(!dont_ask_for_permission) {
if(!installEngine.GetUserPermission()) {
std::cout << "Bailing" << std::endl;
exit(-1);
}
}
if(installEngine.Execute()) {
std::cout << "Operations complete" << std::endl;
}
} else if(uninstall) {
UninstallEngine uninstallEngine(install_root);
for(const auto& package : packages) {
if(!uninstallEngine.AddToList(std::string(package), ignore_dependencies.Get())) {
exit(-1);
}
}
if(uninstallEngine.empty()) {
std::cout << "error: no packages selected" << std::endl;
exit(-1);
}
if(!dont_ask_for_permission) {
if(!uninstallEngine.GetUserPermission()) {
std::cout << "Bailing" << std::endl;
exit(-1);
}
}
uninstallEngine.Execute();
std::cout << "Operations complete" << std::endl;
} else if(query) {
InstallEngine installEngine(install_root, config);
if(query_all) {
// Go through all packages
for (const auto& package: installEngine.dependencyEngine.installed_packages) {
std::cout << package.first << ": " << package.second << std::endl;
}
} else {
// Try to find the package
int num_notfound = 0;
for (const auto& package: packages) {
if (installEngine.dependencyEngine.installed_packages.find(std::string(package)) !=
installEngine.dependencyEngine.installed_packages.end()) {
std::cout << package << ": "
<< installEngine.dependencyEngine.installed_packages[std::string(package)] << std::endl;
} else {
std::cout << "package " << package << " not installed" << std::endl;
num_notfound++;
}
return num_notfound;
}
}
}
return 0;
}