Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

format strings for library and xbps-query #542

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
05cfc88
lib/compat/humanize_number.c: switch to freebsd version
Duncaen Feb 21, 2023
bac5de5
lib: add xbps_fmt* functions for string formatting
Duncaen Feb 20, 2023
5d4f0f2
bin/xbps-query: add -F/--format flag
Duncaen Feb 20, 2023
a6a529c
tests: add tests for xbps_fmt* functions
Duncaen Feb 21, 2023
6d228ac
lib/format.c: new humanize format !humanize[ ][.][width][minscale[max…
Duncaen Feb 21, 2023
e95718b
bin/xbps-query: document format flag
Duncaen Feb 21, 2023
16422b5
lib/format.c: split/cleanup code
Duncaen Mar 10, 2023
fd5157f
lib/format.c: change escaped [{}] to \\[{}]
Duncaen Mar 10, 2023
2162279
lib/format.c: add some more escape sequences
Duncaen Mar 10, 2023
90ce850
bin/xbps-query: update/clean format documentation
Duncaen Mar 10, 2023
f374d6c
bin/xbps-query: fix humanize "i" SI prefixs documentation
Duncaen Mar 10, 2023
578ce80
lib/format.c: refactor a bit
Duncaen Mar 14, 2023
a9c2747
lib/format.c: add optional default to format string variables
Duncaen Mar 14, 2023
c02cdc6
lib/format.c: simplify escape characters
Duncaen Mar 14, 2023
5c31fcb
lib/format.c: fix parsing empty default string
Duncaen Mar 14, 2023
cc8d7d2
lib/format.c: fix xbps_fmts*
Duncaen Mar 14, 2023
6baa761
lib/format.c: handle errors from nexttok
Duncaen Jun 19, 2023
1b78587
lib/json.c: add json printing stuff
Duncaen Sep 18, 2023
354fb92
lib/format.c: add json value conversion
Duncaen Sep 18, 2023
40d4427
bin/xbps-query: add --json flag as alternative to --format
Duncaen Sep 18, 2023
69aa731
lib/format: add \e escape, fix typos in format spec, remove dbg print
classabbyamp Mar 15, 2023
8715af4
bin/xbps-query: make --json compact if there is no indention
Duncaen Sep 18, 2023
c12f5aa
bin/xbps-query: cleanup mode handling
Duncaen Sep 19, 2023
03e1b5d
bin/xbps-query: move --list-repo to main.c, list.c is exclusively pac…
Duncaen Sep 19, 2023
8049a17
bin/xbps-query: add format string support to --list-repos
Duncaen Sep 19, 2023
ae7ccd1
bin/xbps-query: document the --json flag better
Duncaen Sep 19, 2023
31cec81
lib/format.c: IWYU
Duncaen Sep 19, 2023
7d038ca
include: split xbps_fmt stuff into its own header
Duncaen Sep 19, 2023
dcc60f4
lib/format.c: make struct xbps_fmt private
Duncaen Sep 19, 2023
17182be
bin/xbps-query: add pkgname,version and revision format variables
Duncaen Sep 19, 2023
aecab4c
lib/json.c: names and documentation
Duncaen Sep 19, 2023
ae11e15
bin/xbps-query: bring back default/null values for package formats
Duncaen Sep 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions bin/xbps-query/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,10 @@ int repo_show_pkg_namedesc(struct xbps_handle *, xbps_object_t, void *,
int ownedby(struct xbps_handle *, const char *, bool, bool);

/* From list.c */
unsigned int find_longest_pkgver(struct xbps_handle *, xbps_object_t);

int list_pkgs_in_dict(struct xbps_handle *, xbps_object_t, const char *, void *, bool *);
int list_manual_pkgs(struct xbps_handle *, xbps_object_t, const char *, void *, bool *);
int list_hold_pkgs(struct xbps_handle *, xbps_object_t, const char *, void *, bool *);
int list_repolock_pkgs(struct xbps_handle *, xbps_object_t, const char *, void *, bool *);
int list_orphans(struct xbps_handle *);
int list_orphans(struct xbps_handle *, const char *);
int list_pkgs_pkgdb(struct xbps_handle *);
int list_pkgdb(struct xbps_handle *, int (*filter)(xbps_object_t), const char *format, int json);

int repo_list(struct xbps_handle *);

Expand Down
286 changes: 153 additions & 133 deletions bin/xbps-query/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,60 @@
*/

#include <sys/types.h>
#include <stdio.h>

#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#include "defs.h"
#include "xbps.h"
#include "xbps/json.h"

struct length_max_cb {
const char *key;
int max;
};

static int
length_max_cb(struct xbps_handle *xhp UNUSED, xbps_object_t obj,
const char *key UNUSED, void *arg, bool *loop_done UNUSED)
{
struct length_max_cb *ctx = arg;
const char *s = NULL;
size_t len;

if (!xbps_dictionary_get_cstring_nocopy(obj, ctx->key, &s))
return -errno;

len = strlen(s);
if (len > INT_MAX)
return -ERANGE;
if ((int)len > ctx->max)
ctx->max = len;

return 0;
}

struct list_pkgver_cb {
unsigned int pkgver_len;
unsigned int pkgver_align;
unsigned int maxcols;
char *linebuf;
char *buf;
struct xbps_fmt *fmt;
};

int
list_pkgs_in_dict(struct xbps_handle *xhp UNUSED,
static int
list_pkgs_pkgdb_cb(struct xbps_handle *xhp UNUSED,
xbps_object_t obj,
const char *key UNUSED,
void *arg,
bool *loop_done UNUSED)
{
struct list_pkgver_cb *lpc = arg;
struct list_pkgver_cb *ctx = arg;
const char *pkgver = NULL, *short_desc = NULL, *state_str = NULL;
unsigned int len;
pkg_state_t state;
Expand All @@ -58,84 +89,118 @@ list_pkgs_in_dict(struct xbps_handle *xhp UNUSED,

xbps_pkg_state_dictionary(obj, &state);

if (state == XBPS_PKG_STATE_INSTALLED)
state_str = "ii";
else if (state == XBPS_PKG_STATE_UNPACKED)
state_str = "uu";
else if (state == XBPS_PKG_STATE_HALF_REMOVED)
state_str = "hr";
else
state_str = "??";

if (lpc->linebuf == NULL) {
printf("%s %-*s %s\n",
state_str,
lpc->pkgver_len, pkgver,
short_desc);
switch (state) {
case XBPS_PKG_STATE_INSTALLED: state_str = "ii"; break;
case XBPS_PKG_STATE_UNPACKED: state_str = "uu"; break;
case XBPS_PKG_STATE_HALF_REMOVED: state_str = "hr"; break;
case XBPS_PKG_STATE_BROKEN: state_str = "br"; break;
case XBPS_PKG_STATE_NOT_INSTALLED: state_str = "??"; break;
}

if (!ctx->buf) {
printf("%s %-*s %s\n", state_str, ctx->pkgver_align, pkgver,
short_desc);
return 0;
}

len = snprintf(lpc->linebuf, lpc->maxcols, "%s %-*s %s",
state_str,
lpc->pkgver_len, pkgver,
short_desc);
/* add ellipsis if the line was truncated */
if (len >= lpc->maxcols && lpc->maxcols > 4) {
for (unsigned int j = 0; j < 3; j++)
lpc->linebuf[lpc->maxcols-j-1] = '.';
lpc->linebuf[lpc->maxcols] = '\0';
}
puts(lpc->linebuf);
len = snprintf(ctx->buf, ctx->maxcols, "%s %-*s %s\n", state_str,
ctx->pkgver_align, pkgver, short_desc);
if (len >= ctx->maxcols && ctx->maxcols > sizeof("..."))
memcpy(ctx->buf + ctx->maxcols - sizeof("..."), "...", sizeof("..."));
fputs(ctx->buf, stdout);

return 0;
}

int
list_manual_pkgs(struct xbps_handle *xhp UNUSED,
xbps_object_t obj,
const char *key UNUSED,
void *arg UNUSED,
bool *loop_done UNUSED)
list_pkgs_pkgdb(struct xbps_handle *xhp)
{
const char *pkgver = NULL;
bool automatic = false;
struct length_max_cb longest = {.key = "pkgver"};
struct list_pkgver_cb lpc = {0};

xbps_dictionary_get_bool(obj, "automatic-install", &automatic);
if (automatic == false) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
puts(pkgver);
int r = xbps_pkgdb_foreach_cb_multi(xhp, length_max_cb, &longest);
if (r < 0)
return r;

lpc.pkgver_align = longest.max;
lpc.maxcols = get_maxcols();
if (lpc.maxcols > 0) {
lpc.buf = malloc(lpc.maxcols);
if (!lpc.buf)
return -errno;
}

return 0;
return xbps_pkgdb_foreach_cb(xhp, list_pkgs_pkgdb_cb, &lpc);
}

int
list_hold_pkgs(struct xbps_handle *xhp UNUSED,
xbps_object_t obj,
const char *key UNUSED,
void *arg UNUSED,
bool *loop_done UNUSED)
struct list_pkgdb_cb {
struct xbps_fmt *fmt;
struct xbps_json_printer *json;
int (*filter)(xbps_object_t obj);
};

static int
list_pkgdb_cb(struct xbps_handle *xhp UNUSED, xbps_object_t obj,
const char *key UNUSED, void *arg, bool *loop_done UNUSED)
{
const char *pkgver = NULL;
struct list_pkgdb_cb *ctx = arg;
int r;

if (ctx->filter) {
r = ctx->filter(obj);
if (r < 0)
return r;
if (r == 0)
return 0;
}

if (xbps_dictionary_get(obj, "hold")) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
puts(pkgver);
if (ctx->fmt) {
r = xbps_fmt_dictionary(ctx->fmt, obj, stdout);
} else if (ctx->json) {
r = xbps_json_print_xbps_object(ctx->json, obj);
fprintf(ctx->json->file, "\n");
} else {
r = -ENOTSUP;
}
return r;
}

return 0;
int
list_pkgdb(struct xbps_handle *xhp, int (*filter)(xbps_object_t), const char *format, int json)
{
struct list_pkgdb_cb ctx = {.filter = filter};
struct xbps_json_printer pr = {0};
int r;
if (json > 0) {
pr.indent = (json-1) * 2;
pr.file = stdout;
ctx.json = &pr;
} else if (format) {
ctx.fmt = xbps_fmt_parse(format);
if (!ctx.fmt) {
r = -errno;
xbps_error_printf("failed to parse format: %s\n", strerror(-r));
return r;
}
}
r = xbps_pkgdb_foreach_cb(xhp, list_pkgdb_cb, &ctx);
xbps_fmt_free(ctx.fmt);
return r;
}

int
list_repolock_pkgs(struct xbps_handle *xhp UNUSED,
xbps_object_t obj,
const char *key UNUSED,
void *arg UNUSED,
bool *loop_done UNUSED)
list_manual_pkgs(struct xbps_handle *xhp UNUSED,
xbps_object_t obj,
const char *key UNUSED,
void *arg UNUSED,
bool *loop_done UNUSED)
{
const char *pkgver = NULL;
bool automatic = false;

if (xbps_dictionary_get(obj, "repolock")) {
xbps_dictionary_get_bool(obj, "automatic-install", &automatic);
if (automatic == false) {
xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
puts(pkgver);
}
Expand All @@ -144,40 +209,42 @@ list_repolock_pkgs(struct xbps_handle *xhp UNUSED,
}

int
list_orphans(struct xbps_handle *xhp)
list_orphans(struct xbps_handle *xhp, const char *format)
{
xbps_array_t orphans;
const char *pkgver = NULL;
struct xbps_fmt *fmt;
int r = 0;

fmt = xbps_fmt_parse(format);
if (!fmt) {
r = -errno;
xbps_error_printf("failed to parse format: %s\n", strerror(-r));
return r;
}

orphans = xbps_find_pkg_orphans(xhp, NULL);
if (orphans == NULL)
return EINVAL;
if (!orphans) {
r = -errno;
xbps_error_printf("failed to find orphans: %s\n", strerror(-r));
goto err;
}

for (unsigned int i = 0; i < xbps_array_count(orphans); i++) {
xbps_dictionary_get_cstring_nocopy(xbps_array_get(orphans, i),
"pkgver", &pkgver);
puts(pkgver);
xbps_object_t obj = xbps_array_get(orphans, i);
if (!obj)
return -errno;
r = xbps_fmt_dictionary(fmt, obj, stdout);
if (r < 0)
goto err;
}

return 0;
err:
xbps_fmt_free(fmt);
return r;
}

int
list_pkgs_pkgdb(struct xbps_handle *xhp)
{
struct list_pkgver_cb lpc;

lpc.pkgver_len = find_longest_pkgver(xhp, NULL);
lpc.maxcols = get_maxcols();
lpc.linebuf = NULL;
if (lpc.maxcols > 0) {
lpc.linebuf = malloc(lpc.maxcols);
if (lpc.linebuf == NULL)
exit(1);
}

return xbps_pkgdb_foreach_cb(xhp, list_pkgs_in_dict, &lpc);
}
#ifndef __UNCONST
#define __UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
#endif

static void
repo_list_uri(struct xbps_repo *repo)
Expand Down Expand Up @@ -230,50 +297,3 @@ repo_list(struct xbps_handle *xhp)
}
return 0;
}

struct fflongest {
xbps_dictionary_t d;
unsigned int len;
};

static int
_find_longest_pkgver_cb(struct xbps_handle *xhp UNUSED,
xbps_object_t obj,
const char *key UNUSED,
void *arg,
bool *loop_done UNUSED)
{
struct fflongest *ffl = arg;
const char *pkgver = NULL;
unsigned int len;

xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
len = strlen(pkgver);
if (ffl->len == 0 || len > ffl->len)
ffl->len = len;

return 0;
}

unsigned int
find_longest_pkgver(struct xbps_handle *xhp, xbps_object_t o)
{
struct fflongest ffl;

ffl.d = o;
ffl.len = 0;

if (xbps_object_type(o) == XBPS_TYPE_DICTIONARY) {
xbps_array_t array;

array = xbps_dictionary_all_keys(o);
(void)xbps_array_foreach_cb_multi(xhp, array, o,
_find_longest_pkgver_cb, &ffl);
xbps_object_release(array);
} else {
(void)xbps_pkgdb_foreach_cb_multi(xhp,
_find_longest_pkgver_cb, &ffl);
}

return ffl.len;
}
Loading