Rewrite depsolver to use a series of passes over all packages.
The big change is that we follow one step of the depedency chain for
each package to resolve in each iteration, and repeat until there are
no more possible moves. In contrast the old depsolver would try to
follow the dependency chain completely for one package at a time.
This new approach is simpler and faster, and at the same time more
roboust. Instead of knowing how one newly installed package may
affect other packages (obsoleting, pulling in new packages etc), the
new algorithm just looks at the total list of requires, provides,
obsoletes and conflicts after installing new packages.
2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 enum option_type type;
37 const char *description;
41 /* A note about all these options: rpm allows options to mean
42 * different things depending on what other options are present on the
43 * command line. For example, if -q or --query is present, -i no
44 * longer means install, but info. The way we handle this is by
45 * setting all the options that may match (ie if -i is given we set
46 * install and info), and then look at the relevent one depending on
47 * what else in on the command line. */
49 static int option_all, option_whatrequires, option_whatprovides;
50 static int option_package;
52 static const struct option query_options[] = {
53 { OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
54 { OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
55 { OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
56 { OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
57 { OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
58 { OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
59 { OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
60 { OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
61 { OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
62 { OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
63 { OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
64 { OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
65 { OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
66 { OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
67 { OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
68 { OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
69 { OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
70 { OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
71 { OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
75 static const struct option verify_options[] = {
76 { OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
77 { OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
78 { OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", NULL },
79 { OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
80 { OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
81 { OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
82 { OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
83 { OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
84 { OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
85 { OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
86 { OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
87 { OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
88 { OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
89 { OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
90 { OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
91 { OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
92 { OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
96 static const struct option ftw_options[] = {
97 { OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
98 { OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
99 { OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
100 { OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
101 { OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
102 { OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
103 { OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
104 { OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
108 static const struct option signature_options[] = {
109 { OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
110 { OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
111 { OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
112 { OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
113 { OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
114 { OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
115 { OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
119 static const struct option database_options[] = {
120 { OPTION_BOOL, "initdb", 0, NULL, "initialize database", NULL },
121 { OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
125 static int option_erase, option_install, option_upgrade;
127 static const struct option install_options[] = {
128 { OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
129 { OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
130 { OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
131 { OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
132 { OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
133 { OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
134 { OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
135 { OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
136 { OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
137 { OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
138 { OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
139 { OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
140 { OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
141 { OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
142 { OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
143 { OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", NULL, },
144 { OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", NULL, },
145 { OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
146 { OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
147 { OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
148 { OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
149 { OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
150 { OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
151 { OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
152 { OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
153 { OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
154 { OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
155 { OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
156 { OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
157 { OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
158 { OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", NULL },
159 { OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
163 static int option_version;
165 static const struct option common_options[] = {
166 { OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
167 { OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
168 { OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
169 { OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
170 { OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
171 { OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
172 { OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", NULL },
173 { OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
174 { OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
175 { OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
176 { OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
177 { OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
181 static int option_conflicts, option_obsoletes, option_requires;
182 static int option_provides, option_info, option_changelog;
184 static const struct option alias_options[] = {
185 { OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
186 { OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
187 { OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
188 { OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
189 { OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
190 { OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
191 { OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
192 { OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
193 { OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
194 { OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
195 { OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
196 { OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
197 { OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
198 { OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
199 { OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
200 { OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
201 { OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
202 { OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
203 { OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
204 { OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
205 { OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
206 { OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
207 { OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
208 { OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
209 { OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
210 { OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
214 static int option_help, option_usage;
216 static const struct option help_options[] = {
217 { OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
218 { OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
222 static int option_query, option_verify;
224 static const struct option rpm_options[] = {
225 { OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
226 { OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
227 { OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
228 { OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
229 { OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
230 { OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
231 { OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
232 { OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
233 { OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
234 { OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
235 { OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
239 static const char system_repo_filename[] = "system.repo";
240 static const char *repo_filename = system_repo_filename;
242 static struct razor_property *
243 add_property_packages(struct razor_set *set,
244 struct razor_package_query *query,
245 const char *ref_name,
246 const char *ref_version,
247 enum razor_property_type ref_type)
249 struct razor_property *property;
250 struct razor_property_iterator *pi;
251 struct razor_package_iterator *pkgi;
252 const char *name, *version;
253 enum razor_property_type type;
254 enum razor_version_relation relation;
256 pi = razor_property_iterator_create(set, NULL);
257 while (razor_property_iterator_next(pi, &property, &name,
258 &relation, &version, &type)) {
259 if (strcmp(ref_name, name) != 0)
261 if (ref_version && relation == RAZOR_VERSION_EQUAL &&
262 strcmp(ref_version, version) != 0)
264 if (ref_type != type)
267 pkgi = razor_package_iterator_create_for_property(set,
269 razor_package_query_add_iterator(query, pkgi);
270 razor_package_iterator_destroy(pkgi);
272 razor_property_iterator_destroy(pi);
278 strcmpp(const void *p1, const void *p2)
280 return strcmp(*(char * const *) p1, *(char * const *) p2);
284 add_command_line_packages(struct razor_set *set,
285 struct razor_package_query *query,
286 int argc, const char **argv)
288 struct razor_package *package;
289 struct razor_package_iterator *pi;
290 const char *name, *version, *arch;
293 qsort(argv, argc, sizeof(*argv), strcmpp);
296 pi = razor_package_iterator_create(set);
298 while (razor_package_iterator_next(pi, &package,
299 &name, &version, &arch)) {
300 while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
301 printf("package %s is not installed\n", argv[i]);
306 razor_package_query_add_package(query, package);
311 razor_package_iterator_destroy(pi);
314 static struct razor_package_iterator *
315 get_query_packages(struct razor_set *set, int argc, const char *argv[])
317 struct razor_package_query *query;
318 struct razor_package_iterator *pi;
321 if (option_all + option_whatprovides + option_whatrequires > 1) {
322 printf("only one type of query/verify "
323 "may be performed at a time\n");
327 query = razor_package_query_create(set);
330 pi = razor_package_iterator_create(set);
331 razor_package_query_add_iterator(query, pi);
332 razor_package_iterator_destroy(pi);
333 } else if (option_whatrequires) {
334 for (i = 0; i < argc; i++)
335 add_property_packages(set, query,
337 RAZOR_PROPERTY_REQUIRES);
338 } else if (option_whatprovides) {
339 for (i = 0; i < argc; i++)
340 add_property_packages(set, query,
342 RAZOR_PROPERTY_PROVIDES);
343 } else if (argc > 0) {
344 add_command_line_packages(set, query, argc, argv);
346 printf("no arguments given for query/verify\n");
350 return razor_package_query_finish(query);
353 static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
356 print_package_properties(struct razor_set *set,
357 struct razor_package *package,
358 enum razor_property_type ref_type)
360 struct razor_property *property;
361 struct razor_property_iterator *pi;
362 const char *name, *version;
363 enum razor_property_type type;
364 enum razor_version_relation relation;
366 pi = razor_property_iterator_create(set, package);
367 while (razor_property_iterator_next(pi, &property,
368 &name, &relation, &version,
370 if (type != ref_type)
372 if (version[0] == '\0')
373 printf("%s\n", name);
375 printf("%s %s %s\n", name,
376 relation_string[relation], version);
378 razor_property_iterator_destroy(pi);
382 print_package_info(struct razor_set *set, struct razor_package *package)
384 printf("FIXME: Package info not tracked.\n");
388 print_package_changelog(struct razor_set *set, struct razor_package *package)
390 printf("FIXME: Package changelog not tracked.\n");
393 static struct razor_set *
394 create_set_from_command_line(int argc, const char *argv[])
396 struct razor_importer *importer;
397 struct razor_rpm *rpm;
400 importer = razor_importer_new();
402 for (i = 0; i < argc; i++) {
403 rpm = razor_rpm_open(argv[i]);
406 if (razor_importer_add_rpm(importer, rpm))
407 printf("couldn't import %s\n", argv[i]);
409 razor_rpm_close(rpm);
412 return razor_importer_finish(importer);
416 command_query(int argc, const char *argv[])
418 struct razor_set *set;
419 struct razor_package_iterator *pi;
420 struct razor_package *package;
421 const char *name, *version, *arch;
423 if (option_package) {
424 set = create_set_from_command_line(argc, argv);
428 set = razor_set_open(repo_filename);
431 pi = get_query_packages(set, argc, argv);
433 while (razor_package_iterator_next(pi, &package,
434 &name, &version, &arch)) {
435 if (option_conflicts)
436 print_package_properties(set, package,
437 RAZOR_PROPERTY_CONFLICTS);
438 if (option_obsoletes)
439 print_package_properties(set, package,
440 RAZOR_PROPERTY_OBSOLETES);
442 print_package_properties(set, package,
443 RAZOR_PROPERTY_REQUIRES);
445 print_package_properties(set, package,
446 RAZOR_PROPERTY_PROVIDES);
448 print_package_info(set, package);
449 if (option_changelog)
450 print_package_changelog(set, package);
452 if (option_conflicts + option_obsoletes +
453 option_requires + option_provides +
454 option_info + option_changelog == 0)
455 printf("%s-%s.%s\n", name, version, arch);
458 razor_package_iterator_destroy(pi);
460 razor_set_destroy(set);
466 command_verify(int argc, const char *argv[])
468 struct razor_set *set;
469 struct razor_package_iterator *pi;
470 struct razor_package *package;
471 const char *name, *version, *arch;
473 if (option_package) {
474 set = create_set_from_command_line(argc, argv);
478 set = razor_set_open(repo_filename);
481 pi = get_query_packages(set, argc, argv);
483 while (razor_package_iterator_next(pi, &package,
484 &name, &version, &arch)) {
485 printf("verify %s-%s.%s - not implemented\n",
486 name, version, arch);
489 razor_package_iterator_destroy(pi);
493 command_erase(int argc, const char *argv[])
495 struct razor_set *set, *next;
496 struct razor_transaction *trans;
497 struct razor_package_query *query;
498 struct razor_package_iterator *pi;
499 struct razor_package *package;
500 const char *name, *version, *arch;
503 printf("no packages given for erase\n");
507 set = razor_set_open(repo_filename);
509 trans = razor_transaction_create(set, NULL);
511 query = razor_package_query_create(set);
512 add_command_line_packages(set, query, argc, argv);
514 pi = razor_package_query_finish(query);
515 while (razor_package_iterator_next(pi, &package,
516 &name, &version, &arch))
517 razor_transaction_remove_package(trans, package);
518 razor_package_iterator_destroy(pi);
520 next = razor_transaction_finish(trans);
521 razor_set_destroy(set);
523 razor_set_destroy(next);
527 command_install(int argc, const char *argv[])
529 struct razor_set *set, *upstream, *next;
530 struct razor_transaction *trans;
531 struct razor_package_iterator *pi;
532 struct razor_package *package;
533 const char *name, *version, *arch;
536 printf("no packages given for install\n");
540 set = razor_set_open(repo_filename);
541 upstream = create_set_from_command_line(argc, argv);
543 trans = razor_transaction_create(set, upstream);
545 pi = razor_package_iterator_create(upstream);
546 while (razor_package_iterator_next(pi, &package,
547 &name, &version, &arch))
548 razor_transaction_install_package(trans, package);
549 razor_package_iterator_destroy(pi);
551 next = razor_transaction_finish(trans);
552 razor_set_destroy(set);
553 razor_set_destroy(upstream);
555 razor_set_destroy(next);
559 command_update(int argc, const char *argv[])
562 printf("no packages given for update\n");
566 printf("command update - not implemented\n");
570 for_each_option(const struct option *options,
571 const char *name, char short_name,
572 void (*fn)(const struct option *o,
573 const char *name, char short_name,
574 void *data), void *data)
578 for (i = 0; options[i].type != OPTION_LAST; i++) {
579 switch (options[i].type) {
581 count += for_each_option(options[i].data,
582 name, short_name, fn, data);
587 if (name && strcmp(options[i].name, name) == 0) {
588 fn(&options[i], name, 0, data);
594 short_name == options[i].short_name) {
595 fn(&options[i], NULL, short_name, data);
610 handle_option(const struct option *o,
611 const char *name, char short_name, void *data)
613 if (o->data == NULL) {
615 printf("option --%s not supported\n", name);
617 printf("option -%c not supported\n", short_name);
623 *(int *) o->data = 1;
627 *(const char **) o->data = name + strlen(o->name) + 1;
632 /* Shouldn't happen. */
638 parse_options(const struct option *options, int argc, const char **argv)
642 for (i = 1, j = 0; i < argc; i++) {
643 if (argv[i][0] != '-') {
648 if (argv[i][1] == '-') {
649 if (for_each_option(options, &argv[i][2], 0,
650 handle_option, NULL) == 0) {
651 printf("unknown option: %s\n", argv[i]);
657 for (k = 1; argv[i][k]; k++) {
658 if (for_each_option(options, NULL, argv[i][k],
659 handle_option, NULL) == 0) {
660 printf("unknown option: -%c\n", argv[i][k]);
670 print_options_help(const struct option *options)
674 for (i = 0; options[i].type != OPTION_LAST; i++) {
675 switch (options[i].type) {
677 printf("%s\n", options[i].description);
678 print_options_help(options[i].data);
685 if (options[i].short_name)
686 printf("-%c", options[i].short_name);
687 if (options[i].short_name && options[i].name)
690 printf("--%s", options[i].name);
691 if (options[i].arg_name)
692 printf("=%s", options[i].arg_name);
693 if (options[i].description)
694 printf("\t\t%s", options[i].description);
705 print_options_usage(const struct option *options)
709 for (i = 0; options[i].type != OPTION_LAST; i++) {
710 switch (options[i].type) {
712 print_options_usage(options[i].data);
717 if (options[i].short_name)
718 printf("-%c", options[i].short_name);
719 if (options[i].short_name && options[i].name)
722 printf("--%s", options[i].name);
728 if (options[i].short_name)
729 printf("-%c", options[i].short_name);
730 if (options[i].short_name && options[i].name)
733 printf("--%s", options[i].name);
734 if (options[i].arg_name)
735 printf("=%s", options[i].arg_name);
749 main(int argc, const char *argv[])
751 argc = parse_options(rpm_options, argc, argv);
753 if (option_version) {
754 printf("razor rpm version hoopla.\n");
759 printf("Usage: rpm [OPTION...]\n");
760 print_options_help(rpm_options);
765 printf("Usage: rpm [OPTION...]\n");
766 print_options_usage(rpm_options);
772 command_verify(argc, argv);
773 } else if (option_query) {
774 command_query(argc, argv);
775 } else if (option_install) {
776 command_install(argc, argv);
777 } else if (option_upgrade) {
778 command_update(argc, argv);
779 } else if (option_erase) {
780 command_erase(argc, argv);
782 print_options_usage(rpm_options);