Introduce -D, --database

The request of FS#12950 is implemented.

On the backend side, I introduced a new function, alpm_db_set_pkgreason(),
to modify the install reason of a package in the local database. On the
front-end side, I introduced a new main operation, -D/--database, which has
two options, --asdeps and --asexplicit. I documented this in pacman manual.
I've created two pactests to test -D: database001.py and database002.py.

Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
Nagy Gabor 2009-05-20 21:46:23 +02:00 committed by Dan McGee
parent 6b6eb6345b
commit ac9dde072c
11 changed files with 189 additions and 12 deletions

View file

@ -28,6 +28,12 @@ front ends to be written (for instance, a GUI front end).
Operations Operations
---------- ----------
*-D, \--database*::
Modify the package database. This options allows you to modify certain
attributes of the installed packages in pacman's database. At the
moment, you can only change the install reason using '\--asdeps' and
'\--asexplicit' options.
*-Q, \--query*:: *-Q, \--query*::
Query the package database. This operation allows you to view installed Query the package database. This operation allows you to view installed
packages and their files, as well as meta-information about individual packages and their files, as well as meta-information about individual

View file

@ -158,6 +158,15 @@ void alpm_option_set_usedelta(int usedelta);
pmdb_t *alpm_option_get_localdb(); pmdb_t *alpm_option_get_localdb();
alpm_list_t *alpm_option_get_syncdbs(); alpm_list_t *alpm_option_get_syncdbs();
/*
* Install reasons -- ie, why the package was installed
*/
typedef enum _pmpkgreason_t {
PM_PKG_REASON_EXPLICIT = 0, /* explicitly requested by the user */
PM_PKG_REASON_DEPEND = 1 /* installed as a dependency for another package */
} pmpkgreason_t;
/* /*
* Databases * Databases
*/ */
@ -181,6 +190,7 @@ alpm_list_t *alpm_db_get_pkgcache(pmdb_t *db);
pmgrp_t *alpm_db_readgrp(pmdb_t *db, const char *name); pmgrp_t *alpm_db_readgrp(pmdb_t *db, const char *name);
alpm_list_t *alpm_db_get_grpcache(pmdb_t *db); alpm_list_t *alpm_db_get_grpcache(pmdb_t *db);
alpm_list_t *alpm_db_search(pmdb_t *db, const alpm_list_t* needles); alpm_list_t *alpm_db_search(pmdb_t *db, const alpm_list_t* needles);
int alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason);
/* /*
* Packages * Packages
@ -188,12 +198,6 @@ alpm_list_t *alpm_db_search(pmdb_t *db, const alpm_list_t* needles);
/* Info parameters */ /* Info parameters */
/* reasons -- ie, why the package was installed */
typedef enum _pmpkgreason_t {
PM_PKG_REASON_EXPLICIT = 0, /* explicitly requested by the user */
PM_PKG_REASON_DEPEND = 1 /* installed as a dependency for another package */
} pmpkgreason_t;
int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg); int alpm_pkg_load(const char *filename, int full, pmpkg_t **pkg);
int alpm_pkg_free(pmpkg_t *pkg); int alpm_pkg_free(pmpkg_t *pkg);
int alpm_pkg_checkmd5sum(pmpkg_t *pkg); int alpm_pkg_checkmd5sum(pmpkg_t *pkg);

View file

@ -321,6 +321,44 @@ alpm_list_t SYMEXPORT *alpm_db_search(pmdb_t *db, const alpm_list_t* needles)
return(_alpm_db_search(db, needles)); return(_alpm_db_search(db, needles));
} }
/* Set install reason for a package in db
* @param db pointer to the package database
* @param name the name of the package
* @param reason the new install reason
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int SYMEXPORT alpm_db_set_pkgreason(pmdb_t *db, const char *name, pmpkgreason_t reason)
{
ALPM_LOG_FUNC;
/* Sanity checks */
ASSERT(handle != NULL, RET_ERR(PM_ERR_HANDLE_NULL, -1));
ASSERT(db != NULL && name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
pmpkg_t *pkg = _alpm_db_get_pkgfromcache(db, name);
if(pkg == NULL) {
RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
}
_alpm_log(PM_LOG_DEBUG, "setting install reason %u for %s/%s\n", reason, db->treename, name);
/* read DESC */
if(_alpm_db_read(db, pkg, INFRQ_DESC)) {
return(-1);
}
if(pkg->reason == reason) {
/* we are done */
return(0);
}
/* set reason (in pkgcache) */
pkg->reason = reason;
/* write DESC */
if(_alpm_db_write(db, pkg, INFRQ_DESC)) {
return(-1);
}
return(0);
}
/** @} */ /** @} */
static pmdb_t *_alpm_db_new(const char *treename, int is_local) static pmdb_t *_alpm_db_new(const char *treename, int is_local)

View file

@ -0,0 +1,11 @@
self.description = "-D --asdeps"
lp = pmpkg("pkg")
lp.reason = 0
self.addpkg2db("local", lp)
self.args = "-D pkg --asdeps"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg")
self.addrule("PKG_REASON=pkg|1")

View file

@ -0,0 +1,11 @@
self.description = "-D --asexplicit"
lp = pmpkg("pkg")
lp.reason = 1
self.addpkg2db("local", lp)
self.args = "-D pkg --asexplicit"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg")
self.addrule("PKG_REASON=pkg|0")

View file

@ -24,6 +24,7 @@ endif
pacman_SOURCES = \ pacman_SOURCES = \
conf.h conf.c \ conf.h conf.c \
database.c \
deptest.c \ deptest.c \
package.h package.c \ package.h package.c \
pacman.h pacman.c \ pacman.h pacman.c \

View file

@ -86,7 +86,8 @@ enum {
PM_OP_UPGRADE, PM_OP_UPGRADE,
PM_OP_QUERY, PM_OP_QUERY,
PM_OP_SYNC, PM_OP_SYNC,
PM_OP_DEPTEST PM_OP_DEPTEST,
PM_OP_DATABASE
}; };
/* Long Operations */ /* Long Operations */

90
src/pacman/database.c Normal file
View file

@ -0,0 +1,90 @@
/*
* database.c
*
* Copyright (c) 2006-2010 Pacman Development Team <pacman-dev@archlinux.org>
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <alpm.h>
#include <alpm_list.h>
/* pacman */
#include "pacman.h"
#include "conf.h"
#include "util.h"
extern pmdb_t *db_local;
/**
* @brief Modify the 'local' package database.
*
* @param targets a list of packages (as strings) to modify
*
* @return 0 on success, 1 on failure
*/
int pacman_database(alpm_list_t *targets)
{
alpm_list_t *i;
int retval = 0;
pmpkgreason_t reason;
if(targets == NULL) {
pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
return(1);
}
if(config->flags & PM_TRANS_FLAG_ALLDEPS) { /* --asdeps */
reason = PM_PKG_REASON_DEPEND;
} else if(config->flags & PM_TRANS_FLAG_ALLEXPLICIT) { /* --asexplicit */
reason = PM_PKG_REASON_EXPLICIT;
} else {
pm_printf(PM_LOG_ERROR, _("no install reason specified (use -h for help)\n"));
return(1);
}
/* Lock database */
if(trans_init(0) == -1) {
return(1);
}
for(i = targets; i; i = alpm_list_next(i)) {
char *pkgname = i->data;
if(alpm_db_set_pkgreason(db_local, pkgname, reason) == -1) {
pm_printf(PM_LOG_ERROR, _("could not set install reason for package %s (%s)\n"),
pkgname, alpm_strerrorlast());
retval = 1;
} else {
if(reason == PM_PKG_REASON_DEPEND) {
printf(_("%s: install reason has been set to 'installed as dependency'\n"), pkgname);
} else {
printf(_("%s: install reason has been set to 'explicitly installed'\n"), pkgname);
}
}
}
/* Unlock database */
if(trans_release() == -1) {
return(1);
}
return(retval);
}
/* vim: set ts=2 sw=2 noet: */

View file

@ -77,10 +77,11 @@ static void usage(int op, const char * const myname)
printf(_("operations:\n")); printf(_("operations:\n"));
printf(" %s {-h --help}\n", myname); printf(" %s {-h --help}\n", myname);
printf(" %s {-V --version}\n", myname); printf(" %s {-V --version}\n", myname);
printf(" %s {-Q --query} [%s] [%s]\n", myname, str_opt, str_pkg); printf(" %s {-D --database} <%s> <%s>\n", myname, str_opt, str_pkg);
printf(" %s {-R --remove} [%s] <%s>\n", myname, str_opt, str_pkg); printf(" %s {-Q --query} [%s] [%s]\n", myname, str_opt, str_pkg);
printf(" %s {-S --sync} [%s] [%s]\n", myname, str_opt, str_pkg); printf(" %s {-R --remove} [%s] <%s>\n", myname, str_opt, str_pkg);
printf(" %s {-U --upgrade} [%s] <%s>\n", myname, str_opt, str_file); printf(" %s {-S --sync} [%s] [%s]\n", myname, str_opt, str_pkg);
printf(" %s {-U --upgrade} [%s] <%s>\n", myname, str_opt, str_file);
printf(_("\nuse '%s {-h --help}' with an operation for available options\n"), printf(_("\nuse '%s {-h --help}' with an operation for available options\n"),
myname); myname);
} else { } else {
@ -147,6 +148,11 @@ static void usage(int op, const char * const myname)
printf(_(" --print-format <string>\n" printf(_(" --print-format <string>\n"
" specify how the targets should be printed\n")); " specify how the targets should be printed\n"));
printf(_(" -q, --quiet show less information for query and search\n")); printf(_(" -q, --quiet show less information for query and search\n"));
} else if (op == PM_OP_DATABASE) {
printf("%s: %s {-D --database} <%s> <%s>\n", str_usg, myname, str_opt, str_pkg);
printf("%s:\n", str_opt);
printf(_(" --asdeps mark packages as non-explicitly installed\n"));
printf(_(" --asexplicit mark packages as explicitly installed\n"));
} }
printf(_(" --config <path> set an alternate configuration file\n")); printf(_(" --config <path> set an alternate configuration file\n"));
printf(_(" --logfile <path> set an alternate log file\n")); printf(_(" --logfile <path> set an alternate log file\n"));
@ -355,6 +361,7 @@ static int parseargs(int argc, char *argv[])
int option_index = 0; int option_index = 0;
static struct option opts[] = static struct option opts[] =
{ {
{"database", no_argument, 0, 'D'},
{"query", no_argument, 0, 'Q'}, {"query", no_argument, 0, 'Q'},
{"remove", no_argument, 0, 'R'}, {"remove", no_argument, 0, 'R'},
{"sync", no_argument, 0, 'S'}, {"sync", no_argument, 0, 'S'},
@ -409,7 +416,7 @@ static int parseargs(int argc, char *argv[])
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
while((opt = getopt_long(argc, argv, "RUQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) { while((opt = getopt_long(argc, argv, "RUDQSTr:b:vkhscVfmnoldepqituwygz", opts, &option_index))) {
alpm_list_t *list = NULL, *item = NULL; /* lists for splitting strings */ alpm_list_t *list = NULL, *item = NULL; /* lists for splitting strings */
if(opt < 0) { if(opt < 0) {
@ -498,6 +505,7 @@ static int parseargs(int argc, char *argv[])
check_optarg(); check_optarg();
config->print_format = strdup(optarg); config->print_format = strdup(optarg);
break; break;
case 'D': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_DATABASE); break;
case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break; case 'Q': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_QUERY); break;
case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break; case 'R': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_REMOVE); break;
case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break; case 'S': config->op = (config->op != PM_OP_MAIN ? 0 : PM_OP_SYNC); break;
@ -1184,6 +1192,9 @@ int main(int argc, char *argv[])
/* start the requested operation */ /* start the requested operation */
switch(config->op) { switch(config->op) {
case PM_OP_DATABASE:
ret = pacman_database(pm_targets);
break;
case PM_OP_REMOVE: case PM_OP_REMOVE:
ret = pacman_remove(pm_targets); ret = pacman_remove(pm_targets);
break; break;

View file

@ -22,6 +22,8 @@
#include <alpm_list.h> #include <alpm_list.h>
/* database.c */
int pacman_database(alpm_list_t *targets);
/* query.c */ /* query.c */
int pacman_query(alpm_list_t *targets); int pacman_query(alpm_list_t *targets);
/* remove.c */ /* remove.c */

View file

@ -80,6 +80,8 @@ int trans_release(void)
int needs_root(void) int needs_root(void)
{ {
switch(config->op) { switch(config->op) {
case PM_OP_DATABASE:
return(1);
case PM_OP_UPGRADE: case PM_OP_UPGRADE:
case PM_OP_REMOVE: case PM_OP_REMOVE:
return(!config->print); return(!config->print);