Merge branch 'andrew/pformat' into 'master'
Draft: WIP: add python/rust style format strings See merge request pacman/pacman!41
This commit is contained in:
commit
b2fa9f466c
8 changed files with 500 additions and 0 deletions
|
@ -2987,6 +2987,9 @@ int alpm_sandbox_setup_child(alpm_handle_t *handle, const char *sandboxuser, con
|
|||
/* End of libalpm_api */
|
||||
/** @} */
|
||||
|
||||
size_t alpm_info_print_pkg(const char *format, alpm_pkg_t *pkg);
|
||||
size_t alpm_info_print_pkgs(const char *format, alpm_list_t *pkgs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
226
lib/libalpm/info.c
Normal file
226
lib/libalpm/info.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alpm.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "mfmt.h"
|
||||
|
||||
typedef enum field_t {
|
||||
FILENAME,
|
||||
NAME,
|
||||
BASE,
|
||||
DESCRIPTION,
|
||||
VERSION,
|
||||
ORIGIN,
|
||||
REASON,
|
||||
LICENSE,
|
||||
GROUP,
|
||||
|
||||
DEPENDS,
|
||||
OPTDEPENDS,
|
||||
CONFLICTS,
|
||||
PROVIDES,
|
||||
REPLACES,
|
||||
REQUIREDBY,
|
||||
|
||||
DELTAS,
|
||||
FILES,
|
||||
BACKUP,
|
||||
DB,
|
||||
VALIDATION,
|
||||
URL,
|
||||
BUILDDATE,
|
||||
INSTALLDATE,
|
||||
PACKAGER,
|
||||
MD5SUM,
|
||||
SHA256SUM,
|
||||
ARCH,
|
||||
SIZE,
|
||||
ISIZE,
|
||||
BASE64SIG,
|
||||
|
||||
UNKNOWN,
|
||||
} field_t;
|
||||
|
||||
static struct field_map_t {
|
||||
const char *input;
|
||||
field_t field;
|
||||
} field_map[] = {
|
||||
{"filename", FILENAME},
|
||||
{"name", NAME},
|
||||
{"base", BASE},
|
||||
{"description", DESCRIPTION},
|
||||
{"version", VERSION},
|
||||
|
||||
{"license", LICENSE},
|
||||
{"group", GROUP},
|
||||
{"groups", GROUP},
|
||||
|
||||
{"depends", DEPENDS},
|
||||
{"optdepends", OPTDEPENDS},
|
||||
{"conflicts", CONFLICTS},
|
||||
{"provides", PROVIDES},
|
||||
{"replaces", REPLACES},
|
||||
{"requiredby", REQUIREDBY},
|
||||
|
||||
{"url", URL},
|
||||
{"builddate", BUILDDATE},
|
||||
{"installdate", INSTALLDATE},
|
||||
{"packager", PACKAGER},
|
||||
{"md5sum", MD5SUM},
|
||||
{"sha256sum", SHA256SUM},
|
||||
{"arch", ARCH},
|
||||
{"size", SIZE},
|
||||
{"isize", ISIZE},
|
||||
{"base64sig", BASE64SIG},
|
||||
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
static char *_alpm_hr_size(off_t bytes, char *dest)
|
||||
{
|
||||
static const char *suff[] = {"B", "K", "M", "G", "T", "P", "E", NULL};
|
||||
float hrsize;
|
||||
int s = 0;
|
||||
while((bytes >= 1000000 || bytes <= -1000000) && suff[s + 1]) {
|
||||
bytes /= 1024;
|
||||
++s;
|
||||
}
|
||||
hrsize = bytes;
|
||||
if((hrsize >= 1000 || hrsize <= -1000) && suff[s + 1]) {
|
||||
hrsize /= 1024;
|
||||
++s;
|
||||
}
|
||||
sprintf(dest, "%.2f %s", hrsize, suff[s]);
|
||||
return dest;
|
||||
}
|
||||
|
||||
static field_t _alpm_info_lookup_field(const char *name) {
|
||||
struct field_map_t *m;
|
||||
for(m = field_map; m->input; m++) {
|
||||
if(strcmp(name, m->input) == 0) { return m->field; }
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
static size_t _alpm_info_print_str(mfmt_token_callback_t *t, const char *str, FILE *f) {
|
||||
return mfmt_render_str(t, str ? str : "NULL", f);
|
||||
}
|
||||
|
||||
static size_t _alpm_info_print_size(mfmt_token_callback_t *t, const off_t s, FILE *f) {
|
||||
if(s) {
|
||||
char hrsize[50];
|
||||
if(t->conversion == 'd') {
|
||||
snprintf(hrsize, 50, "%lld", (long long)s);
|
||||
} else {
|
||||
_alpm_hr_size(s, hrsize);
|
||||
}
|
||||
return mfmt_render_str(t, hrsize, f);
|
||||
} else {
|
||||
return mfmt_render_str(t, "NULL", f);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t _alpm_info_print_strlist(mfmt_token_callback_t *t, alpm_list_t *l, FILE *f) {
|
||||
if(l) {
|
||||
size_t len = 0;
|
||||
while(l) {
|
||||
len += mfmt_render_str(t, l->data, f) + 1;
|
||||
fputc('\n', f);
|
||||
l = l->next;
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
return mfmt_render_str(t, "NULL", f);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t _alpm_info_print_deplist(mfmt_token_callback_t *t, alpm_list_t *l, FILE *f) {
|
||||
if(l) {
|
||||
size_t len = 0;
|
||||
while(l) {
|
||||
char *s = alpm_dep_compute_string(l->data);
|
||||
len += mfmt_render_str(t, s, f) + 1;
|
||||
fputc('\n', f);
|
||||
l = l->next;
|
||||
free(s);
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
return mfmt_render_str(t, "NULL", f);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t _alpm_info_print_timestamp(mfmt_token_callback_t *t, const alpm_time_t s, FILE *f) {
|
||||
if(s) {
|
||||
char datestr[50] = "";
|
||||
if(strftime(datestr, 50, " %c", localtime(&s)) == 0) { return 0; }
|
||||
return mfmt_render_str(t, datestr + 1, f);
|
||||
} else {
|
||||
return mfmt_render_str(t, "NULL", f);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t _alpm_info_process_token(FILE *f, mfmt_token_callback_t *t, void *ctx, void *arg) {
|
||||
alpm_pkg_t *p = arg;
|
||||
(void)ctx;
|
||||
switch(_alpm_info_lookup_field(t->name)) {
|
||||
case NAME: return _alpm_info_print_str(t, alpm_pkg_get_name(p), f);
|
||||
case DESCRIPTION: return _alpm_info_print_str(t, alpm_pkg_get_desc(p), f);
|
||||
case PACKAGER: return _alpm_info_print_str(t, alpm_pkg_get_packager(p), f);
|
||||
case MD5SUM: return _alpm_info_print_str(t, alpm_pkg_get_md5sum(p), f);
|
||||
case FILENAME: return _alpm_info_print_str(t, alpm_pkg_get_filename(p), f);
|
||||
case BASE: return _alpm_info_print_str(t, alpm_pkg_get_base(p), f);
|
||||
case VERSION: return _alpm_info_print_str(t, alpm_pkg_get_version(p), f);
|
||||
case URL: return _alpm_info_print_str(t, alpm_pkg_get_url(p), f);
|
||||
case SHA256SUM: return _alpm_info_print_str(t, alpm_pkg_get_sha256sum(p), f);
|
||||
case ARCH: return _alpm_info_print_str(t, alpm_pkg_get_arch(p), f);
|
||||
case BASE64SIG: return _alpm_info_print_str(t, alpm_pkg_get_base64_sig(p), f);
|
||||
|
||||
case SIZE: return _alpm_info_print_size(t, alpm_pkg_get_size(p), f);
|
||||
case ISIZE: return _alpm_info_print_size(t, alpm_pkg_get_isize(p), f);
|
||||
|
||||
case BUILDDATE: return _alpm_info_print_timestamp(t, alpm_pkg_get_builddate(p), f);
|
||||
case INSTALLDATE: return _alpm_info_print_timestamp(t, alpm_pkg_get_installdate(p), f);
|
||||
|
||||
case DEPENDS: return _alpm_info_print_deplist(t, alpm_pkg_get_depends(p), f);
|
||||
case OPTDEPENDS: return _alpm_info_print_deplist(t, alpm_pkg_get_optdepends(p), f);
|
||||
case CONFLICTS: return _alpm_info_print_deplist(t, alpm_pkg_get_conflicts(p), f);
|
||||
case PROVIDES: return _alpm_info_print_deplist(t, alpm_pkg_get_provides(p), f);
|
||||
case REPLACES: return _alpm_info_print_deplist(t, alpm_pkg_get_replaces(p), f);
|
||||
case REQUIREDBY: {
|
||||
alpm_list_t *rb = alpm_pkg_compute_requiredby(p);
|
||||
size_t len = _alpm_info_print_strlist(t, rb, f);
|
||||
FREELIST(rb);
|
||||
return len;
|
||||
}
|
||||
|
||||
default: errno = EINVAL; return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SYMEXPORT alpm_info_print_pkg(const char *format, alpm_pkg_t *pkg) {
|
||||
alpm_list_t l = {
|
||||
.data = pkg,
|
||||
.next = NULL,
|
||||
};
|
||||
l.prev = &l;
|
||||
return alpm_info_print_pkgs(format, &l);
|
||||
}
|
||||
|
||||
size_t SYMEXPORT alpm_info_print_pkgs(const char *format, alpm_list_t *pkgs) {
|
||||
mfmt_t *mfmt = mfmt_parse(format, _alpm_info_process_token, NULL);
|
||||
size_t len = 0;
|
||||
if(mfmt == NULL) {
|
||||
return 0;
|
||||
}
|
||||
for(alpm_list_t *i = pkgs; i; i = i->next) {
|
||||
size_t plen = mfmt_printf(mfmt, i->data, stdout);
|
||||
if(plen == 0) { return 0; }
|
||||
len += plen;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* vim: set ts=2 sw=2 et: */
|
|
@ -31,5 +31,7 @@ libalpm_sources = files('''
|
|||
sync.h sync.c
|
||||
trans.h trans.c
|
||||
util.h util.c
|
||||
info.c
|
||||
mfmt.c mfmt.h
|
||||
version.c
|
||||
'''.split())
|
||||
|
|
193
lib/libalpm/mfmt.c
Normal file
193
lib/libalpm/mfmt.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mfmt.h"
|
||||
|
||||
char *_mfmt_find_unescaped_char(char *haystack, char needle) {
|
||||
while(1) {
|
||||
haystack = strchrnul(haystack, needle);
|
||||
if(*haystack && *(haystack + 1) == needle) { haystack += 2; continue; }
|
||||
else { break; }
|
||||
}
|
||||
return haystack;
|
||||
}
|
||||
|
||||
void _mfmt_brace_dedup(char *str) {
|
||||
char *c = str, *end = str + strlen(str);
|
||||
while((c = strchr(c, '{'))) {
|
||||
memmove(c, c + 1, end - c);
|
||||
c++;
|
||||
}
|
||||
|
||||
c = str;
|
||||
while((c = strchr(c, '}'))) {
|
||||
memmove(c, c + 1, end - c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
mfmt_t *mfmt_parse(const char *tmpl, mfmt_callback_t *cb, void *ctx) {
|
||||
mfmt_t *mfmt;
|
||||
char *c;
|
||||
|
||||
mfmt = calloc(sizeof(mfmt_t), 1);
|
||||
if(mfmt == NULL) { return NULL; }
|
||||
|
||||
mfmt->cb = cb;
|
||||
mfmt->ctx = ctx;
|
||||
|
||||
for(c = (char*) tmpl; c && *c; ) {
|
||||
mfmt->token_count++;
|
||||
if(*c == '{' && *(c + 1) != '{') {
|
||||
/* replacement */
|
||||
if(!*(c = _mfmt_find_unescaped_char(c + 1, '}'))) {
|
||||
errno = EINVAL;
|
||||
free(mfmt);
|
||||
return NULL;
|
||||
} else {
|
||||
c++;
|
||||
}
|
||||
} else {
|
||||
/* literal */
|
||||
c = _mfmt_find_unescaped_char(c, '{');
|
||||
}
|
||||
}
|
||||
|
||||
if((mfmt->tokens = calloc(sizeof(mfmt_token_t), mfmt->token_count)) == NULL) {
|
||||
free(mfmt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t i;
|
||||
for(c = (char*) tmpl, i = 0; c && *c; i++) {
|
||||
if(*c == '{' && *(c + 1) != '{') {
|
||||
/* replacement */
|
||||
mfmt_token_callback_t *t = &mfmt->tokens[i].callback;
|
||||
char *end = _mfmt_find_unescaped_char(c + 1, '}');
|
||||
t->type = MFMT_TOKEN_CALLBACK;
|
||||
t->name = strndup(c + 1, end - c - 1);
|
||||
c = end + 1;
|
||||
} else {
|
||||
/* literal */
|
||||
char *end = _mfmt_find_unescaped_char(c, '{');
|
||||
mfmt_token_literal_t *t = &mfmt->tokens[i].literal;
|
||||
t->type = MFMT_TOKEN_LITERAL;
|
||||
t->string = strndup(c, end - c);
|
||||
_mfmt_brace_dedup(t->string);
|
||||
c = end;
|
||||
}
|
||||
}
|
||||
|
||||
return mfmt;
|
||||
}
|
||||
|
||||
size_t mfmt_printf(mfmt_t *mfmt, void *args, FILE *f) {
|
||||
size_t len = 0;
|
||||
size_t i;
|
||||
for(i = 0; i < mfmt->token_count; i++) {
|
||||
mfmt_token_t *t = &mfmt->tokens[i];
|
||||
switch(t->base.type) {
|
||||
case MFMT_TOKEN_LITERAL:
|
||||
len += fputs(t->literal.string, f);
|
||||
break;
|
||||
case MFMT_TOKEN_CALLBACK:
|
||||
len += mfmt->cb(f, &t->callback, mfmt->ctx, args);
|
||||
break;
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t _mfmt_printf_close(mfmt_t *mfmt, void *args, FILE *f) {
|
||||
if(f) {
|
||||
size_t len = mfmt_printf(mfmt, args, f);
|
||||
fclose(f);
|
||||
return len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t mfmt_printd(mfmt_t *mfmt, void *args, int fd) {
|
||||
return _mfmt_printf_close(mfmt, args, fdopen(fd, "w"));
|
||||
}
|
||||
|
||||
size_t mfmt_printb(mfmt_t *mfmt, void *args, char *buf, size_t buflen) {
|
||||
return _mfmt_printf_close(mfmt, args, fmemopen(buf, buflen, "w"));
|
||||
}
|
||||
|
||||
size_t mfmt_prints(mfmt_t *mfmt, void *args, char **buf, size_t *buflen) {
|
||||
return _mfmt_printf_close(mfmt, args, open_memstream(buf, buflen));
|
||||
}
|
||||
|
||||
size_t mfmt_fmt(const char *tmpl, mfmt_val_t *args, FILE *f) {
|
||||
mfmt_t *mfmt = mfmt_parse(tmpl, NULL, NULL);
|
||||
size_t len;
|
||||
for(size_t i = 0; i < mfmt->token_count; i++) {
|
||||
mfmt_token_t *t = &mfmt->tokens[i];
|
||||
switch(t->base.type) {
|
||||
case MFMT_TOKEN_LITERAL:
|
||||
len += fputs(t->literal.string, f);
|
||||
break;
|
||||
case MFMT_TOKEN_CALLBACK:
|
||||
/* fprintf(stderr, "token: %s\n", t->callback.name); */
|
||||
if(t->callback.name[0]) {
|
||||
for(mfmt_val_t *v = args; v; v++) {
|
||||
/* fprintf(stderr, "val: %s\n", v->name); */
|
||||
if(strcmp(v->name, t->callback.name) == 0) {
|
||||
len += fputs(v->string, f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len += fputs(args->string, f);
|
||||
args++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t mfmt_mfmt(mfmt_t *mfmt, mfmt_val_t *args, FILE *f) {
|
||||
size_t len;
|
||||
for(size_t i = 0; i < mfmt->token_count; i++) {
|
||||
mfmt_token_t *t = &mfmt->tokens[i];
|
||||
switch(t->base.type) {
|
||||
case MFMT_TOKEN_LITERAL:
|
||||
len += fputs(t->literal.string, f);
|
||||
break;
|
||||
case MFMT_TOKEN_CALLBACK:
|
||||
/* fprintf(stderr, "token: %s\n", t->callback.name); */
|
||||
if(t->callback.name[0]) {
|
||||
for(mfmt_val_t *v = args; v; v++) {
|
||||
/* fprintf(stderr, "val: %s\n", v->name); */
|
||||
if(strcmp(v->name, t->callback.name) == 0) {
|
||||
len += fputs(v->string, f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len += fputs(args->string, f);
|
||||
args++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t mfmt_render_int(mfmt_token_callback_t *t, const intmax_t i, FILE *f) {
|
||||
(void)t;
|
||||
return fprintf(f, "%jd", i);
|
||||
}
|
||||
|
||||
size_t mfmt_render_str(mfmt_token_callback_t *t, const char *str, FILE *f) {
|
||||
(void)t;
|
||||
return fputs(str, f);
|
||||
}
|
66
lib/libalpm/mfmt.h
Normal file
66
lib/libalpm/mfmt.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef enum mfmt_token_type_t {
|
||||
MFMT_TOKEN_LITERAL,
|
||||
MFMT_TOKEN_CALLBACK,
|
||||
} mfmt_token_type_t;
|
||||
|
||||
typedef struct mfmt_token_literal_t {
|
||||
mfmt_token_type_t type;
|
||||
char *string;
|
||||
} mfmt_token_literal_t;
|
||||
|
||||
typedef struct mfmt_token_base_t {
|
||||
mfmt_token_type_t type;
|
||||
} mfmt_token_base_t;
|
||||
|
||||
typedef struct mfmt_token_callback_t {
|
||||
mfmt_token_type_t type;
|
||||
|
||||
size_t position;
|
||||
char *name;
|
||||
size_t width;
|
||||
size_t precision;
|
||||
char align;
|
||||
char fill;
|
||||
char conversion;
|
||||
int sign;
|
||||
} mfmt_token_callback_t;
|
||||
|
||||
typedef union mfmt_token_t {
|
||||
mfmt_token_base_t base;
|
||||
mfmt_token_literal_t literal;
|
||||
mfmt_token_callback_t callback;
|
||||
} mfmt_token_t;
|
||||
|
||||
typedef size_t (mfmt_callback_t)(FILE *f, mfmt_token_callback_t *token, void *ctx, void *args);
|
||||
|
||||
typedef struct mfmt_t {
|
||||
mfmt_callback_t *cb;
|
||||
void *ctx;
|
||||
size_t token_count;
|
||||
mfmt_token_t *tokens;
|
||||
} mfmt_t;
|
||||
|
||||
typedef struct mfmt_val_t {
|
||||
const char *name;
|
||||
const char *string;
|
||||
} mfmt_val_t;
|
||||
|
||||
mfmt_t *mfmt_parse(const char *tmpl, mfmt_callback_t *cb, void *ctx);
|
||||
size_t mfmt_printf(mfmt_t *mfmt, void *args, FILE *f);
|
||||
size_t mfmt_printd(mfmt_t *mfmt, void *args, int fd);
|
||||
size_t mfmt_printb(mfmt_t *mfmt, void *args, char *buf, size_t buflen);
|
||||
size_t mfmt_prints(mfmt_t *mfmt, void *args, char **buf, size_t *buflen);
|
||||
void mfmt_free(mfmt_t *mfmt);
|
||||
|
||||
size_t mfmt_render_int(mfmt_token_callback_t *token, intmax_t i, FILE *f);
|
||||
size_t mfmt_render_uint(mfmt_token_callback_t *token, uintmax_t i, FILE *f);
|
||||
size_t mfmt_render_str(mfmt_token_callback_t *token, const char *str, FILE *f);
|
||||
|
||||
size_t mfmt_formatf(const char *tmpl, mfmt_callback_t *cb, void *ctx, FILE *f);
|
||||
size_t mfmt_formatd(const char *tmpl, mfmt_callback_t *cb, void *ctx, int fd);
|
||||
size_t mfmt_formatb(const char *tmpl, mfmt_callback_t *cb, void *ctx, char *buf, size_t buflen);
|
||||
size_t mfmt_formats(const char *tmpl, mfmt_callback_t *cb, void *ctx, char **buf);
|
|
@ -60,6 +60,7 @@ typedef struct __config_t {
|
|||
unsigned short disable_dl_timeout;
|
||||
unsigned short disable_sandbox;
|
||||
char *print_format;
|
||||
char *pformat;
|
||||
/* unfortunately, we have to keep track of paths both here and in the library
|
||||
* because they can come from both the command line or config file, and we
|
||||
* need to ensure we get the order of preference right. */
|
||||
|
@ -175,6 +176,7 @@ enum {
|
|||
OP_ASEXPLICIT,
|
||||
OP_ARCH,
|
||||
OP_PRINTFORMAT,
|
||||
OP_PFORMAT,
|
||||
OP_GPGDIR,
|
||||
OP_DBONLY,
|
||||
OP_FORCE,
|
||||
|
|
|
@ -684,6 +684,9 @@ static int parsearg_trans(int opt)
|
|||
free(config->print_format);
|
||||
config->print_format = strdup(optarg);
|
||||
break;
|
||||
case OP_PFORMAT:
|
||||
config->pformat = strdup(optarg);
|
||||
break;
|
||||
case OP_ASSUMEINSTALLED:
|
||||
parsearg_util_addlist(&(config->assumeinstalled));
|
||||
break;
|
||||
|
@ -977,6 +980,7 @@ static int parseargs(int argc, char *argv[])
|
|||
{"asexplicit", no_argument, 0, OP_ASEXPLICIT},
|
||||
{"arch", required_argument, 0, OP_ARCH},
|
||||
{"print-format", required_argument, 0, OP_PRINTFORMAT},
|
||||
{"pformat" , required_argument, 0, OP_PFORMAT},
|
||||
{"gpgdir", required_argument, 0, OP_GPGDIR},
|
||||
{"dbonly", no_argument, 0, OP_DBONLY},
|
||||
{"color", required_argument, 0, OP_COLOR},
|
||||
|
|
|
@ -1201,6 +1201,10 @@ double humanize_size(off_t bytes, const char target_unit, int precision,
|
|||
void print_packages(const alpm_list_t *packages)
|
||||
{
|
||||
const alpm_list_t *i;
|
||||
if(config->pformat) {
|
||||
alpm_info_print_pkgs(config->pformat, (alpm_list_t*) packages);
|
||||
return;
|
||||
}
|
||||
if(!config->print_format) {
|
||||
config->print_format = strdup("%l");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue