xbps-repo: new 'remove-obsoletes' target to remove obsolete pkgs in a local repo.

This commit is contained in:
Juan RP 2012-07-22 10:48:29 +02:00
parent f0c96aac65
commit 5a120e346e
8 changed files with 216 additions and 100 deletions

4
NEWS
View File

@ -1,5 +1,9 @@
xbps-0.16.6 (???): 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 * configure: fixes for Ubuntu, which uses ld(1) --as-needed by default and
some function tests were failiing due to this. some function tests were failiing due to this.

View File

@ -3,7 +3,8 @@ TOPDIR = ../..
BIN = xbps-repo BIN = xbps-repo
OBJS = main.o index.o show.o find-files.o list.o 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/fetch_cb.o ../xbps-bin/util.o
OBJS += ../xbps-bin/state_cb.o ../xbps-bin/list.o OBJS += ../xbps-bin/state_cb.o ../xbps-bin/list.o
MAN = $(BIN).8 MAN = $(BIN).8

70
bin/xbps-repo/common.c Normal file
View File

@ -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 <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <libgen.h>
#include <assert.h>
#include <xbps_api.h>
#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;
}

View File

@ -34,6 +34,9 @@ struct repo_search_data {
size_t pkgver_len; size_t pkgver_len;
}; };
/* From common.c */
int repo_remove_pkg(const char *, const char *, const char *);
/* From index.c */ /* From index.c */
int repo_index_add(struct xbps_handle *, int, char **); int repo_index_add(struct xbps_handle *, int, char **);
int repo_index_clean(struct xbps_handle *, const 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_add(struct xbps_handle *, int, char **);
int repo_index_files_clean(struct xbps_handle *, const 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 **); int acquire_repo_lock(const char *, char **);
void release_repo_lock(char **, int); void release_repo_lock(char **, int);
@ -63,6 +66,9 @@ int repo_search_pkgs_cb(struct xbps_handle *,
void *, void *,
bool *); bool *);
/* From remove-obsoletes.c */
int repo_remove_obsoletes(struct xbps_handle *, const char *);
/* From show.c */ /* From show.c */
int show_pkg_info_from_repolist(struct xbps_handle *, int show_pkg_info_from_repolist(struct xbps_handle *,
const char *, const char *,

View File

@ -36,95 +36,6 @@
#include <xbps_api.h> #include <xbps_api.h>
#include "defs.h" #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 * Removes stalled pkg entries in repository's index.plist file, if any
* binary package cannot be read (unavailable, not enough perms, etc). * binary package cannot be read (unavailable, not enough perms, etc).
@ -187,13 +98,10 @@ again:
} }
free(binpkg); free(binpkg);
} }
rv = remove_obsolete_binpkgs(xhp, array, repodir); if (flush && !prop_array_externalize_to_zfile(array, plist)) {
if (rv != 0)
goto out;
if (flush && !prop_array_externalize_to_zfile(array, plist))
rv = errno; rv = errno;
goto out;
}
printf("index: %u packages registered.\n", prop_array_count(array)); printf("index: %u packages registered.\n", prop_array_count(array));
out: out:
free(plist); free(plist);
@ -316,7 +224,8 @@ repo_index_add(struct xbps_handle *xhp, int argc, char **argv)
buf = xbps_xasprintf("`%s' (%s)", buf = xbps_xasprintf("`%s' (%s)",
oldpkgver, oldarch); oldpkgver, oldarch);
assert(buf); assert(buf);
rv = remove_oldpkg(repodir, oldarch, oldfilen); rv = repo_remove_pkg(repodir,
oldarch, oldfilen);
if (rv != 0) { if (rv != 0) {
prop_object_release(newpkgd); prop_object_release(newpkgd);
free(tmpfilen); free(tmpfilen);
@ -337,7 +246,7 @@ repo_index_add(struct xbps_handle *xhp, int argc, char **argv)
assert(buf); assert(buf);
buf2 = strdup(oldpkgver); buf2 = strdup(oldpkgver);
assert(buf2); assert(buf2);
rv = remove_oldpkg(repodir, oldarch, oldfilen); rv = repo_remove_pkg(repodir, oldarch, oldfilen);
if (rv != 0) { if (rv != 0) {
free(buf); free(buf);
free(buf2); free(buf2);

View File

@ -66,6 +66,9 @@ usage(bool fail)
" pkg-list [repo]\n" " pkg-list [repo]\n"
" Print packages in repository matching `repo' URI.\n" " Print packages in repository matching `repo' URI.\n"
" If `repo' not specified, all registered repositories will be used.\n" " If `repo' not specified, all registered repositories will be used.\n"
" remove-obsoletes <repository>\n"
" Removes obsolete packages (not registered in index any longer) from\n"
" local repository \"<repository>\".\n"
" search <pattern> [patterns]\n" " search <pattern> [patterns]\n"
" Search for packages in repositories matching the patterns.\n" " Search for packages in repositories matching the patterns.\n"
" show <pkgname|pkgpattern>\n" " show <pkgname|pkgpattern>\n"
@ -263,6 +266,13 @@ main(int argc, char **argv)
xbps_error_printf("xbps-repo: no repositories " xbps_error_printf("xbps-repo: no repositories "
"currently registered!\n"); "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) { } else if (strcasecmp(argv[0], "index-add") == 0) {
/* Registers a binary package into the repository's index. */ /* Registers a binary package into the repository's index. */
if (argc < 2) if (argc < 2)

View File

@ -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 <sys/stat.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <libgen.h>
#include <assert.h>
#include <xbps_api.h>
#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;
}

View File

@ -1,4 +1,4 @@
.Dd July 17, 2012 .Dd July 22, 2012
.Os Void GNU/Linux .Os Void GNU/Linux
.Dt xbps-repo 8 .Dt xbps-repo 8
.Sh NAME .Sh NAME
@ -91,6 +91,11 @@ or
.Em description .Em description
values in repository pool. Please note that patterns are matched in case values in repository pool. Please note that patterns are matched in case
insensitive mode. Multiple patterns can be specified as arguments. 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 .It Sy show Ar pkgname | pkgpattern
Shows information for binary package Shows information for binary package
.Ar pkgname .Ar pkgname