[pacman-dev] [PATCH 4/5] Reimplement advanced group handling
Jakob Gruber
jakob.gruber at gmail.com
Sat Sep 25 05:40:05 EDT 2010
Allows user interaction during group installation, and makes groups
installation use the same code paths as individual packages which should
ensure proper handling of additional flag (like --needed, --ignore,
...). Implemented in libalpm using callbacks for user interaction.
Reimplements group handling lost in
b4317a740ac2d4f5e4d1aa56a97171c52be70d02.
Related issues:
* http://www.archlinux.org/pipermail/pacman-dev/2009-June/008847.html
operation aborts when a package from a group is ignored and user chooses
not to install it
* FS#15141
'pacman -S <repo>/<group>' syntax
* FS#19854
--ignore is ignored when installing a group
* FS#19853
no prompting about groups
* FS#20221
installing group from multiple repos with --needed
Signed-off-by: Jakob Gruber <jakob.gruber at gmail.com>
---
lib/libalpm/alpm.h | 11 ++++++++-
lib/libalpm/sync.c | 51 ++++++++++++++++++++++++++++++++++++++++++------
src/pacman/callback.c | 21 ++++++++++++++++++++
src/pacman/util.c | 12 ++++++++--
4 files changed, 83 insertions(+), 12 deletions(-)
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 0c01f21..f02bcbf 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -368,6 +368,11 @@ typedef enum _pmtransevt_t {
* The repository's tree name is passed to the callback.
*/
PM_TRANS_EVT_RETRIEVE_START,
+ /** Package not found during sync, looking for group */
+ PM_TRANS_EVT_PKG_NOT_FOUND,
+ /** Group will be installed, group and db is
+ * passed to the callback. */
+ PM_TRANS_EVT_INSTALL_GROUP,
} pmtransevt_t;
/*@}*/
@@ -379,6 +384,8 @@ typedef enum _pmtransconv_t {
PM_TRANS_CONV_CORRUPTED_PKG = (1 << 3),
PM_TRANS_CONV_LOCAL_NEWER = (1 << 4),
PM_TRANS_CONV_REMOVE_PKGS = (1 << 5),
+ PM_TRANS_CONV_INSTALL_GROUPPKG = (1 << 6),
+ PM_TRANS_CONV_INSTALL_GROUP = (1 << 7),
} pmtransconv_t;
/* Transaction Progress */
@@ -411,8 +418,8 @@ int alpm_trans_interrupt(void);
int alpm_trans_release(void);
int alpm_sync_sysupgrade(int enable_downgrade);
-int alpm_sync_target(char *target);
-int alpm_sync_dbtarget(char *db, char *target);
+int alpm_sync_target(const char *target);
+int alpm_sync_dbtarget(char *db, const char *target);
int alpm_add_target(char *target);
int alpm_remove_target(char *target);
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index f819396..8982874 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -248,7 +248,7 @@ static int sync_pkg(pmpkg_t *spkg, alpm_list_t *pkg_list)
return(0);
}
-static int sync_target(alpm_list_t *dbs_sync, char *target)
+static int sync_target(alpm_list_t *dbs_sync, const char *target)
{
alpm_list_t *i, *j;
alpm_list_t *known_pkgs = NULL;
@@ -271,15 +271,53 @@ static int sync_target(alpm_list_t *dbs_sync, char *target)
return(sync_pkg(spkg, handle->trans->add));
}
+ /* begin group handling. this section is responsible for looking for
+ * groups, user interaction, and finally adding group members to the
+ * queue. to stay consistent with individual package handling, it
+ * calls sync_target() for each group member to be installed */
_alpm_log(PM_LOG_DEBUG, "%s package not found, searching for group...\n", target);
+ EVENT(handle->trans, PM_TRANS_EVT_PKG_NOT_FOUND, (void*)target, NULL);
+
for(i = dbs_sync; i; i = i->next) {
pmdb_t *db = i->data;
grp = alpm_db_readgrp(db, target);
+
if(grp) {
found = 1;
- for(j = alpm_grp_get_pkgs(grp); j; j = j->next) {
- pmpkg_t *pkg = j->data;
- if(sync_pkg(pkg, known_pkgs) == -1) {
+
+ /* display group members */
+ EVENT(handle->trans, PM_TRANS_EVT_INSTALL_GROUP, (void*)grp,
+ (void*)db);
+
+ /* ask if user wants to install all group members */
+ int installall = 1;
+ QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_GROUP, db, grp,
+ NULL, &installall);
+
+ /* individually process all member packages */
+ for(j = alpm_grp_get_pkgs(grp); j; j = alpm_list_next(j)) {
+ pmpkg_t *pkg = alpm_list_getdata(j);
+ const char *pkgname = alpm_pkg_get_name(pkg);
+
+ /* package already processed in another repo, skip */
+ if(known_pkgs && alpm_list_find_str(known_pkgs, pkgname)) {
+ continue;
+ }
+ known_pkgs = alpm_list_add(known_pkgs, (void*)pkgname);
+
+ /* confirm user wants to install group member */
+ if(installall == 0) {
+ int install = 1;
+ QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_GROUPPKG, pkg, grp,
+ NULL, &install);
+ if(install == 0) {
+ continue;
+ }
+ }
+
+ /* try adding pkg to transaction list (and run it through all
+ * checks - needed, ignored, ...) */
+ if(sync_target(i, alpm_pkg_get_name(pkg)) == -1) {
if(pm_errno == PM_ERR_TRANS_DUP_TARGET || pm_errno == PM_ERR_PKG_IGNORED) {
/* just skip duplicate or ignored targets */
continue;
@@ -288,7 +326,6 @@ static int sync_target(alpm_list_t *dbs_sync, char *target)
return(-1);
}
}
- known_pkgs = alpm_list_add(known_pkgs, pkg);
}
}
}
@@ -309,7 +346,7 @@ static int sync_target(alpm_list_t *dbs_sync, char *target)
* @param target the name of the sync target to add
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target)
+int SYMEXPORT alpm_sync_dbtarget(char *dbname, const char *target)
{
alpm_list_t *i;
alpm_list_t *dbs_sync;
@@ -340,7 +377,7 @@ int SYMEXPORT alpm_sync_dbtarget(char *dbname, char *target)
* @param target the name of the sync target to add
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
-int SYMEXPORT alpm_sync_target(char *target)
+int SYMEXPORT alpm_sync_target(const char *target)
{
alpm_list_t *dbs_sync;
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 32dafb5..b91358b 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -229,6 +229,16 @@ void cb_trans_evt(pmtransevt_t event, void *data1, void *data2)
case PM_TRANS_EVT_RETRIEVE_START:
printf(_(":: Retrieving packages from %s...\n"), (char*)data1);
break;
+ case PM_TRANS_EVT_PKG_NOT_FOUND:
+ printf(_("%s package not found, searching for group...\n"),
+ (char*)data1);
+ break;
+ case PM_TRANS_EVT_INSTALL_GROUP:
+ printf( _(":: group %s/%s:\n"),
+ (char*)alpm_db_get_name(data2),
+ (char*)alpm_grp_get_name(data1));
+ display_targets(alpm_grp_get_pkgs(data1), 2);
+ break;
/* all the simple done events, with fallthrough for each */
case PM_TRANS_EVT_FILECONFLICTS_DONE:
case PM_TRANS_EVT_CHECKDEPS_DONE:
@@ -309,6 +319,17 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
*response = yesno(_(":: File %s is corrupted. Do you want to delete it?"),
(char *)data1);
break;
+ case PM_TRANS_CONV_INSTALL_GROUP:
+ *response = yesno(_(":: Install whole content from group %s/%s?"),
+ alpm_db_get_name(data1),
+ alpm_grp_get_name(data2));
+ break;
+ case PM_TRANS_CONV_INSTALL_GROUPPKG:
+ *response = yesno(_(":: Install %s from group %s?"),
+ alpm_pkg_get_name(data1),
+ alpm_grp_get_name(data2));
+ break;
+
}
if(config->noask) {
if(config->ask & event) {
diff --git a/src/pacman/util.c b/src/pacman/util.c
index b0824cf..9ccda90 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -506,8 +506,9 @@ void list_display_linebreak(const char *title, const alpm_list_t *list)
}
}
}
-/* prepare a list of pkgs to display */
-void display_targets(const alpm_list_t *pkgs, int install)
+/* prepare a list of pkgs to display
+ * mode: 0=remove, 1=install, 2=group display */
+void display_targets(const alpm_list_t *pkgs, int mode)
{
char *str;
const alpm_list_t *i;
@@ -544,7 +545,7 @@ void display_targets(const alpm_list_t *pkgs, int install)
mbdlsize = dlsize / (1024.0 * 1024.0);
mbisize = isize / (1024.0 * 1024.0);
- if(install) {
+ if(mode == 1) {
asprintf(&str, _("Targets (%d):"), alpm_list_count(targets));
list_display(str, targets);
free(str);
@@ -554,6 +555,11 @@ void display_targets(const alpm_list_t *pkgs, int install)
if(!(config->flags & PM_TRANS_FLAG_DOWNLOADONLY)) {
printf(_("Total Installed Size: %.2f MB\n"), mbisize);
}
+ } else if(mode == 2) {
+ asprintf(&str, _("Members (%d):"), alpm_list_count(targets));
+ list_display(str, targets);
+ free(str);
+ printf("\n");
} else {
asprintf(&str, _("Remove (%d):"), alpm_list_count(targets));
list_display(str, targets);
--
1.7.3
More information about the pacman-dev
mailing list