Merge branch 'morganamilo/notes' into morganamilo/tip

This commit is contained in:
morganamilo 2021-11-06 23:41:15 +00:00
commit 2200dd8797
No known key found for this signature in database
GPG key ID: E48D0A8326DE47C5
25 changed files with 291 additions and 17 deletions

View file

@ -261,6 +261,12 @@ Upgrade Options (apply to '-S' and '-U')[[UO]]
as explicitly installed so it will not be removed by the '\--recursive' as explicitly installed so it will not be removed by the '\--recursive'
remove operation. 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* <package>:: *\--ignore* <package>::
Directs pacman to ignore upgrades of package even if there is one Directs pacman to ignore upgrades of package even if there is one
available. Multiple packages can be specified by separating them available. Multiple packages can be specified by separating them
@ -471,6 +477,13 @@ Database Options (apply to '-D')[[QO]]
package installed even when it was initially installed as a dependency package installed even when it was initially installed as a dependency
of another package. 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*:: *-k, \--check*::
Check the local package database is internally consistent. This will Check the local package database is internally consistent. This will
check all required files are present and that installed packages have check all required files are present and that installed packages have

View file

@ -431,8 +431,22 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
ASSERT(trans != NULL, return -1); ASSERT(trans != NULL, return -1);
if(_alpm_db_get_pkgfromcache(db, newpkg->name)) {
oldpkg = newpkg->oldpkg;
}
/* set note on package only if it was explicitly added to transaction */
if(trans->note && newpkg->reason == ALPM_PKG_REASON_EXPLICIT) {
STRDUP(newpkg->note, trans->note,
RET_ERR(handle, ALPM_ERR_MEMORY, -1));
} else if(oldpkg && oldpkg->note) {
STRDUP(newpkg->note,oldpkg->note,
RET_ERR(handle, ALPM_ERR_MEMORY, -1));
}
if(oldpkg) {
/* see if this is an upgrade. if so, remove the old package first */ /* see if this is an upgrade. if so, remove the old package first */
if(_alpm_db_get_pkgfromcache(db, newpkg->name) && (oldpkg = newpkg->oldpkg)) {
int cmp = _alpm_pkg_compare_versions(newpkg, oldpkg); int cmp = _alpm_pkg_compare_versions(newpkg, oldpkg);
if(cmp < 0) { if(cmp < 0) {
log_msg = "downgrading"; log_msg = "downgrading";

View file

@ -2473,6 +2473,12 @@ const char *alpm_pkg_get_desc(alpm_pkg_t *pkg);
*/ */
const char *alpm_pkg_get_url(alpm_pkg_t *pkg); const char *alpm_pkg_get_url(alpm_pkg_t *pkg);
/** Returns the package note.
* @param pkg a pointer to package
* @return a reference to an internal string
*/
char *alpm_pkg_get_note(alpm_pkg_t *pkg);
/** Returns the build timestamp of the package. /** Returns the build timestamp of the package.
* @param pkg a pointer to package * @param pkg a pointer to package
* @return the timestamp of the build time * @return the timestamp of the build time
@ -2651,6 +2657,15 @@ off_t alpm_pkg_download_size(alpm_pkg_t *newpkg);
*/ */
int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason); int alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason);
/** Set install note for a package in the local database.
* The provided package object must be from the local database or this method
* will fail. The write to the local database is performed immediately.
* @param pkg the package to edit
* @param note the new install note, null to remove a note
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int alpm_pkg_set_note(alpm_pkg_t *pkg, char *note);
/* End of libalpm_pkg_t accessors */ /* End of libalpm_pkg_t accessors */
/** @} */ /** @} */
@ -2800,6 +2815,16 @@ alpm_list_t *alpm_trans_get_add(alpm_handle_t *handle);
*/ */
alpm_list_t *alpm_trans_get_remove(alpm_handle_t *handle); alpm_list_t *alpm_trans_get_remove(alpm_handle_t *handle);
/** Sets the install note for a transaction
*
* All target packages will gain the note, dependencies will not.
*
* @param handle the context handle
* @note the the note, may not contain new lines
* @return 0 on success, -1 on error (pm_errno is set accordingly)
*/
int alpm_trans_set_note(alpm_handle_t *handle, char *note);
/** Initialize the transaction. /** Initialize the transaction.
* @param handle the context handle * @param handle the context handle
* @param flags flags of the transaction (like nodeps, etc; see alpm_transflag_t) * @param flags flags of the transaction (like nodeps, etc; see alpm_transflag_t)

View file

@ -81,6 +81,12 @@ static const char *_cache_get_url(alpm_pkg_t *pkg)
return pkg->url; return pkg->url;
} }
static char *_cache_get_note(alpm_pkg_t *pkg)
{
LAZY_LOAD(INFRQ_DESC);
return pkg->note;
}
static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg) static alpm_time_t _cache_get_builddate(alpm_pkg_t *pkg)
{ {
LAZY_LOAD(INFRQ_DESC); LAZY_LOAD(INFRQ_DESC);
@ -330,6 +336,7 @@ static const struct pkg_operations local_pkg_ops = {
.get_base = _cache_get_base, .get_base = _cache_get_base,
.get_desc = _cache_get_desc, .get_desc = _cache_get_desc,
.get_url = _cache_get_url, .get_url = _cache_get_url,
.get_note = _cache_get_note,
.get_builddate = _cache_get_builddate, .get_builddate = _cache_get_builddate,
.get_installdate = _cache_get_installdate, .get_installdate = _cache_get_installdate,
.get_packager = _cache_get_packager, .get_packager = _cache_get_packager,
@ -752,6 +759,8 @@ static int local_db_read(alpm_pkg_t *info, int inforeq)
READ_AND_STORE_ALL(info->groups); READ_AND_STORE_ALL(info->groups);
} else if(strcmp(line, "%URL%") == 0) { } else if(strcmp(line, "%URL%") == 0) {
READ_AND_STORE(info->url); READ_AND_STORE(info->url);
} else if(strcmp(line, "%NOTE%") == 0) {
READ_AND_STORE(info->note);
} else if(strcmp(line, "%LICENSE%") == 0) { } else if(strcmp(line, "%LICENSE%") == 0) {
READ_AND_STORE_ALL(info->licenses); READ_AND_STORE_ALL(info->licenses);
} else if(strcmp(line, "%ARCH%") == 0) { } else if(strcmp(line, "%ARCH%") == 0) {
@ -1040,6 +1049,11 @@ int _alpm_local_db_write(alpm_db_t *db, alpm_pkg_t *info, int inforeq)
write_deps(fp, "%CONFLICTS%", info->conflicts); write_deps(fp, "%CONFLICTS%", info->conflicts);
write_deps(fp, "%PROVIDES%", info->provides); write_deps(fp, "%PROVIDES%", info->provides);
if(info->note) {
fprintf(fp, "%%NOTE%%\n"
"%s\n\n", info->note);
}
fclose(fp); fclose(fp);
fp = NULL; fp = NULL;
} }
@ -1158,6 +1172,31 @@ int SYMEXPORT alpm_pkg_set_reason(alpm_pkg_t *pkg, alpm_pkgreason_t reason)
return 0; return 0;
} }
int SYMEXPORT alpm_pkg_set_note(alpm_pkg_t *pkg, char *note)
{
ASSERT(pkg != NULL, return -1);
ASSERT(pkg->origin == ALPM_PKG_FROM_LOCALDB,
RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
ASSERT(pkg->origin_data.db == pkg->handle->db_local,
RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
_alpm_log(pkg->handle, ALPM_LOG_DEBUG,
"setting note for %s: %s\n", pkg->name, note);
LAZY_LOAD(INFRQ_DESC);
FREE(pkg->note);
if(note) {
ASSERT(!strchr(note, '\n'), RET_ERR(pkg->handle, ALPM_ERR_WRONG_ARGS, -1));
STRDUP(pkg->note, note,
RET_ERR(pkg->handle, ALPM_ERR_MEMORY, -1));
}
/* write DESC */
if(_alpm_local_db_write(pkg->handle->db_local, pkg, INFRQ_DESC)) {
RET_ERR(pkg->handle, ALPM_ERR_DB_WRITE, -1);
}
return 0;
}
static const struct db_operations local_db_ops = { static const struct db_operations local_db_ops = {
.validate = local_db_validate, .validate = local_db_validate,
.populate = local_db_populate, .populate = local_db_populate,

View file

@ -405,6 +405,7 @@ int _alpm_db_search(alpm_db_t *db, const alpm_list_t *needles,
const char *matched = NULL; const char *matched = NULL;
const char *name = pkg->name; const char *name = pkg->name;
const char *desc = alpm_pkg_get_desc(pkg); const char *desc = alpm_pkg_get_desc(pkg);
const char *note = alpm_pkg_get_note(pkg);
/* check name as regex AND as plain text */ /* check name as regex AND as plain text */
if(name && (regexec(&reg, name, 0, 0, 0) == 0 || strstr(name, targ))) { if(name && (regexec(&reg, name, 0, 0, 0) == 0 || strstr(name, targ))) {
@ -414,6 +415,11 @@ int _alpm_db_search(alpm_db_t *db, const alpm_list_t *needles,
else if(desc && regexec(&reg, desc, 0, 0, 0) == 0) { else if(desc && regexec(&reg, desc, 0, 0, 0) == 0) {
matched = desc; matched = desc;
} }
/* check note */
else if(note && regexec(&reg, note, 0, 0, 0) == 0) {
matched = note;
}
/* TODO: should we be doing this, and should we print something /* TODO: should we be doing this, and should we print something
* differently when we do match it since it isn't currently printed? */ * differently when we do match it since it isn't currently printed? */
if(!matched) { if(!matched) {

View file

@ -78,6 +78,7 @@ int SYMEXPORT alpm_pkg_checkmd5sum(alpm_pkg_t *pkg)
static const char *_pkg_get_base(alpm_pkg_t *pkg) { return pkg->base; } static const char *_pkg_get_base(alpm_pkg_t *pkg) { return pkg->base; }
static const char *_pkg_get_desc(alpm_pkg_t *pkg) { return pkg->desc; } static const char *_pkg_get_desc(alpm_pkg_t *pkg) { return pkg->desc; }
static const char *_pkg_get_url(alpm_pkg_t *pkg) { return pkg->url; } static const char *_pkg_get_url(alpm_pkg_t *pkg) { return pkg->url; }
static char *_pkg_get_note(alpm_pkg_t *pkg) { return pkg->note; }
static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; } static alpm_time_t _pkg_get_builddate(alpm_pkg_t *pkg) { return pkg->builddate; }
static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; } static alpm_time_t _pkg_get_installdate(alpm_pkg_t *pkg) { return pkg->installdate; }
static const char *_pkg_get_packager(alpm_pkg_t *pkg) { return pkg->packager; } static const char *_pkg_get_packager(alpm_pkg_t *pkg) { return pkg->packager; }
@ -143,6 +144,7 @@ const struct pkg_operations default_pkg_ops = {
.get_base = _pkg_get_base, .get_base = _pkg_get_base,
.get_desc = _pkg_get_desc, .get_desc = _pkg_get_desc,
.get_url = _pkg_get_url, .get_url = _pkg_get_url,
.get_note = _pkg_get_note,
.get_builddate = _pkg_get_builddate, .get_builddate = _pkg_get_builddate,
.get_installdate = _pkg_get_installdate, .get_installdate = _pkg_get_installdate,
.get_packager = _pkg_get_packager, .get_packager = _pkg_get_packager,
@ -227,6 +229,13 @@ const char SYMEXPORT *alpm_pkg_get_url(alpm_pkg_t *pkg)
return pkg->ops->get_url(pkg); return pkg->ops->get_url(pkg);
} }
char SYMEXPORT *alpm_pkg_get_note(alpm_pkg_t *pkg)
{
ASSERT(pkg != NULL, return NULL);
pkg->handle->pm_errno = ALPM_ERR_OK;
return pkg->ops->get_note(pkg);
}
alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg) alpm_time_t SYMEXPORT alpm_pkg_get_builddate(alpm_pkg_t *pkg)
{ {
ASSERT(pkg != NULL, return -1); ASSERT(pkg != NULL, return -1);
@ -611,6 +620,7 @@ int _alpm_pkg_dup(alpm_pkg_t *pkg, alpm_pkg_t **new_ptr)
STRDUP(newpkg->version, pkg->version, goto cleanup); STRDUP(newpkg->version, pkg->version, goto cleanup);
STRDUP(newpkg->desc, pkg->desc, goto cleanup); STRDUP(newpkg->desc, pkg->desc, goto cleanup);
STRDUP(newpkg->url, pkg->url, goto cleanup); STRDUP(newpkg->url, pkg->url, goto cleanup);
STRDUP(newpkg->note, pkg->note, goto cleanup);
newpkg->builddate = pkg->builddate; newpkg->builddate = pkg->builddate;
newpkg->installdate = pkg->installdate; newpkg->installdate = pkg->installdate;
STRDUP(newpkg->packager, pkg->packager, goto cleanup); STRDUP(newpkg->packager, pkg->packager, goto cleanup);
@ -684,6 +694,7 @@ void _alpm_pkg_free(alpm_pkg_t *pkg)
FREE(pkg->version); FREE(pkg->version);
FREE(pkg->desc); FREE(pkg->desc);
FREE(pkg->url); FREE(pkg->url);
FREE(pkg->note);
FREE(pkg->packager); FREE(pkg->packager);
FREE(pkg->md5sum); FREE(pkg->md5sum);
FREE(pkg->sha256sum); FREE(pkg->sha256sum);

View file

@ -46,6 +46,7 @@ struct pkg_operations {
const char *(*get_base) (alpm_pkg_t *); const char *(*get_base) (alpm_pkg_t *);
const char *(*get_desc) (alpm_pkg_t *); const char *(*get_desc) (alpm_pkg_t *);
const char *(*get_url) (alpm_pkg_t *); const char *(*get_url) (alpm_pkg_t *);
char *(*get_note) (alpm_pkg_t *);
alpm_time_t (*get_builddate) (alpm_pkg_t *); alpm_time_t (*get_builddate) (alpm_pkg_t *);
alpm_time_t (*get_installdate) (alpm_pkg_t *); alpm_time_t (*get_installdate) (alpm_pkg_t *);
const char *(*get_packager) (alpm_pkg_t *); const char *(*get_packager) (alpm_pkg_t *);
@ -93,6 +94,7 @@ struct _alpm_pkg_t {
char *version; char *version;
char *desc; char *desc;
char *url; char *url;
char *note;
char *packager; char *packager;
char *md5sum; char *md5sum;
char *sha256sum; char *sha256sum;

View file

@ -299,6 +299,7 @@ void _alpm_trans_free(alpm_trans_t *trans)
alpm_list_free(trans->add); alpm_list_free(trans->add);
alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free); alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free);
alpm_list_free(trans->remove); alpm_list_free(trans->remove);
FREE(trans->note);
FREELIST(trans->skip_remove); FREELIST(trans->skip_remove);
@ -451,3 +452,19 @@ alpm_list_t SYMEXPORT *alpm_trans_get_remove(alpm_handle_t *handle)
return handle->trans->remove; return handle->trans->remove;
} }
int SYMEXPORT alpm_trans_set_note(alpm_handle_t *handle, char *note) {
CHECK_HANDLE(handle, return -1);
ASSERT(handle->trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1));
ASSERT(handle->trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1));
if(handle->trans->note) {
ASSERT(!strchr(handle->trans->note, '\n'), RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1));
free(handle->trans->note);
handle->trans->note = NULL;
}
STRDUP(handle->trans->note, note, RET_ERR(handle, ALPM_ERR_MEMORY, -1));
return 0;
}

View file

@ -39,6 +39,7 @@ typedef enum _alpm_transstate_t {
typedef struct _alpm_trans_t { typedef struct _alpm_trans_t {
/* bitfield of alpm_transflag_t flags */ /* bitfield of alpm_transflag_t flags */
int flags; int flags;
char *note;
alpm_transstate_t state; alpm_transstate_t state;
alpm_list_t *unresolvable; /* list of (alpm_pkg_t *) */ alpm_list_t *unresolvable; /* list of (alpm_pkg_t *) */
alpm_list_t *add; /* list of (alpm_pkg_t *) */ alpm_list_t *add; /* list of (alpm_pkg_t *) */

View file

@ -155,6 +155,7 @@ int config_free(config_t *oldconfig)
free(oldconfig->dbpath); free(oldconfig->dbpath);
free(oldconfig->logfile); free(oldconfig->logfile);
free(oldconfig->gpgdir); free(oldconfig->gpgdir);
free(oldconfig->note);
FREELIST(oldconfig->hookdirs); FREELIST(oldconfig->hookdirs);
FREELIST(oldconfig->cachedirs); FREELIST(oldconfig->cachedirs);
free(oldconfig->xfercommand); free(oldconfig->xfercommand);

View file

@ -99,6 +99,8 @@ typedef struct __config_t {
unsigned int ask; unsigned int ask;
/* Bitfield of alpm_transflag_t */ /* Bitfield of alpm_transflag_t */
int flags; int flags;
char *note;
int rmnote;
/* Bitfields of alpm_siglevel_t */ /* Bitfields of alpm_siglevel_t */
int siglevel; int siglevel;
int localfilesiglevel; int localfilesiglevel;
@ -171,6 +173,8 @@ enum {
OP_NEEDED, OP_NEEDED,
OP_NOKEEP, OP_NOKEEP,
OP_ASEXPLICIT, OP_ASEXPLICIT,
OP_NOTE,
OP_RMNOTE,
OP_ARCH, OP_ARCH,
OP_PRINTFORMAT, OP_PRINTFORMAT,
OP_GPGDIR, OP_GPGDIR,

View file

@ -38,11 +38,12 @@
* *
* @return 0 on success, 1 on failure * @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_list_t *i;
alpm_db_t *db_local; alpm_db_t *db_local;
int ret = 0; int ret = 0;
int set_reason = 0;
alpm_pkgreason_t reason; 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 */ if(config->flags & ALPM_TRANS_FLAG_ALLDEPS) { /* --asdeps */
reason = ALPM_PKG_REASON_DEPEND; reason = ALPM_PKG_REASON_DEPEND;
set_reason = 1;
} else if(config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT) { /* --asexplicit */ } else if(config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT) { /* --asexplicit */
reason = ALPM_PKG_REASON_EXPLICIT; reason = ALPM_PKG_REASON_EXPLICIT;
} else { set_reason = 1;
pm_printf(ALPM_LOG_ERROR, _("no install reason specified (use -h for help)\n"));
return 1;
} }
/* Lock database */ /* Lock database */
@ -69,19 +69,46 @@ static int change_install_reason(alpm_list_t *targets)
for(i = targets; i; i = alpm_list_next(i)) { for(i = targets; i; i = alpm_list_next(i)) {
char *pkgname = i->data; char *pkgname = i->data;
alpm_pkg_t *pkg = alpm_db_get_pkg(db_local, pkgname); 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"), if(!pkg) {
pkgname, alpm_strerror(alpm_errno(config->handle))); pm_printf(ALPM_LOG_ERROR, _("package '%s' was not found"), pkgname);
ret = 1; ret = 1;
} else { continue;
if(!config->quiet) { }
if(reason == ALPM_PKG_REASON_DEPEND) {
printf(_("%s: install reason has been set to 'installed as dependency'\n"), pkgname); if(set_reason) {
} else { if(alpm_pkg_set_reason(pkg, reason)) {
printf(_("%s: install reason has been set to 'explicitly installed'\n"), pkgname); 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 */ /* Unlock database */
@ -296,8 +323,9 @@ int pacman_database(alpm_list_t *targets)
} }
} }
if(config->flags & (ALPM_TRANS_FLAG_ALLDEPS | ALPM_TRANS_FLAG_ALLEXPLICIT)) { if(config->note || config->rmnote ||
ret = change_install_reason(targets); (config->flags & (ALPM_TRANS_FLAG_ALLDEPS | ALPM_TRANS_FLAG_ALLEXPLICIT))) {
ret = change_pkg(targets);
} }
return ret; return ret;

View file

@ -70,6 +70,7 @@ enum {
T_URL, T_URL,
T_VALIDATED_BY, T_VALIDATED_BY,
T_VERSION, T_VERSION,
T_NOTE,
/* the following is a sentinel and should remain in last position */ /* the following is a sentinel and should remain in last position */
_T_MAX _T_MAX
}; };
@ -124,6 +125,7 @@ static void make_aligned_titles(void)
buf[T_URL] = _("URL"); buf[T_URL] = _("URL");
buf[T_VALIDATED_BY] = _("Validated By"); buf[T_VALIDATED_BY] = _("Validated By");
buf[T_VERSION] = _("Version"); buf[T_VERSION] = _("Version");
buf[T_NOTE] = _("Note");
for(i = 0; i < ARRAYSIZE(wbuf); i++) { for(i = 0; i < ARRAYSIZE(wbuf); i++) {
wlen[i] = mbstowcs(wbuf[i], buf[i], strlen(buf[i]) + 1); 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) { if(from == ALPM_PKG_FROM_LOCALDB) {
string_display(titles[T_INSTALL_DATE], idatestr, cols); string_display(titles[T_INSTALL_DATE], idatestr, cols);
string_display(titles[T_INSTALL_REASON], reason, 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) { if(from == ALPM_PKG_FROM_FILE || from == ALPM_PKG_FROM_LOCALDB) {
string_display(titles[T_INSTALL_SCRIPT], string_display(titles[T_INSTALL_SCRIPT],

View file

@ -169,6 +169,8 @@ static void usage(int op, const char * const myname)
printf("%s:\n", str_opt); printf("%s:\n", str_opt);
addlist(_(" --asdeps mark packages as non-explicitly installed\n")); addlist(_(" --asdeps mark packages as non-explicitly installed\n"));
addlist(_(" --asexplicit mark packages as explicitly installed\n")); addlist(_(" --asexplicit mark packages as explicitly installed\n"));
addlist(_(" --note <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(_(" -k, --check test local database for validity (-kk for sync databases)\n"));
addlist(_(" -q, --quiet suppress output of success messages\n")); addlist(_(" -q, --quiet suppress output of success messages\n"));
} else if(op == PM_OP_DEPTEST) { } 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")); " overwrite conflicting files (can be used more than once)\n"));
addlist(_(" --asdeps install packages as non-explicitly installed\n")); addlist(_(" --asdeps install packages as non-explicitly installed\n"));
addlist(_(" --asexplicit install packages as explicitly installed\n")); addlist(_(" --asexplicit install packages as explicitly installed\n"));
addlist(_(" --note <note> add an install note to packages\n"));
addlist(_(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n")); addlist(_(" --ignore <pkg> ignore a package upgrade (can be used more than once)\n"));
addlist(_(" --ignoregroup <grp>\n" addlist(_(" --ignoregroup <grp>\n"
" ignore a group upgrade (can be used more than once)\n")); " ignore a group upgrade (can be used more than once)\n"));
@ -482,6 +485,12 @@ static int parsearg_database(int opt)
case OP_ASEXPLICIT: case OP_ASEXPLICIT:
config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT; config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT;
break; break;
case OP_NOTE:
config->note = strdup(optarg);
break;
case OP_RMNOTE:
config->rmnote = 1;
break;
case OP_CHECK: case OP_CHECK:
case 'k': case 'k':
(config->op_q_check)++; (config->op_q_check)++;
@ -502,7 +511,11 @@ static void checkargs_database(void)
&& config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT, && config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT,
"--asdeps", "--asexplicit"); "--asdeps", "--asexplicit");
invalid_opt(config->note && config->rmnote, "--note", "--rmnote");
if(config->op_q_check) { 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, invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLDEPS,
"--asdeps", "--check"); "--asdeps", "--check");
invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT, invalid_opt(config->flags & ALPM_TRANS_FLAG_ALLEXPLICIT,
@ -730,6 +743,9 @@ static int parsearg_upgrade(int opt)
case OP_ASEXPLICIT: case OP_ASEXPLICIT:
config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT; config->flags |= ALPM_TRANS_FLAG_ALLEXPLICIT;
break; break;
case OP_NOTE:
config->note = strdup(optarg);
break;
case OP_NEEDED: case OP_NEEDED:
config->flags |= ALPM_TRANS_FLAG_NEEDED; config->flags |= ALPM_TRANS_FLAG_NEEDED;
break; break;
@ -948,6 +964,8 @@ static int parseargs(int argc, char *argv[])
{"needed", no_argument, 0, OP_NEEDED}, {"needed", no_argument, 0, OP_NEEDED},
{"nokeep", no_argument, 0, OP_NOKEEP}, {"nokeep", no_argument, 0, OP_NOKEEP},
{"asexplicit", no_argument, 0, OP_ASEXPLICIT}, {"asexplicit", no_argument, 0, OP_ASEXPLICIT},
{"note", required_argument, 0, OP_NOTE},
{"rmnote", no_argument, 0, OP_RMNOTE},
{"arch", required_argument, 0, OP_ARCH}, {"arch", required_argument, 0, OP_ARCH},
{"print-format", required_argument, 0, OP_PRINTFORMAT}, {"print-format", required_argument, 0, OP_PRINTFORMAT},
{"gpgdir", required_argument, 0, OP_GPGDIR}, {"gpgdir", required_argument, 0, OP_GPGDIR},

View file

@ -329,9 +329,15 @@ static int display(alpm_pkg_t *pkg)
&& !config->op_q_changelog && !config->op_q_check) { && !config->op_q_changelog && !config->op_q_check) {
if(!config->quiet) { if(!config->quiet) {
const colstr_t *colstr = &config->colstr; 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), printf("%s%s %s%s%s", colstr->title, alpm_pkg_get_name(pkg),
colstr->version, alpm_pkg_get_version(pkg), colstr->nocolor); colstr->version, alpm_pkg_get_version(pkg), colstr->nocolor);
if(note) {
printf(" (%s)", note);
}
if(config->op_q_upgrade) { if(config->op_q_upgrade) {
int usage; int usage;
alpm_pkg_t *newpkg = alpm_sync_get_new_version(pkg, alpm_get_syncdbs(config->handle)); alpm_pkg_t *newpkg = alpm_sync_get_new_version(pkg, alpm_get_syncdbs(config->handle));

View file

@ -72,6 +72,15 @@ int trans_init(int flags, int check_valid)
trans_init_error(); trans_init_error();
return -1; return -1;
} }
if(config->note) {
ret = alpm_trans_set_note(config->handle, config->note);
if(ret == -1) {
trans_init_error();
return -1;
}
}
return 0; return 0;
} }

View file

@ -9,6 +9,8 @@ pacman_tests = [
'tests/config002.py', 'tests/config002.py',
'tests/database001.py', 'tests/database001.py',
'tests/database002.py', 'tests/database002.py',
'tests/database003.py',
'tests/database004.py',
'tests/database010.py', 'tests/database010.py',
'tests/database011.py', 'tests/database011.py',
'tests/database012.py', 'tests/database012.py',
@ -174,6 +176,7 @@ pacman_tests = [
'tests/symlink020.py', 'tests/symlink020.py',
'tests/symlink021.py', 'tests/symlink021.py',
'tests/sync-failover-404-with-body.py', 'tests/sync-failover-404-with-body.py',
'tests/sync-keep-note.py',
'tests/sync-install-assumeinstalled.py', 'tests/sync-install-assumeinstalled.py',
'tests/sync-nodepversion01.py', 'tests/sync-nodepversion01.py',
'tests/sync-nodepversion02.py', 'tests/sync-nodepversion02.py',
@ -181,6 +184,7 @@ pacman_tests = [
'tests/sync-nodepversion04.py', 'tests/sync-nodepversion04.py',
'tests/sync-nodepversion05.py', 'tests/sync-nodepversion05.py',
'tests/sync-nodepversion06.py', 'tests/sync-nodepversion06.py',
'tests/sync-note-targets-only.py',
'tests/sync-sysupgrade-print-replaced-packages.py', 'tests/sync-sysupgrade-print-replaced-packages.py',
'tests/sync-update-assumeinstalled.py', 'tests/sync-update-assumeinstalled.py',
'tests/sync-update-package-removing-required-provides.py', 'tests/sync-update-package-removing-required-provides.py',

View file

@ -121,6 +121,8 @@ class pmdb(object):
pkg.groups = _getsection(fd) pkg.groups = _getsection(fd)
elif line == "%URL%": elif line == "%URL%":
pkg.url = fd.readline().strip("\n") pkg.url = fd.readline().strip("\n")
elif line == "%NOTE%":
pkg.note = fd.readline().strip("\n")
elif line == "%LICENSE%": elif line == "%LICENSE%":
pkg.license = _getsection(fd) pkg.license = _getsection(fd)
elif line == "%ARCH%": elif line == "%ARCH%":
@ -208,6 +210,7 @@ class pmdb(object):
make_section(data, "INSTALLDATE", pkg.installdate) make_section(data, "INSTALLDATE", pkg.installdate)
make_section(data, "SIZE", pkg.size) make_section(data, "SIZE", pkg.size)
make_section(data, "REASON", pkg.reason) make_section(data, "REASON", pkg.reason)
make_section(data, "NOTE", pkg.note)
else: else:
make_section(data, "FILENAME", pkg.filename()) make_section(data, "FILENAME", pkg.filename())
make_section(data, "REPLACES", pkg.replaces) make_section(data, "REPLACES", pkg.replaces)

View file

@ -34,6 +34,7 @@ class pmpkg(object):
self.desc = "" self.desc = ""
self.groups = [] self.groups = []
self.url = "" self.url = ""
self.note = ""
self.license = [] self.license = []
self.arch = "" self.arch = ""
self.builddate = "" self.builddate = ""
@ -71,6 +72,7 @@ class pmpkg(object):
s.append("url: %s" % self.url) s.append("url: %s" % self.url)
s.append("files: %s" % " ".join(self.files)) s.append("files: %s" % " ".join(self.files))
s.append("reason: %d" % self.reason) s.append("reason: %d" % self.reason)
s.append("note: %s" % self.note)
return "\n".join(s) return "\n".join(s)
def fullname(self): def fullname(self):

View file

@ -108,6 +108,9 @@ class pmrule(object):
if f.startswith(value + "\t"): if f.startswith(value + "\t"):
success = 1 success = 1
break; break;
elif case == "NOTE":
if newpkg.note != value:
success = 0
else: else:
tap.diag("PKG rule '%s' not found" % case) tap.diag("PKG rule '%s' not found" % case)
success = -1 success = -1

View file

@ -322,7 +322,7 @@ class pmtest(object):
self.result["success"] += 1 self.result["success"] += 1
else: else:
self.result["fail"] += 1 self.result["fail"] += 1
tap.ok(success, i) tap.ok(success == 1, i)
def configfile(self): def configfile(self):
return os.path.join(self.root, util.PACCONF) return os.path.join(self.root, util.PACCONF)

View file

@ -0,0 +1,10 @@
self.description = "-D --note :D"
lp = pmpkg("pkg")
self.addpkg2db("local", lp)
self.args = "-D pkg --note :D"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg")
self.addrule("PKG_NOTE=pkg|:D")

View file

@ -0,0 +1,11 @@
self.description = "-D --rmnote"
lp = pmpkg("pkg")
lp.note = "D:"
self.addpkg2db("local", lp)
self.args = "-D pkg --rmnote"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg")
self.addrule("PKG_NOTE=pkg|")

View file

@ -0,0 +1,14 @@
self.description = "Sync a package keeping the existing note"
sp = pmpkg("pkg")
self.addpkg2db("sync", sp)
lp = pmpkg("pkg")
lp.note = "this is a note"
self.addpkg2db("local", lp)
self.args = "-S pkg"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg")
self.addrule("PKG_NOTE=pkg|this is a note")

View file

@ -0,0 +1,30 @@
self.description = "Make sure note is only set for targets"
sp1 = pmpkg("pkg1", "1.0-2")
sp1.depends = ["pkg2"]
sp2 = pmpkg("pkg2")
sp3 = pmpkg("pkg3")
sp3.depends = ["pkg4"]
sp4 = pmpkg("pkg4")
for p in sp1, sp2, sp3, sp4:
self.addpkg2db("sync", p)
lp1 = pmpkg("pkg1")
self.addpkg2db("local", lp1)
self.args = "-S pkg1 pkg3 --note aaaa"
self.addrule("PACMAN_RETCODE=0")
self.addrule("PKG_EXIST=pkg1")
self.addrule("PKG_EXIST=pkg2")
self.addrule("PKG_EXIST=pkg3")
self.addrule("PKG_EXIST=pkg4")
self.addrule("PKG_NOTE=pkg1|aaaa")
self.addrule("PKG_NOTE=pkg2|")
self.addrule("PKG_NOTE=pkg3|aaaa")
self.addrule("PKG_NOTE=pkg4|")