diff --git a/doc/pacman.8.asciidoc b/doc/pacman.8.asciidoc index bb205627..b91584ee 100644 --- a/doc/pacman.8.asciidoc +++ b/doc/pacman.8.asciidoc @@ -256,6 +256,12 @@ Upgrade Options (apply to '-S' and '-U')[[UO]] as explicitly installed so it will not be removed by the '\--recursive' remove operation. +*\--note*:: + Add an install note to packages. This will only apply to targets explicitly + listed and not their dependencies. The note can be used to keep track of why + a package was installed or any other info of note. The note can later be + edited or removed with '\--D \--note' or '\--D \--rmnote' respectively. + *\--ignore* :: Directs pacman to ignore upgrades of package even if there is one available. Multiple packages can be specified by separating them @@ -468,6 +474,13 @@ Database Options (apply to '-D')[[QO]] package installed even when it was initially installed as a dependency of another package. +*\--note*:: + Add or edit a package's install note. The note can be used to keep track of why + a package was installed or any other info of note. + +*\--rmnote*:: + Remove a package's install note. + *-k, \--check*:: Check the local package database is internally consistent. This will check all required files are present and that installed packages have diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 12fee64c..acf9ca71 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -155,6 +155,7 @@ int config_free(config_t *oldconfig) free(oldconfig->dbpath); free(oldconfig->logfile); free(oldconfig->gpgdir); + free(oldconfig->note); FREELIST(oldconfig->hookdirs); FREELIST(oldconfig->cachedirs); free(oldconfig->xfercommand); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 04350d39..f7bbafbd 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -99,6 +99,8 @@ typedef struct __config_t { unsigned int ask; /* Bitfield of alpm_transflag_t */ int flags; + char *note; + int rmnote; /* Bitfields of alpm_siglevel_t */ int siglevel; int localfilesiglevel; @@ -170,6 +172,8 @@ enum { OP_IGNOREGROUP, OP_NEEDED, OP_ASEXPLICIT, + OP_NOTE, + OP_RMNOTE, OP_ARCH, OP_PRINTFORMAT, OP_GPGDIR, diff --git a/src/pacman/database.c b/src/pacman/database.c index 17a9c273..340f3a56 100644 --- a/src/pacman/database.c +++ b/src/pacman/database.c @@ -38,11 +38,12 @@ * * @return 0 on success, 1 on failure */ -static int change_install_reason(alpm_list_t *targets) +static int change_pkg(alpm_list_t *targets) { alpm_list_t *i; alpm_db_t *db_local; int ret = 0; + int set_reason = 0; alpm_pkgreason_t reason; @@ -53,11 +54,10 @@ static int change_install_reason(alpm_list_t *targets) if(config->flags & ALPM_TRANS_FLAG_ALLDEPS) { /* --asdeps */ reason = ALPM_PKG_REASON_DEPEND; + set_reason = 1; } else if(config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT) { /* --asexplicit */ reason = ALPM_PKG_REASON_EXPLICIT; - } else { - pm_printf(ALPM_LOG_ERROR, _("no install reason specified (use -h for help)\n")); - return 1; + set_reason = 1; } /* Lock database */ @@ -69,19 +69,46 @@ static int change_install_reason(alpm_list_t *targets) for(i = targets; i; i = alpm_list_next(i)) { char *pkgname = i->data; alpm_pkg_t *pkg = alpm_db_get_pkg(db_local, pkgname); - if(!pkg || alpm_pkg_set_reason(pkg, reason)) { - pm_printf(ALPM_LOG_ERROR, _("could not set install reason for package %s (%s)\n"), - pkgname, alpm_strerror(alpm_errno(config->handle))); + + if(!pkg) { + pm_printf(ALPM_LOG_ERROR, _("package '%s' was not found"), pkgname); ret = 1; - } else { - if(!config->quiet) { - if(reason == ALPM_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); + continue; + } + + if(set_reason) { + if(alpm_pkg_set_reason(pkg, reason)) { + pm_printf(ALPM_LOG_ERROR, _("could not set install reason for package %s (%s)\n"), + pkgname, alpm_strerror(alpm_errno(config->handle))); + ret = 1; + } else { + if(!config->quiet) { + if(reason == ALPM_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); + } } } } + + if(config->rmnote) { + if(alpm_pkg_set_note(pkg, NULL)) { + pm_printf(ALPM_LOG_ERROR, _("could not set install note for package %s (%s)\n"), + pkgname, alpm_strerror(alpm_errno(config->handle))); + ret = 1; + } else if(!config->quiet) { + printf(_("%s: note removed\n"), pkgname); + } + } else if(config->note) { + if(alpm_pkg_set_note(pkg, config->note)) { + pm_printf(ALPM_LOG_ERROR, _("could not set install note for package %s (%s)\n"), + pkgname, alpm_strerror(alpm_errno(config->handle))); + ret = 1; + } else if(!config->quiet) { + printf(_("%s: note set\n"), pkgname); + } + } } /* Unlock database */ @@ -296,8 +323,9 @@ int pacman_database(alpm_list_t *targets) } } - if(config->flags & (ALPM_TRANS_FLAG_ALLDEPS | ALPM_TRANS_FLAG_ALLEXPLICIT)) { - ret = change_install_reason(targets); + if(config->note || config->rmnote || + (config->flags & (ALPM_TRANS_FLAG_ALLDEPS | ALPM_TRANS_FLAG_ALLEXPLICIT))) { + ret = change_pkg(targets); } return ret; diff --git a/src/pacman/package.c b/src/pacman/package.c index eaee3bb0..8e33d2bd 100644 --- a/src/pacman/package.c +++ b/src/pacman/package.c @@ -70,6 +70,7 @@ enum { T_URL, T_VALIDATED_BY, T_VERSION, + T_NOTE, /* the following is a sentinel and should remain in last position */ _T_MAX }; @@ -124,6 +125,7 @@ static void make_aligned_titles(void) buf[T_URL] = _("URL"); buf[T_VALIDATED_BY] = _("Validated By"); buf[T_VERSION] = _("Version"); + buf[T_NOTE] = _("Note"); for(i = 0; i < ARRAYSIZE(wbuf); i++) { wlen[i] = mbstowcs(wbuf[i], buf[i], strlen(buf[i]) + 1); @@ -301,6 +303,7 @@ void dump_pkg_full(alpm_pkg_t *pkg, int extra) if(from == ALPM_PKG_FROM_LOCALDB) { string_display(titles[T_INSTALL_DATE], idatestr, cols); string_display(titles[T_INSTALL_REASON], reason, cols); + string_display(titles[T_NOTE], alpm_pkg_get_note(pkg), cols); } if(from == ALPM_PKG_FROM_FILE || from == ALPM_PKG_FROM_LOCALDB) { string_display(titles[T_INSTALL_SCRIPT], diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c index db64e05a..beab709c 100644 --- a/src/pacman/pacman.c +++ b/src/pacman/pacman.c @@ -169,6 +169,8 @@ static void usage(int op, const char * const myname) printf("%s:\n", str_opt); addlist(_(" --asdeps mark packages as non-explicitly installed\n")); addlist(_(" --asexplicit mark packages as explicitly installed\n")); + addlist(_(" --note add or edit a packages install notes\n")); + addlist(_(" --rmnote remove install note from packages\n")); addlist(_(" -k, --check test local database for validity (-kk for sync databases)\n")); addlist(_(" -q, --quiet suppress output of success messages\n")); } else if(op == PM_OP_DEPTEST) { @@ -193,6 +195,7 @@ static void usage(int op, const char * const myname) " overwrite conflicting files (can be used more than once)\n")); addlist(_(" --asdeps install packages as non-explicitly installed\n")); addlist(_(" --asexplicit install packages as explicitly installed\n")); + addlist(_(" --note add an install note to packages\n")); addlist(_(" --ignore ignore a package upgrade (can be used more than once)\n")); addlist(_(" --ignoregroup \n" " ignore a group upgrade (can be used more than once)\n")); @@ -481,6 +484,12 @@ static int parsearg_database(int opt) case OP_ASEXPLICIT: config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT; break; + case OP_NOTE: + config->note = strdup(optarg); + break; + case OP_RMNOTE: + config->rmnote = 1; + break; case OP_CHECK: case 'k': (config->op_q_check)++; @@ -501,7 +510,11 @@ static void checkargs_database(void) && config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT, "--asdeps", "--asexplicit"); + invalid_opt(config->note && config->rmnote, "--note", "--rmnote"); + if(config->op_q_check) { + invalid_opt(config->note != NULL, "--note", "--check"); + invalid_opt(config->rmnote, "--rmnote", "--check"); invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLDEPS, "--asdeps", "--check"); invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT, @@ -728,6 +741,9 @@ static int parsearg_upgrade(int opt) case OP_ASEXPLICIT: config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT; break; + case OP_NOTE: + config->note = strdup(optarg); + break; case OP_NEEDED: config->flags |= ALPM_TRANS_FLAG_NEEDED; break; @@ -942,6 +958,8 @@ static int parseargs(int argc, char *argv[]) {"ignoregroup", required_argument, 0, OP_IGNOREGROUP}, {"needed", no_argument, 0, OP_NEEDED}, {"asexplicit", no_argument, 0, OP_ASEXPLICIT}, + {"note", required_argument, 0, OP_NOTE}, + {"rmnote", no_argument, 0, OP_RMNOTE}, {"arch", required_argument, 0, OP_ARCH}, {"print-format", required_argument, 0, OP_PRINTFORMAT}, {"gpgdir", required_argument, 0, OP_GPGDIR}, diff --git a/src/pacman/query.c b/src/pacman/query.c index e3e7d844..f28c0f89 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -329,9 +329,15 @@ static int display(alpm_pkg_t *pkg) && !config->op_q_changelog && !config->op_q_check) { if(!config->quiet) { const colstr_t *colstr = &config->colstr; + char *note = alpm_pkg_get_note(pkg); + printf("%s%s %s%s%s", colstr->title, alpm_pkg_get_name(pkg), colstr->version, alpm_pkg_get_version(pkg), colstr->nocolor); + if(note) { + printf(" (%s)", note); + } + if(config->op_q_upgrade) { int usage; alpm_pkg_t *newpkg = alpm_sync_get_new_version(pkg, alpm_get_syncdbs(config->handle)); diff --git a/src/pacman/util.c b/src/pacman/util.c index 5486e7a5..cfcd618c 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -72,6 +72,15 @@ int trans_init(int flags, int check_valid) trans_init_error(); return -1; } + + if(config->note) { + ret = alpm_trans_set_note(config->handle, config->note); + if(ret == -1) { + trans_init_error(); + return -1; + } + } + return 0; }