Introduce install/remove iterators.
These iterator constructors lets you pass in two sets and creates
an iterator for the packages to remove or the packages to install.
The iterators will step through the packages in a sequence that respects
the pre, post, preun and postun modifiers.
Right now, the install order isn't actually implemented, this patch just
implements the API changes and updates the applications.
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.
29 #include <curl/curl.h>
34 static const char system_repo_filename[] = "system.repo";
35 static const char next_repo_filename[] = "system-next.repo";
36 static const char rawhide_repo_filename[] = "rawhide.repo";
37 static const char updated_repo_filename[] = "system-updated.repo";
38 static const char install_root[] = "install";
39 static const char *repo_filename = system_repo_filename;
40 static const char *yum_url;
43 command_list(int argc, const char *argv[])
45 struct razor_set *set;
46 struct razor_package_iterator *pi;
47 struct razor_package *package;
48 const char *pattern, *name, *version, *arch;
49 int only_names = 0, i = 0;
51 if (i < argc && strcmp(argv[i], "--only-names") == 0) {
57 set = razor_set_open(repo_filename);
58 pi = razor_package_iterator_create(set);
59 while (razor_package_iterator_next(pi, &package,
60 &name, &version, &arch)) {
61 if (pattern && fnmatch(pattern, name, 0) != 0)
67 printf("%s-%s.%s\n", name, version, arch);
69 razor_package_iterator_destroy(pi);
70 razor_set_destroy(set);
76 list_properties(const char *package_name, uint32_t type)
78 struct razor_set *set;
79 struct razor_property *property;
80 struct razor_package *package;
81 struct razor_property_iterator *pi;
82 const char *name, *version;
85 set = razor_set_open(repo_filename);
87 package = razor_set_get_package(set, package_name);
91 pi = razor_property_iterator_create(set, package);
92 while (razor_property_iterator_next(pi, &property,
93 &name, &flags, &version)) {
94 if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
97 if (version[0] != '\0')
99 razor_property_relation_to_string(property),
102 if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
104 if (flags & RAZOR_PROPERTY_PRE)
106 if (flags & RAZOR_PROPERTY_POST)
108 if (flags & RAZOR_PROPERTY_PREUN)
110 if (flags & RAZOR_PROPERTY_POSTUN)
116 razor_property_iterator_destroy(pi);
118 razor_set_destroy(set);
124 command_list_requires(int argc, const char *argv[])
126 return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
130 command_list_provides(int argc, const char *argv[])
132 return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
136 command_list_obsoletes(int argc, const char *argv[])
138 return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
142 command_list_conflicts(int argc, const char *argv[])
144 return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
148 command_list_files(int argc, const char *argv[])
150 struct razor_set *set;
152 set = razor_set_open(repo_filename);
155 razor_set_list_files(set, argv[0]);
156 razor_set_destroy(set);
162 command_list_file_packages(int argc, const char *argv[])
164 struct razor_set *set;
165 struct razor_package_iterator *pi;
166 struct razor_package *package;
167 const char *name, *version, *arch;
169 set = razor_set_open(repo_filename);
173 pi = razor_package_iterator_create_for_file(set, argv[0]);
174 while (razor_package_iterator_next(pi, &package,
175 &name, &version, &arch))
176 printf("%s-%s\n", name, version);
177 razor_package_iterator_destroy(pi);
179 razor_set_destroy(set);
185 command_list_package_files(int argc, const char *argv[])
187 struct razor_set *set;
189 set = razor_set_open(repo_filename);
192 razor_set_list_package_files(set, argv[0]);
193 razor_set_destroy(set);
199 list_packages_for_property(struct razor_set *set,
200 struct razor_property *property)
202 struct razor_package_iterator *pi;
203 struct razor_package *package;
204 const char *name, *version, *arch;
206 pi = razor_package_iterator_create_for_property(set, property);
207 while (razor_package_iterator_next(pi, &package,
208 &name, &version, &arch))
209 printf("%s-%s.%s\n", name, version, arch);
210 razor_package_iterator_destroy(pi);
214 list_property_packages(const char *ref_name,
215 const char *ref_version,
218 struct razor_set *set;
219 struct razor_property *property;
220 struct razor_property_iterator *pi;
221 const char *name, *version;
224 if (ref_name == NULL)
227 set = razor_set_open(repo_filename);
231 pi = razor_property_iterator_create(set, NULL);
232 while (razor_property_iterator_next(pi, &property,
233 &name, &flags, &version)) {
234 if (strcmp(ref_name, name) != 0)
237 (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
238 strcmp(ref_version, version) != 0)
240 if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
243 list_packages_for_property(set, property);
245 razor_property_iterator_destroy(pi);
251 command_what_requires(int argc, const char *argv[])
253 return list_property_packages(argv[0], argv[1],
254 RAZOR_PROPERTY_REQUIRES);
258 command_what_provides(int argc, const char *argv[])
260 return list_property_packages(argv[0], argv[1],
261 RAZOR_PROPERTY_PROVIDES);
265 show_progress(void *clientp,
266 double dltotal, double dlnow, double ultotal, double ulnow)
268 const char *file = clientp;
270 if (!dlnow < dltotal)
271 fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
272 file, (int) dlnow / 1024, (int) dltotal / 1024);
278 download_if_missing(const char *url, const char *file)
287 curl = curl_easy_init();
291 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
292 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
293 curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
294 curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
296 if (stat(file, &buf) < 0) {
297 fp = fopen(file, "w");
300 "failed to open %s for writing\n", file);
303 curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
304 curl_easy_setopt(curl, CURLOPT_URL, url);
305 res = curl_easy_perform(curl);
307 if (res != CURLE_OK) {
308 fprintf(stderr, "curl error: %s\n", error);
312 res = curl_easy_getinfo(curl,
313 CURLINFO_RESPONSE_CODE, &response);
314 if (res != CURLE_OK) {
315 fprintf(stderr, "curl error: %s\n", error);
319 if (response != 200) {
320 fprintf(stderr, " - failed %ld\n", response);
324 fprintf(stderr, "\n");
327 curl_easy_cleanup(curl);
332 #define YUM_URL "http://download.fedora.redhat.com" \
333 "/pub/fedora/linux/development/i386/os"
336 command_import_yum(int argc, const char *argv[])
338 struct razor_set *set;
341 printf("downloading from %s.\n", yum_url);
342 snprintf(buffer, sizeof buffer,
343 "%s/repodata/primary.xml.gz", yum_url);
344 if (download_if_missing(buffer, "primary.xml.gz") < 0)
346 snprintf(buffer, sizeof buffer,
347 "%s/repodata/filelists.xml.gz", yum_url);
348 if (download_if_missing(buffer, "filelists.xml.gz") < 0)
351 set = razor_set_create_from_yum();
354 razor_set_write(set, rawhide_repo_filename);
355 razor_set_destroy(set);
356 printf("wrote %s\n", rawhide_repo_filename);
362 command_import_rpmdb(int argc, const char *argv[])
364 struct razor_set *set;
366 set = razor_set_create_from_rpmdb();
369 razor_set_write(set, repo_filename);
370 razor_set_destroy(set);
371 printf("wrote %s\n", repo_filename);
377 mark_packages_for_update(struct razor_transaction *trans,
378 struct razor_set *set, const char *pattern)
380 struct razor_package_iterator *pi;
381 struct razor_package *package;
382 const char *name, *version, *arch;
385 pi = razor_package_iterator_create(set);
386 while (razor_package_iterator_next(pi, &package,
387 &name, &version, &arch)) {
388 if (pattern && fnmatch(pattern, name, 0) == 0) {
389 razor_transaction_update_package(trans, package);
393 razor_package_iterator_destroy(pi);
399 mark_packages_for_removal(struct razor_transaction *trans,
400 struct razor_set *set, const char *pattern)
402 struct razor_package_iterator *pi;
403 struct razor_package *package;
404 const char *name, *version, *arch;
407 pi = razor_package_iterator_create(set);
408 while (razor_package_iterator_next(pi, &package,
409 &name, &version, &arch)) {
410 if (pattern && fnmatch(pattern, name, 0) == 0) {
411 razor_transaction_remove_package(trans, package);
415 razor_package_iterator_destroy(pi);
421 command_update(int argc, const char *argv[])
423 struct razor_set *set, *upstream;
424 struct razor_transaction *trans;
427 set = razor_set_open(repo_filename);
428 upstream = razor_set_open(rawhide_repo_filename);
429 if (set == NULL || upstream == NULL)
432 trans = razor_transaction_create(set, upstream);
434 razor_transaction_update_all(trans);
435 for (i = 0; i < argc; i++) {
436 if (mark_packages_for_update(trans, set, argv[i]) == 0) {
437 fprintf(stderr, "no match for %s\n", argv[i]);
442 razor_transaction_resolve(trans);
443 errors = razor_transaction_describe(trans);
445 fprintf(stderr, "unresolved dependencies\n");
449 set = razor_transaction_finish(trans);
450 razor_set_write(set, updated_repo_filename);
451 razor_set_destroy(set);
452 razor_set_destroy(upstream);
453 printf("wrote system-updated.repo\n");
459 command_remove(int argc, const char *argv[])
461 struct razor_set *set, *upstream;
462 struct razor_transaction *trans;
465 set = razor_set_open(repo_filename);
469 upstream = razor_set_create();
470 trans = razor_transaction_create(set, upstream);
471 for (i = 0; i < argc; i++) {
472 if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
473 fprintf(stderr, "no match for %s\n", argv[i]);
478 errors = razor_transaction_resolve(trans);
482 set = razor_transaction_finish(trans);
483 razor_set_write(set, updated_repo_filename);
484 razor_set_destroy(set);
485 razor_set_destroy(upstream);
486 printf("wrote system-updated.repo\n");
492 print_diff(enum razor_diff_action action,
493 struct razor_package *package,
499 if (action == RAZOR_DIFF_ACTION_ADD)
500 printf("install %s-%s.%s\n", name, version, arch);
501 if (action == RAZOR_DIFF_ACTION_REMOVE)
502 printf("remove %s-%s.%s\n", name, version, arch);
506 command_diff(int argc, const char *argv[])
508 struct razor_set *set, *updated;
510 set = razor_set_open(repo_filename);
511 updated = razor_set_open(updated_repo_filename);
512 if (set == NULL || updated == NULL)
515 razor_set_diff(set, updated, print_diff, NULL);
517 razor_set_destroy(set);
518 razor_set_destroy(updated);
524 command_import_rpms(int argc, const char *argv[])
528 struct razor_importer *importer;
529 struct razor_set *set;
530 struct razor_rpm *rpm;
533 const char *dirname = argv[0];
535 if (dirname == NULL) {
536 fprintf(stderr, "usage: razor import-rpms DIR\n");
540 dir = opendir(dirname);
542 fprintf(stderr, "couldn't read dir %s\n", dirname);
546 importer = razor_importer_create();
548 while (de = readdir(dir), de != NULL) {
549 len = strlen(de->d_name);
550 if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
552 snprintf(filename, sizeof filename,
553 "%s/%s", dirname, de->d_name);
554 rpm = razor_rpm_open(filename);
557 "failed to open rpm \"%s\"\n", filename);
560 if (razor_importer_add_rpm(importer, rpm)) {
561 fprintf(stderr, "couldn't import %s\n", filename);
564 razor_rpm_close(rpm);
568 razor_importer_destroy(importer);
572 set = razor_importer_finish(importer);
574 razor_set_write(set, repo_filename);
575 razor_set_destroy(set);
576 printf("wrote %s\n", repo_filename);
582 rpm_filename(const char *name, const char *version, const char *arch)
584 static char file[PATH_MAX];
588 v = strchr(version, ':');
594 snprintf(file, sizeof file, "%s-%s.%s.rpm", name, v, arch);
600 download_packages(struct razor_set *system, struct razor_set *next)
602 struct razor_package_iterator *pi;
603 struct razor_package *package;
604 const char *name, *version, *arch;
605 char file[PATH_MAX], url[256];
608 pi = razor_set_create_install_iterator(system, next);
610 while (razor_package_iterator_next(pi, &package,
611 &name, &version, &arch)) {
612 snprintf(url, sizeof url,
614 yum_url, rpm_filename(name, version, arch));
615 snprintf(file, sizeof file,
616 "rpms/%s", rpm_filename(name, version, arch));
617 if (download_if_missing(url, file) < 0)
620 razor_package_iterator_destroy(pi);
623 fprintf(stderr, "failed to download %d packages\n", errors);
631 install_packages(struct razor_set *system, struct razor_set *next)
633 struct razor_package_iterator *pi;
634 struct razor_package *package;
635 struct razor_rpm *rpm;
636 const char *name, *version, *arch;
639 pi = razor_set_create_install_iterator(system, next);
640 while (razor_package_iterator_next(pi, &package,
641 &name, &version, &arch)) {
642 printf("install %s-%s\n", name, version);
644 snprintf(file, sizeof file,
645 "rpms/%s", rpm_filename(name, version, arch));
646 rpm = razor_rpm_open(file);
648 fprintf(stderr, "failed to open rpm %s\n", file);
651 if (razor_rpm_install(rpm, install_root) < 0) {
653 "failed to install rpm %s\n", file);
656 razor_rpm_close(rpm);
658 razor_package_iterator_destroy(pi);
664 command_install(int argc, const char *argv[])
666 struct razor_root *root;
667 struct razor_set *system, *upstream, *next;
668 struct razor_transaction *trans;
669 int i = 0, errors, dependencies = 1;
671 if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
676 root = razor_root_open(install_root);
677 system = razor_root_get_system_set(root);
678 upstream = razor_set_open(rawhide_repo_filename);
679 trans = razor_transaction_create(system, upstream);
681 for (; i < argc; i++) {
682 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
683 fprintf(stderr, "no package matched %s\n", argv[i]);
684 razor_root_close(root);
690 razor_transaction_resolve(trans);
691 if (razor_transaction_describe(trans) > 0) {
692 razor_root_close(root);
697 next = razor_transaction_finish(trans);
699 razor_root_update(root, next);
701 if (mkdir("rpms", 0777) && errno != EEXIST) {
702 fprintf(stderr, "failed to create rpms directory.\n");
703 razor_root_close(root);
707 if (download_packages(system, next) < 0) {
708 razor_root_close(root);
712 install_packages(system, next);
714 razor_set_destroy(next);
715 razor_set_destroy(upstream);
717 return razor_root_commit(root);
721 command_init(int argc, const char *argv[])
723 return razor_root_create(install_root);
727 command_download(int argc, const char *argv[])
729 struct razor_set *set;
730 struct razor_package_iterator *pi;
731 struct razor_package *package;
732 const char *pattern = argv[0], *name, *version, *arch;
733 char url[256], file[256];
736 if (mkdir("rpms", 0777) && errno != EEXIST) {
737 fprintf(stderr, "failed to create rpms directory.\n");
741 set = razor_set_open(rawhide_repo_filename);
742 pi = razor_package_iterator_create(set);
743 while (razor_package_iterator_next(pi, &package,
744 &name, &version, &arch)) {
745 if (pattern && fnmatch(pattern, name, 0) != 0)
749 snprintf(url, sizeof url,
750 "%s/Packages/%s-%s.%s.rpm",
751 yum_url, name, version, arch);
752 snprintf(file, sizeof file,
753 "rpms/%s-%s.%s.rpm", name, version, arch);
754 download_if_missing(url, file);
756 razor_package_iterator_destroy(pi);
757 razor_set_destroy(set);
760 fprintf(stderr, "no packages matched \"%s\"\n", pattern);
761 else if (matches == 1)
762 fprintf(stderr, "downloaded 1 package\n");
764 fprintf(stderr, "downloaded %d packages\n", matches);
771 const char *description;
772 int (*func)(int argc, const char *argv[]);
773 } razor_commands[] = {
774 { "list", "list all packages", command_list },
775 { "list-requires", "list all requires for the given package", command_list_requires },
776 { "list-provides", "list all provides for the given package", command_list_provides },
777 { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
778 { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
779 { "list-files", "list files for package set", command_list_files },
780 { "list-file-packages", "list packages owning file", command_list_file_packages },
781 { "list-package-files", "list files in package", command_list_package_files },
782 { "what-requires", "list the packages that have the given requires", command_what_requires },
783 { "what-provides", "list the packages that have the given provides", command_what_provides },
784 { "import-yum", "import yum metadata files", command_import_yum },
785 { "import-rpmdb", "import the system rpm database", command_import_rpmdb },
786 { "import-rpms", "import rpms from the given directory", command_import_rpms },
787 { "update", "update all or specified packages", command_update },
788 { "remove", "remove specified packages", command_remove },
789 { "diff", "show diff between two package sets", command_diff },
790 { "install", "install rpm", command_install },
791 { "init", "init razor root", command_init },
792 { "download", "download packages", command_download }
801 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
803 razor_commands[i].name, razor_commands[i].description);
809 main(int argc, const char *argv[])
814 repo = getenv("RAZOR_REPO");
816 repo_filename = repo;
818 yum_url = getenv("YUM_URL");
825 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
826 if (strcmp(razor_commands[i].name, argv[1]) == 0)
827 return razor_commands[i].func(argc - 2, argv + 2);