From 5a120e346e1be953ef54f277f93a38c7ba446f33 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sun, 22 Jul 2012 10:48:29 +0200 Subject: [PATCH] xbps-repo: new 'remove-obsoletes' target to remove obsolete pkgs in a local repo. --- NEWS | 4 ++ bin/xbps-repo/Makefile | 3 +- bin/xbps-repo/common.c | 70 +++++++++++++++++++ bin/xbps-repo/defs.h | 8 ++- bin/xbps-repo/index.c | 103 ++-------------------------- bin/xbps-repo/main.c | 10 +++ bin/xbps-repo/remove-obsoletes.c | 111 +++++++++++++++++++++++++++++++ bin/xbps-repo/xbps-repo.8 | 7 +- 8 files changed, 216 insertions(+), 100 deletions(-) create mode 100644 bin/xbps-repo/common.c create mode 100644 bin/xbps-repo/remove-obsoletes.c diff --git a/NEWS b/NEWS index d41e918b..1cf408ee 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ xbps-0.16.6 (???): + * xbps-repo(8): a new target has been added: 'remove-obsoletes'. This removes + obsolete packages found in a local repository; obsoletes are packages not + registered in repository's index. + * configure: fixes for Ubuntu, which uses ld(1) --as-needed by default and some function tests were failiing due to this. diff --git a/bin/xbps-repo/Makefile b/bin/xbps-repo/Makefile index 0948437b..6c2106d5 100644 --- a/bin/xbps-repo/Makefile +++ b/bin/xbps-repo/Makefile @@ -3,7 +3,8 @@ TOPDIR = ../.. BIN = xbps-repo OBJS = main.o index.o show.o find-files.o list.o -OBJS += index-files.o index-lock.o clean.o +OBJS += index-files.o index-lock.o clean.o common.o +OBJS += remove-obsoletes.o OBJS += ../xbps-bin/fetch_cb.o ../xbps-bin/util.o OBJS += ../xbps-bin/state_cb.o ../xbps-bin/list.o MAN = $(BIN).8 diff --git a/bin/xbps-repo/common.c b/bin/xbps-repo/common.c new file mode 100644 index 00000000..2efd7371 --- /dev/null +++ b/bin/xbps-repo/common.c @@ -0,0 +1,70 @@ +/*- + * Copyright (c) 2012 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "defs.h" + +int +repo_remove_pkg(const char *repodir, const char *arch, const char *file) +{ + char *filepath; + int rv; + + /* Remove real binpkg */ + filepath = xbps_xasprintf("%s/%s/%s", repodir, arch, file); + assert(filepath); + if (remove(filepath) == -1) { + rv = errno; + xbps_error_printf("failed to remove old binpkg `%s': %s\n", + file, strerror(rv)); + free(filepath); + return rv; + } + free(filepath); + + /* Remove symlink to binpkg */ + filepath = xbps_xasprintf("%s/%s", repodir, file); + assert(filepath); + if (remove(filepath) == -1) { + rv = errno; + xbps_error_printf("failed to remove old binpkg `%s': %s\n", + file, strerror(rv)); + free(filepath); + return rv; + } + free(filepath); + + return 0; +} diff --git a/bin/xbps-repo/defs.h b/bin/xbps-repo/defs.h index a78d2316..59cc1fec 100644 --- a/bin/xbps-repo/defs.h +++ b/bin/xbps-repo/defs.h @@ -34,6 +34,9 @@ struct repo_search_data { size_t pkgver_len; }; +/* From common.c */ +int repo_remove_pkg(const char *, const char *, const char *); + /* From index.c */ int repo_index_add(struct xbps_handle *, int, char **); int repo_index_clean(struct xbps_handle *, const char *); @@ -42,7 +45,7 @@ int repo_index_clean(struct xbps_handle *, const char *); int repo_index_files_add(struct xbps_handle *, int, char **); int repo_index_files_clean(struct xbps_handle *, const char *); -/* From index-common.c */ +/* From index-lock.c */ int acquire_repo_lock(const char *, char **); void release_repo_lock(char **, int); @@ -63,6 +66,9 @@ int repo_search_pkgs_cb(struct xbps_handle *, void *, bool *); +/* From remove-obsoletes.c */ +int repo_remove_obsoletes(struct xbps_handle *, const char *); + /* From show.c */ int show_pkg_info_from_repolist(struct xbps_handle *, const char *, diff --git a/bin/xbps-repo/index.c b/bin/xbps-repo/index.c index 5a919437..18e8aa18 100644 --- a/bin/xbps-repo/index.c +++ b/bin/xbps-repo/index.c @@ -36,95 +36,6 @@ #include #include "defs.h" -static int -remove_oldpkg(const char *repodir, const char *arch, const char *file) -{ - char *filepath; - int rv; - - /* Remove real binpkg */ - filepath = xbps_xasprintf("%s/%s/%s", repodir, arch, file); - assert(filepath); - if (remove(filepath) == -1) { - rv = errno; - xbps_error_printf("failed to remove old binpkg `%s': %s\n", - file, strerror(rv)); - free(filepath); - return rv; - } - free(filepath); - - /* Remove symlink to binpkg */ - filepath = xbps_xasprintf("%s/%s", repodir, file); - assert(filepath); - if (remove(filepath) == -1) { - rv = errno; - xbps_error_printf("failed to remove old binpkg `%s': %s\n", - file, strerror(rv)); - free(filepath); - return rv; - } - free(filepath); - - return 0; -} - -static int -remove_obsolete_binpkgs(struct xbps_handle *xhp, - prop_array_t idx, - const char *repodir) -{ - prop_dictionary_t pkgd; - DIR *dirp; - struct dirent *dp; - const char *pkgver, *arch; - int rv = 0; - - if (chdir(repodir) == -1) { - fprintf(stderr, "cannot chdir to %s: %s\n", - repodir, strerror(errno)); - return errno; - } - if ((dirp = opendir(repodir)) == NULL) { - fprintf(stderr, "failed to open %s: %s\n", - repodir, strerror(errno)); - return errno; - } - while ((dp = readdir(dirp))) { - if (strcmp(dp->d_name, "..") == 0) - continue; - if (!strstr(dp->d_name, ".xbps")) - continue; - - pkgd = xbps_dictionary_metadata_plist_by_url(dp->d_name, - "./props.plist"); - if (pkgd == NULL) { - fprintf(stderr, "failed to read metadata for `%s'," - " skipping!\n", dp->d_name); - continue; - } - prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); - prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); - /* - * If binpkg is not registered in index, remove binpkg. - */ - if (!xbps_find_pkg_in_array_by_pkgver(xhp, idx, pkgver, arch)) { - rv = remove_oldpkg(repodir, arch, dp->d_name); - if (rv != 0) { - fprintf(stderr, "index: failed to remove " - "package `%s': %s\n", dp->d_name, - strerror(rv)); - prop_object_release(pkgd); - break; - } - printf("Removed obsolete package `%s'.\n", dp->d_name); - } - prop_object_release(pkgd); - } - (void)closedir(dirp); - return rv; -} - /* * Removes stalled pkg entries in repository's index.plist file, if any * binary package cannot be read (unavailable, not enough perms, etc). @@ -187,13 +98,10 @@ again: } free(binpkg); } - rv = remove_obsolete_binpkgs(xhp, array, repodir); - if (rv != 0) - goto out; - - if (flush && !prop_array_externalize_to_zfile(array, plist)) + if (flush && !prop_array_externalize_to_zfile(array, plist)) { rv = errno; - + goto out; + } printf("index: %u packages registered.\n", prop_array_count(array)); out: free(plist); @@ -316,7 +224,8 @@ repo_index_add(struct xbps_handle *xhp, int argc, char **argv) buf = xbps_xasprintf("`%s' (%s)", oldpkgver, oldarch); assert(buf); - rv = remove_oldpkg(repodir, oldarch, oldfilen); + rv = repo_remove_pkg(repodir, + oldarch, oldfilen); if (rv != 0) { prop_object_release(newpkgd); free(tmpfilen); @@ -337,7 +246,7 @@ repo_index_add(struct xbps_handle *xhp, int argc, char **argv) assert(buf); buf2 = strdup(oldpkgver); assert(buf2); - rv = remove_oldpkg(repodir, oldarch, oldfilen); + rv = repo_remove_pkg(repodir, oldarch, oldfilen); if (rv != 0) { free(buf); free(buf2); diff --git a/bin/xbps-repo/main.c b/bin/xbps-repo/main.c index a7ebba21..ea8283f8 100644 --- a/bin/xbps-repo/main.c +++ b/bin/xbps-repo/main.c @@ -66,6 +66,9 @@ usage(bool fail) " pkg-list [repo]\n" " Print packages in repository matching `repo' URI.\n" " If `repo' not specified, all registered repositories will be used.\n" + " remove-obsoletes \n" + " Removes obsolete packages (not registered in index any longer) from\n" + " local repository \"\".\n" " search [patterns]\n" " Search for packages in repositories matching the patterns.\n" " show \n" @@ -263,6 +266,13 @@ main(int argc, char **argv) xbps_error_printf("xbps-repo: no repositories " "currently registered!\n"); } + } else if (strcasecmp(argv[0], "remove-obsoletes") == 0) { + if (argc < 2) + usage(true); + + if ((rv = repo_remove_obsoletes(&xh, argv[1])) != 0) + goto out; + } else if (strcasecmp(argv[0], "index-add") == 0) { /* Registers a binary package into the repository's index. */ if (argc < 2) diff --git a/bin/xbps-repo/remove-obsoletes.c b/bin/xbps-repo/remove-obsoletes.c new file mode 100644 index 00000000..6ab7e2cd --- /dev/null +++ b/bin/xbps-repo/remove-obsoletes.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2012 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "defs.h" + +int +repo_remove_obsoletes(struct xbps_handle *xhp, const char *repodir) +{ + prop_dictionary_t pkgd; + prop_array_t idx; + DIR *dirp; + struct dirent *dp; + const char *pkgver, *arch; + char *plist; + int rv = 0; + + if ((plist = xbps_pkg_index_plist(xhp, repodir)) == NULL) + return -1; + + idx = prop_array_internalize_from_zfile(plist); + if (idx == NULL) { + if (errno != ENOENT) { + xbps_error_printf("xbps-repo: cannot read `%s': %s\n", + plist, strerror(errno)); + free(plist); + return -1; + } else { + free(plist); + return 0; + } + } + if (chdir(repodir) == -1) { + fprintf(stderr, "cannot chdir to %s: %s\n", + repodir, strerror(errno)); + prop_object_release(idx); + return errno; + } + if ((dirp = opendir(repodir)) == NULL) { + fprintf(stderr, "failed to open %s: %s\n", + repodir, strerror(errno)); + prop_object_release(idx); + return errno; + } + while ((dp = readdir(dirp))) { + if (strcmp(dp->d_name, "..") == 0) + continue; + if (!strstr(dp->d_name, ".xbps")) + continue; + + pkgd = xbps_dictionary_metadata_plist_by_url(dp->d_name, + "./props.plist"); + if (pkgd == NULL) { + fprintf(stderr, "failed to read metadata for `%s'," + " skipping!\n", dp->d_name); + continue; + } + prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); + prop_dictionary_get_cstring_nocopy(pkgd, "architecture", &arch); + /* + * If binpkg is not registered in index, remove binpkg. + */ + if (!xbps_find_pkg_in_array_by_pkgver(xhp, idx, pkgver, arch)) { + rv = repo_remove_pkg(repodir, arch, dp->d_name); + if (rv != 0) { + fprintf(stderr, "index: failed to remove " + "package `%s': %s\n", dp->d_name, + strerror(rv)); + prop_object_release(pkgd); + break; + } + printf("Removed obsolete package `%s'.\n", dp->d_name); + } + prop_object_release(pkgd); + } + (void)closedir(dirp); + prop_object_release(idx); + return rv; +} diff --git a/bin/xbps-repo/xbps-repo.8 b/bin/xbps-repo/xbps-repo.8 index 41f1f006..5c8fb1bd 100644 --- a/bin/xbps-repo/xbps-repo.8 +++ b/bin/xbps-repo/xbps-repo.8 @@ -1,4 +1,4 @@ -.Dd July 17, 2012 +.Dd July 22, 2012 .Os Void GNU/Linux .Dt xbps-repo 8 .Sh NAME @@ -91,6 +91,11 @@ or .Em description values in repository pool. Please note that patterns are matched in case insensitive mode. Multiple patterns can be specified as arguments. +.It Sy remove-obsoletes Ar /path/to/local/repository +Removes obsolete packages from +.Ar repository . +Packages that are not currently registered in repository's index will +be removed. .It Sy show Ar pkgname | pkgpattern Shows information for binary package .Ar pkgname