diff --git a/CHANGES b/CHANGES index 25298d0..40b1b70 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +20110906 + Added "requires" and "provides" to have a closer look on packages + requirements 20110901 pkg_install's pkgdb not needed anymore for a fresh start (bsdx's idea) diff --git a/Makefile.in b/Makefile.in index 9d69db0..1f0e1e9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,10 +1,11 @@ -# $Id: Makefile.in,v 1.9 2011/08/30 11:52:17 imilh Exp $ +# $Id: Makefile.in,v 1.10 2011/09/06 17:49:09 imilh Exp $ PROG= pkgin VERSION= @PACKAGE_VERSION@ SRCS= main.c summary.c tools.c pkgindb.c depends.c actions.c \ pkglist.c download.c order.c impact.c autoremove.c fsops.c \ - pkgindb_queries.c pkg_str.c sqlite_callbacks.c selection.c + pkgindb_queries.c pkg_str.c sqlite_callbacks.c selection.c \ + pkg_check.c # included from libinstall SRCS+= automatic.c decompress.c dewey.c fexec.c global.c \ opattern.c pkgdb.c var.c diff --git a/README b/README index 819a6d8..e2983a5 100644 --- a/README +++ b/README @@ -1,3 +1,3 @@ Please refer to http://pkgin.net/ -Emile "iMil" Heitor +Emile "iMil" Heitor diff --git a/actions.c b/actions.c index 3e342a9..d33e20f 100644 --- a/actions.c +++ b/actions.c @@ -1,7 +1,7 @@ -/* $Id: actions.c,v 1.9 2011/09/01 18:45:43 imilh Exp $ */ +/* $Id: actions.c,v 1.10 2011/09/06 17:49:09 imilh Exp $ */ /* - * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. + * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -260,157 +260,6 @@ action_list(char *flatlist, char *str) return newlist; } -/* find required files (REQUIRES) from PROVIDES or filename */ -static int -pkg_met_reqs(Plisthead *impacthead) -{ - int met_reqs = 1, foundreq; - Pkglist *pimpact, *requires; - Plisthead *requireshead = NULL; -#ifdef CHECK_PROVIDES - Pkglist *impactprov = NULL, *provides = NULL; - Plisthead *provideshead = NULL; -#endif - struct stat sb; - char query[BUFSIZ]; - - /* first, parse impact list */ - SLIST_FOREACH(pimpact, impacthead, next) { - /* retreive requires list for package */ - snprintf(query, BUFSIZ, GET_REQUIRES_QUERY, pimpact->full); - requireshead = rec_pkglist(query); - - if (requireshead == NULL) /* empty requires list (very unlikely) */ - continue; - - /* parse requires list */ - SLIST_FOREACH(requires, requireshead, next) { - - foundreq = 0; - - /* for performance sake, first check basesys */ - if ((strncmp(requires->full, LOCALBASE, - strlen(LOCALBASE) - 1)) != 0) { - if (stat(requires->full, &sb) < 0) { - printf(MSG_REQT_NOT_PRESENT, - requires->full, pimpact->full); - - met_reqs = 0; - } - /* was a basysfile, no need to check PROVIDES */ - continue; - } - /* FIXME: the code below actually works, but there's no - * point losing performances when some REQUIRES do not match - * PROVIDES in pkg_summary(5). This is a known issue and will - * hopefuly be fixed. - */ -#ifndef CHECK_PROVIDES - continue; -#else - /* search what local packages provide */ - provideshead = rec_pkglist(LOCAL_PROVIDES); - SLIST_FOREACH(provides, provideshead, next) { - if (strncmp(provides->full, - requires->full, - strlen(requires->full)) == 0) { - - foundreq = 1; - - /* found, no need to go further*/ - break; - } /* match */ - } /* SLIST_FOREACH LOCAL_PROVIDES */ - free_pkglist(&provideshead, LIST); - - /* REQUIRES was not found on local packages, try impact list */ - if (!foundreq) { - /* re-parse impact list to retreive PROVIDES */ - SLIST_FOREACH(impactprov, impacthead, next) { - snprintf(query, BUFSIZ, GET_PROVIDES_QUERY, - impactprov->full); - provideshead = rec_pkglist(query); - - if (provideshead == NULL) - continue; - - /* then parse provides list for every package */ - SLIST_FOREACH(provides, provideshead, next) { - if (strncmp(provides->full, - requires->full, - strlen(requires->full)) == 0) { - - foundreq = 1; - - /* found, no need to go further - return to impactprov list */ - break; - } /* match */ - } - free_pkglist(&provideshead, LIST); - - if (foundreq) /* exit impactprov list loop */ - break; - - } /* SLIST_NEXT impactprov */ - - } /* if (!foundreq) LOCAL_PROVIDES -> impact list */ - - /* FIXME: BIG FAT DISCLAIMER - * as of 04/2009, some packages described in pkg_summary - * have unmet REQUIRES. This is a known bug that makes the - * PROVIDES untrustable and some packages uninstallable. - * foundreq is forced to 1 for now for every REQUIRES - * matching LOCALBASE, which is hardcoded to "/usr/pkg" - */ - if (!foundreq) { - printf(MSG_REQT_NOT_PRESENT_BUT, requires->full); - - foundreq = 1; - } -#endif - } /* SLIST_FOREACH requires */ - free_pkglist(&requireshead, LIST); - } /* 1st impact SLIST_FOREACH */ - - return met_reqs; -} - -/* check for conflicts and if needed files are present */ -static int -pkg_has_conflicts(Plisthead *conflictshead, Pkglist *pimpact) -{ - int has_conflicts = 0; - Pkglist *conflicts; /* SLIST conflicts pointer */ - char *conflict_pkg, query[BUFSIZ]; - - if (conflictshead == NULL) - return 0; - - /* check conflicts */ - SLIST_FOREACH(conflicts, conflictshead, next) { - if (pkg_match(conflicts->full, pimpact->full)) { - - /* got a conflict, retrieve conflicting local package */ - snprintf(query, BUFSIZ, - GET_CONFLICT_QUERY, conflicts->full); - - XMALLOC(conflict_pkg, BUFSIZ * sizeof(char)); - if (pkgindb_doquery(query, - pdb_get_value, conflict_pkg) == PDB_OK) - - printf(MSG_CONFLICT_PKG, - pimpact->full, conflict_pkg); - - XFREE(conflict_pkg); - - has_conflicts = 1; - } /* match conflict */ - } /* SLIST_FOREACH conflicts */ - - return has_conflicts; -} - #define H_BUF 6 int @@ -423,7 +272,6 @@ pkgin_install(char **opkgargs, uint8_t do_inst) Pkglist *pimpact; Plisthead *impacthead; /* impact head */ Plisthead *removehead = NULL, *installhead = NULL; - Plisthead *conflictshead = NULL; /* conflicts head */ char **pkgargs; char *toinstall = NULL, *toupgrade = NULL, *toremove = NULL; char pkgpath[BUFSIZ], h_psize[H_BUF], h_fsize[H_BUF]; @@ -447,14 +295,11 @@ pkgin_install(char **opkgargs, uint8_t do_inst) goto installend; } - /* conflicts list */ - conflictshead = rec_pkglist(LOCAL_CONFLICTS); - /* browse impact tree */ SLIST_FOREACH(pimpact, impacthead, next) { /* check for conflicts */ - if (pkg_has_conflicts(conflictshead, pimpact)) + if (pkg_has_conflicts(pimpact)) if (!check_yesno(DEFAULT_NO)) goto installend; @@ -571,7 +416,6 @@ pkgin_install(char **opkgargs, uint8_t do_inst) XFREE(toinstall); XFREE(toupgrade); - free_pkglist(&conflictshead, LIST); free_pkglist(&impacthead, IMPACT); free_pkglist(&removehead, DEPTREE); free_pkglist(&installhead, DEPTREE); diff --git a/cmd.h b/cmd.h index 6d0cc35..6b8b4af 100644 --- a/cmd.h +++ b/cmd.h @@ -1,4 +1,4 @@ -/* $Id: cmd.h,v 1.4 2011/08/30 16:23:00 imilh Exp $ */ +/* $Id: cmd.h,v 1.5 2011/09/06 17:49:09 imilh Exp $ */ /* * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc. @@ -72,6 +72,10 @@ static struct command { PKG_EXPORT_CMD }, { "import", "im", "Import \"non auto-removable\" package list from file.", PKG_IMPORT_CMD }, + { "provides", "prov", "Show what a package provides.", + PKG_SHPROV_CMD }, + { "requires", "req", "Show what a package requires.", + PKG_SHREQ_CMD }, { "tonic", "to", "Gin Tonic recipe.", PKG_GINTO_CMD }, { NULL, NULL, NULL, 0 } diff --git a/main.c b/main.c index d82369d..418e72b 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.10 2011/08/30 16:23:00 imilh Exp $ */ +/* $Id: main.c,v 1.11 2011/09/06 17:49:09 imilh Exp $ */ /* * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. @@ -220,6 +220,14 @@ main(int argc, char *argv[]) missing_param(argc, 2, MSG_MISSING_FILENAME); import_keep(do_inst, argv[1]); break; + case PKG_SHPROV_CMD: /* show what a package provides */ + missing_param(argc, 2, MSG_MISSING_PKGNAME); + show_prov_req(GET_PROVIDES_QUERY, argv[1]); + break; + case PKG_SHREQ_CMD: /* show what a package requires */ + missing_param(argc, 2, MSG_MISSING_PKGNAME); + show_prov_req(GET_REQUIRES_QUERY, argv[1]); + break; case PKG_GINTO_CMD: /* Miod's request */ ginto(); break; diff --git a/messages.h b/messages.h index 1107c95..21da3a5 100644 --- a/messages.h +++ b/messages.h @@ -1,4 +1,4 @@ -/* $Id: messages.h,v 1.9 2011/08/30 16:23:00 imilh Exp $ */ +/* $Id: messages.h,v 1.10 2011/09/06 17:49:09 imilh Exp $ */ /* * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. @@ -63,8 +63,8 @@ #define MSG_INSTALLING "installing %s...\n" #define MSG_REQT_NOT_PRESENT \ "%s, needed by %s is not present in this system.\n" -#define MSG_REQT_NOT_PRESENT_BUT \ - "warning: %s is not present in this system (may be installed by this package)\n" +#define MSG_REQT_NOT_PRESENT_DEPS \ + "warning: %s is not present in this system nor package's dependencies\n" #define MSG_CONFLICT_PKG \ "%s (to be installed) conflicts with installed package %s.\n" #define MSG_NOTHING_TO_DO "nothing to do.\n" @@ -144,3 +144,6 @@ please re-run %s with a package name matching one of the following:\n" /* selection.c */ #define MSG_EMPTY_IMPORT_LIST "Empty import list." + +/* pkg_check.c */ +#define MSG_NO_PROV_REQ "Nothing %s by %s.\n" diff --git a/pkg_check.c b/pkg_check.c new file mode 100644 index 0000000..91ec331 --- /dev/null +++ b/pkg_check.c @@ -0,0 +1,226 @@ +/* $Id: pkg_check.c,v 1.1 2011/09/06 17:49:09 imilh Exp $ */ + +/* + * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Emile "iMil" Heitor . + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 "pkgin.h" + +/** + * \brief Return a PROVIDES/REQUIRES list + */ +static Plisthead * +get_prov_req(const char *get_query, char *pkgname) +{ + char query[BUFSIZ]; + Plisthead *plisthead; + + snprintf(query, BUFSIZ, get_query, pkgname); + plisthead = rec_pkglist(query); + + return plisthead; +} + +/* find required files (REQUIRES) from PROVIDES or filename */ +int +pkg_met_reqs(Plisthead *impacthead) +{ + int met_reqs = 1, foundreq; + Pkglist *pimpact, *requires; + Plisthead *requireshead = NULL; + struct stat sb; +#ifdef CHECK_PROVIDES + Pkglist *impactprov = NULL, *provides = NULL; + Plisthead *l_provideshead = NULL, *r_provideshead = NULL; + + l_provideshead = rec_pkglist(LOCAL_PROVIDES); +#endif + + /* first, parse impact list */ + SLIST_FOREACH(pimpact, impacthead, next) { + /* retreive requires list for package */ + if ((requireshead = get_prov_req(GET_REQUIRES_QUERY, + pimpact->full)) == NULL) + /* empty requires list (very unlikely) */ + continue; + + /* parse requires list */ + SLIST_FOREACH(requires, requireshead, next) { + + foundreq = 0; + + /* for performance sake, first check basesys */ + if ((strncmp(requires->full, LOCALBASE, + strlen(LOCALBASE) - 1)) != 0) { + if (stat(requires->full, &sb) < 0) { + printf(MSG_REQT_NOT_PRESENT, + requires->full, pimpact->full); + + met_reqs = 0; + } + /* was a basysfile, no need to check PROVIDES */ + continue; + } + /* FIXME: the code below actually works, but there's no + * point losing performances when some REQUIRES do not match + * PROVIDES in pkg_summary(5). This is a known issue and will + * hopefuly be fixed. + */ +#ifndef CHECK_PROVIDES + continue; +#else + /* search what local packages provide */ + SLIST_FOREACH(provides, l_provideshead, next) { + if (strncmp(provides->full, + requires->full, + strlen(requires->full)) == 0) { + + foundreq = 1; + + /* found, no need to go further*/ + break; + } /* match */ + } /* SLIST_FOREACH LOCAL_PROVIDES */ + + /* REQUIRES was not found on local packages, try impact list */ + if (!foundreq) { + /* re-parse impact list to retreive PROVIDES */ + SLIST_FOREACH(impactprov, impacthead, next) { + if ((r_provideshead = + get_prov_req(GET_PROVIDES_QUERY, + impactprov->full)) == NULL) + continue; + + /* then parse provides list for every package */ + SLIST_FOREACH(provides, r_provideshead, next) { + if (strncmp(provides->full, + requires->full, + strlen(requires->full)) == 0) { + + foundreq = 1; + + /* found, no need to go further + return to impactprov list */ + break; + } /* match */ + } + free_pkglist(&r_provideshead, LIST); + + if (foundreq) /* exit impactprov list loop */ + break; + + } /* SLIST_NEXT impactprov */ + + } /* if (!foundreq) LOCAL_PROVIDES -> impact list */ + + /* FIXME: BIG FAT DISCLAIMER + * as of 04/2009, some packages described in pkg_summary + * have unmet REQUIRES. This is a known bug that makes the + * PROVIDES untrustable and some packages uninstallable. + * foundreq is forced to 1 for now for every REQUIRES + * matching LOCALBASE, which is hardcoded to "/usr/pkg" + */ + if (!foundreq) { + printf(MSG_REQT_NOT_PRESENT_DEPS, requires->full); + + foundreq = 1; + } +#endif + } /* SLIST_FOREACH requires */ + free_pkglist(&requireshead, LIST); + } /* 1st impact SLIST_FOREACH */ + +#ifdef CHECK_PROVIDES + free_pkglist(&l_provideshead, LIST); +#endif + + return met_reqs; +} + +/* check for conflicts and if needed files are present */ +int +pkg_has_conflicts(Pkglist *pimpact) +{ + int has_conflicts = 0; + char *conflict_pkg, query[BUFSIZ]; + Pkglist *conflicts; /* SLIST conflicts pointer */ + Plisthead *conflictshead; + + /* conflicts list */ + if ((conflictshead = rec_pkglist(LOCAL_CONFLICTS)) == NULL) + return 0; + + /* check conflicts */ + SLIST_FOREACH(conflicts, conflictshead, next) { + if (pkg_match(conflicts->full, pimpact->full)) { + + /* got a conflict, retrieve conflicting local package */ + snprintf(query, BUFSIZ, + GET_CONFLICT_QUERY, conflicts->full); + + XMALLOC(conflict_pkg, BUFSIZ * sizeof(char)); + if (pkgindb_doquery(query, + pdb_get_value, conflict_pkg) == PDB_OK) + + printf(MSG_CONFLICT_PKG, + pimpact->full, conflict_pkg); + + XFREE(conflict_pkg); + + has_conflicts = 1; + } /* match conflict */ + } /* SLIST_FOREACH conflicts */ + + free_pkglist(&conflictshead, LIST); + + return has_conflicts; +} + +void +show_prov_req(const char *query, const char *pkgname) +{ + const char *out[] = { "provided", "required" }; + const char *say; + char *fullpkgname; + Plisthead *plisthead; + Pkglist *plist; + + if ((fullpkgname = unique_pkg(pkgname, REMOTE_PKG)) == NULL) + errx(EXIT_FAILURE, MSG_PKG_NOT_AVAIL, pkgname); + + say = ( query == GET_PROVIDES_QUERY ) ? out[0] : out[1]; + + if ((plisthead = get_prov_req(query, fullpkgname)) == NULL) { + printf(MSG_NO_PROV_REQ, say, fullpkgname); + exit(EXIT_SUCCESS); + } + + SLIST_FOREACH(plist, plisthead, next) + printf("%s is %s by %s\n", plist->full, say, fullpkgname); +} diff --git a/pkgin.1 b/pkgin.1 index 345d488..eb4d262 100644 --- a/pkgin.1 +++ b/pkgin.1 @@ -242,4 +242,4 @@ FreeBSD port and patches MINIX port .El .Sh BUGS -Probably many to be found. +We're hunting them. diff --git a/pkgin.h b/pkgin.h index 9de1178..2400347 100644 --- a/pkgin.h +++ b/pkgin.h @@ -1,4 +1,4 @@ -/* $Id: pkgin.h,v 1.14 2011/08/31 12:01:27 imilh Exp $ */ +/* $Id: pkgin.h,v 1.15 2011/09/06 17:49:09 imilh Exp $ */ /* * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. @@ -102,6 +102,8 @@ #define PKG_AUTORM_CMD 15 #define PKG_EXPORT_CMD 16 #define PKG_IMPORT_CMD 17 +#define PKG_SHPROV_CMD 18 +#define PKG_SHREQ_CMD 19 #define PKG_GINTO_CMD 255 #define PKG_EQUAL '=' @@ -249,5 +251,9 @@ char **glob_to_pkgarg(char **); /* selection.c */ void export_keep(void); void import_keep(uint8_t, const char *); +/* pkg_check.c */ +int pkg_met_reqs(Plisthead *); +int pkg_has_conflicts(Pkglist *); +void show_prov_req(const char *, const char *); #endif diff --git a/pkgindb_queries.c b/pkgindb_queries.c index 6018259..2768cfb 100644 --- a/pkgindb_queries.c +++ b/pkgindb_queries.c @@ -1,4 +1,4 @@ -/* $Id: pkgindb_queries.c,v 1.10 2011/08/31 16:58:26 imilh Exp $ */ +/* $Id: pkgindb_queries.c,v 1.11 2011/09/06 17:49:09 imilh Exp $ */ /* * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. @@ -95,13 +95,13 @@ const char GET_CONFLICT_QUERY[] = const char GET_REQUIRES_QUERY[] = "SELECT REMOTE_REQUIRES.REMOTE_REQUIRES_PKGNAME " "FROM REMOTE_REQUIRES,REMOTE_PKG " - "WHERE REMOTE_PKG.PKGNAME = \'%s\' " + "WHERE REMOTE_PKG.FULLPKGNAME = '%s' " "AND REMOTE_REQUIRES.PKG_ID = REMOTE_PKG.PKG_ID;"; const char GET_PROVIDES_QUERY[] = "SELECT REMOTE_PROVIDES.REMOTE_PROVIDES_PKGNAME " "FROM REMOTE_PROVIDES,REMOTE_PKG " - "WHERE REMOTE_PKG.PKGNAME = \'%s\' " + "WHERE REMOTE_PKG.FULLPKGNAME = '%s' " "AND REMOTE_PROVIDES.PKG_ID = REMOTE_PKG.PKG_ID;"; const char LOCAL_PROVIDES[] =