Skip to content

Commit 053a545

Browse files
committed
bin/xbps-alternatives: add repository mode to list repo alternatives
1 parent d5a5630 commit 053a545

File tree

2 files changed

+175
-33
lines changed

2 files changed

+175
-33
lines changed

bin/xbps-alternatives/main.c

Lines changed: 159 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*-
22
* Copyright (c) 2015 Juan Romero Pardines.
3+
* Copyright (c) 2020 Duncan Overbruck <[email protected]>.
34
* All rights reserved.
45
*
56
* Redistribution and use in source and binary forms, with or without
@@ -41,16 +42,22 @@ usage(bool fail)
4142
fprintf(stdout,
4243
"Usage: xbps-alternatives [OPTIONS] MODE\n\n"
4344
"OPTIONS\n"
44-
" -C --config <dir> Path to confdir (xbps.d)\n"
45-
" -d --debug Debug mode shown to stderr\n"
46-
" -g --group <name> Group of alternatives to match\n"
47-
" -h --help Show usage\n"
48-
" -r --rootdir <dir> Full path to rootdir\n"
49-
" -v --verbose Verbose messages\n"
50-
" -V --version Show XBPS version\n"
45+
" -C --config <dir> Path to confdir (xbps.d)\n"
46+
" -d --debug Debug mode shown to stderr\n"
47+
" -g --group <name> Group of alternatives to match\n"
48+
" -h --help Show usage\n"
49+
" -i, --ignore-conf-repos Ignore repositories defined in xbps.d\n"
50+
" -R, --repository Enable repository mode. This mode explicitly\n"
51+
" looks for packages in repositories\n"
52+
" --repository=<url> Enable repository mode and add repository\n"
53+
" to the top of the list. This option can be\n"
54+
" specified multiple times\n"
55+
" -r --rootdir <dir> Full path to rootdir\n"
56+
" -v --verbose Verbose messages\n"
57+
" -V --version Show XBPS version\n"
5158
"MODE\n"
52-
" -l --list [PKG] List all alternatives or from PKG\n"
53-
" -s --set PKG Set alternatives for PKG\n");
59+
" -l --list [PKG] List all alternatives or from PKG\n"
60+
" -s --set PKG Set alternatives for PKG\n");
5461
exit(fail ? EXIT_FAILURE : EXIT_SUCCESS);
5562
}
5663

@@ -107,27 +114,11 @@ list_pkg_alternatives(xbps_dictionary_t pkgd, const char *group, bool print_key)
107114
xbps_object_release(allkeys);
108115
}
109116

110-
static int
111-
list_alternatives(struct xbps_handle *xhp, const char *pkgname, const char *grp)
117+
static void
118+
print_alternatives(struct xbps_handle *xhp, xbps_dictionary_t alternatives, const char *grp, bool repo_mode)
112119
{
113-
xbps_dictionary_t alternatives, pkgd;
114120
xbps_array_t allkeys;
115-
116-
(void)xbps_pkgdb_get_pkg(xhp, "foo");
117-
118-
if (pkgname) {
119-
/* list alternatives for pkgname */
120-
if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL)
121-
return ENOENT;
122-
123-
list_pkg_alternatives(pkgd, NULL, true);
124-
return 0;
125-
}
126-
assert(xhp->pkgdb);
127-
128-
alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_");
129-
if (alternatives == NULL)
130-
return ENOENT;
121+
xbps_dictionary_t pkgd;
131122

132123
allkeys = xbps_dictionary_all_keys(alternatives);
133124
for (unsigned int i = 0; i < xbps_array_count(allkeys); i++) {
@@ -147,28 +138,136 @@ list_alternatives(struct xbps_handle *xhp, const char *pkgname, const char *grp)
147138
const char *str = NULL;
148139

149140
xbps_array_get_cstring_nocopy(array, x, &str);
150-
printf(" - %s%s\n", str, x == 0 ? " (current)" : "");
141+
printf(" - %s%s\n", str, !repo_mode && x == 0 ? " (current)" : "");
151142
pkgd = xbps_pkgdb_get_pkg(xhp, str);
143+
if (pkgd == NULL && repo_mode)
144+
pkgd = xbps_rpool_get_pkg(xhp, str);
152145
assert(pkgd);
153146
list_pkg_alternatives(pkgd, keyname, false);
154147
}
155148
}
156149
xbps_object_release(allkeys);
150+
}
157151

152+
static int
153+
list_alternatives(struct xbps_handle *xhp, const char *pkgname, const char *grp)
154+
{
155+
xbps_dictionary_t alternatives, pkgd;
156+
157+
if (pkgname) {
158+
/* list alternatives for pkgname */
159+
if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL)
160+
return -ENOENT;
161+
162+
list_pkg_alternatives(pkgd, NULL, true);
163+
return 0;
164+
} else {
165+
// XXX: initializing the pkgdb.
166+
(void)xbps_pkgdb_get_pkg(xhp, "foo");
167+
}
168+
assert(xhp->pkgdb);
169+
170+
alternatives = xbps_dictionary_get(xhp->pkgdb, "_XBPS_ALTERNATIVES_");
171+
if (alternatives == NULL)
172+
return -ENOENT;
173+
174+
print_alternatives(xhp, alternatives, grp, false);
158175
return 0;
159176
}
160177

178+
struct search_data {
179+
const char *group;
180+
xbps_dictionary_t result;
181+
};
182+
183+
static int
184+
search_array_cb(struct xbps_handle *xhp UNUSED,
185+
xbps_object_t obj,
186+
const char *key UNUSED,
187+
void *arg,
188+
bool *done UNUSED)
189+
{
190+
xbps_object_iterator_t iter;
191+
xbps_dictionary_t alternatives;
192+
struct search_data *sd = arg;
193+
const char *pkgver = NULL;
194+
195+
if (!xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver))
196+
return 0;
197+
198+
alternatives = xbps_dictionary_get(obj, "alternatives");
199+
if (alternatives == NULL)
200+
return 0;
201+
202+
iter = xbps_dictionary_iterator(alternatives);
203+
assert(iter);
204+
205+
/*
206+
* Register all provided groups in the result dictionary.
207+
*/
208+
while ((obj = xbps_object_iterator_next(iter))) {
209+
xbps_array_t grouparr;
210+
const char *group = xbps_dictionary_keysym_cstring_nocopy(obj);
211+
bool alloc = false;
212+
213+
/* skip the group if we search for a specific one */
214+
if (sd->group != NULL && strcmp(sd->group, group) != 0)
215+
continue;
216+
217+
grouparr = xbps_dictionary_get(sd->result, group);
218+
if (grouparr == NULL) {
219+
if ((grouparr = xbps_array_create()) == NULL) {
220+
xbps_error_printf("Failed to create array: %s\n", strerror(errno));
221+
exit(EXIT_FAILURE);
222+
}
223+
alloc = true;
224+
xbps_dictionary_set(sd->result, group, grouparr);
225+
} else {
226+
/*
227+
* check if pkgver is already in the group array,
228+
* this only happens if multiple repositories provide
229+
* the same pkgver.
230+
*/
231+
if (xbps_match_string_in_array(grouparr, pkgver))
232+
continue;
233+
}
234+
xbps_array_add_cstring_nocopy(grouparr, pkgver);
235+
236+
if (alloc)
237+
xbps_object_release(grouparr);
238+
}
239+
240+
return 0;
241+
}
242+
243+
static int
244+
search_repo_cb(struct xbps_repo *repo, void *arg, bool *done UNUSED)
245+
{
246+
xbps_array_t allkeys;
247+
int rv;
248+
249+
if (repo->idx == NULL)
250+
return 0;
251+
252+
allkeys = xbps_dictionary_all_keys(repo->idx);
253+
rv = xbps_array_foreach_cb(repo->xhp, allkeys, repo->idx, search_array_cb, arg);
254+
xbps_object_release(allkeys);
255+
return rv;
256+
}
257+
161258
int
162259
main(int argc, char **argv)
163260
{
164-
const char *shortopts = "C:dg:hls:r:Vv";
261+
const char *shortopts = "C:dg:hils:Rr:Vv";
165262
const struct option longopts[] = {
166263
{ "config", required_argument, NULL, 'C' },
167264
{ "debug", no_argument, NULL, 'd' },
168265
{ "group", required_argument, NULL, 'g' },
169266
{ "help", no_argument, NULL, 'h' },
267+
{ "ignore-conf-repos", no_argument, NULL, 'i' },
170268
{ "list", no_argument, NULL, 'l' },
171269
{ "set", required_argument, NULL, 's' },
270+
{ "repository", optional_argument, NULL, 'R' },
172271
{ "rootdir", required_argument, NULL, 'r' },
173272
{ "verbose", no_argument, NULL, 'v' },
174273
{ "version", no_argument, NULL, 'V' },
@@ -177,7 +276,7 @@ main(int argc, char **argv)
177276
struct xbps_handle xh;
178277
const char *confdir, *rootdir, *group, *pkg;
179278
int c, rv, flags = 0;
180-
bool list_mode = false, set_mode = false;
279+
bool list_mode = false, set_mode = false, repo_mode = false;
181280

182281
confdir = rootdir = group = pkg = NULL;
183282

@@ -195,13 +294,22 @@ main(int argc, char **argv)
195294
case 'h':
196295
usage(false);
197296
/* NOTREACHED */
297+
case 'i':
298+
flags |= XBPS_FLAG_IGNORE_CONF_REPOS;
299+
break;
198300
case 'l':
199301
list_mode = true;
200302
break;
201303
case 's':
202304
set_mode = true;
203305
pkg = optarg;
204306
break;
307+
case 'R':
308+
if (optarg != NULL) {
309+
xbps_repo_store(&xh, optarg);
310+
}
311+
repo_mode = true;
312+
break;
205313
case 'r':
206314
rootdir = optarg;
207315
break;
@@ -250,7 +358,26 @@ main(int argc, char **argv)
250358
rv = xbps_pkgdb_update(&xh, true, false);
251359
} else if (list_mode) {
252360
/* list alternative groups */
253-
rv = list_alternatives(&xh, pkg, group);
361+
if (repo_mode) {
362+
struct search_data sd = { 0 };
363+
if ((sd.result = xbps_dictionary_create()) == NULL) {
364+
xbps_error_printf("Failed to create dictionary: %s\n", strerror(errno));
365+
exit(EXIT_FAILURE);
366+
}
367+
sd.group = group;
368+
rv = xbps_rpool_foreach(&xh, search_repo_cb, &sd);
369+
if (rv != 0 && rv != ENOTSUP) {
370+
fprintf(stderr, "Failed to initialize rpool: %s\n",
371+
strerror(rv));
372+
exit(EXIT_FAILURE);
373+
}
374+
if (xbps_dictionary_count(sd.result) > 0)
375+
print_alternatives(&xh, sd.result, group, true);
376+
else
377+
exit(EXIT_FAILURE);
378+
} else {
379+
rv = list_alternatives(&xh, pkg, group);
380+
}
254381
}
255382

256383
xbps_end(&xh);

bin/xbps-alternatives/xbps-alternatives.1

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.Dd Feb 9, 2023
1+
.Dd Aug 31, 2023
22
.Dt XBPS-ALTERNATIVES 1
33
.Os
44
.Sh NAME
@@ -34,6 +34,21 @@ Alternative group name to match. To be used with the
3434
mode.
3535
.It Fl h, Fl -help
3636
Show the help message.
37+
.It Fl i, Fl -ignore-conf-repos
38+
Ignore repositories defined in configuration files.
39+
Only repositories specified in the command line via
40+
.Ar --repository
41+
will be used.
42+
.It Fl R
43+
Enable repository mode when listing alternatives.
44+
This mode explicitly looks for all alternatives available
45+
in repositories rather than looking for installed alternatives.
46+
.It Fl -repository Ar url
47+
Appends the specified repository to the top of the list.
48+
The
49+
.Ar url
50+
argument expects a URL to the repository for remote repositories or
51+
a path for local repositories.
3752
.It Fl r, Fl -rootdir Ar dir
3853
Specifies a full path for the target root directory.
3954
.It Fl v, Fl -verbose

0 commit comments

Comments
 (0)