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:
parent
6b6eb6345b
commit
ac9dde072c
11 changed files with 189 additions and 12 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
11
pactest/tests/database001.py
Normal file
11
pactest/tests/database001.py
Normal 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")
|
11
pactest/tests/database002.py
Normal file
11
pactest/tests/database002.py
Normal 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")
|
|
@ -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 \
|
||||||
|
|
|
@ -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
90
src/pacman/database.c
Normal 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: */
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue