]> git.ipfire.org Git - pakfire.git/blob - src/cli/pakfire-builder.c
cli: pakfire-builder: Implement repo compose
[pakfire.git] / src / cli / pakfire-builder.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2023 Pakfire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <errno.h>
22 #include <getopt.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27
28 #include <pakfire/pakfire.h>
29 #include <pakfire/string.h>
30
31 #include "lib/build.h"
32 #include "lib/clean.h"
33 #include "lib/command.h"
34 #include "lib/dist.h"
35 #include "lib/info.h"
36 #include "lib/provides.h"
37 #include "lib/repo.h"
38 #include "lib/repolist.h"
39 #include "lib/requires.h"
40 #include "lib/shell.h"
41 #include "lib/search.h"
42 #include "lib/terminal.h"
43 #include "lib/version.h"
44
45 #define MAX_REPOS 16
46
47 struct config {
48 const char* distro;
49 char* arch;
50 int flags;
51
52 // Repos
53 const char* enable_repos[MAX_REPOS];
54 unsigned int num_enable_repos;
55 const char* disable_repos[MAX_REPOS];
56 unsigned int num_disable_repos;
57 };
58
59 static int cli_main(struct pakfire* pakfire, int argc, char* argv[]) {
60 static const struct command commands[] = {
61 { "build", 0, cli_build },
62 { "clean", 0, cli_clean },
63 { "dist", 0, cli_dist },
64 { "info", 0, cli_info },
65 { "provides", 0, cli_provides },
66 { "repo", 0, cli_repo },
67 { "repolist", 0, cli_repolist },
68 { "requires", 0, cli_requires },
69 { "shell", 0, cli_shell },
70 { "search", 0, cli_search },
71 { NULL },
72 };
73
74 return command_dispatch(pakfire, commands, argc, argv);
75 }
76
77 static void help(void) {
78 printf(
79 "%s [OPTIONS...] COMMAND\n\n"
80 "Options:\n"
81 " -a --arch Run in different architecture\n"
82 " --distro Selects the distribution to compile for\n"
83 " --debug Run in debug mode\n"
84 " -h --help Show help\n"
85 " --version Show version\n"
86 "\n"
87 "Commands:\n"
88 " search Search for packages\n"
89 " provides Shows which package provides a dependency\n"
90 " requires Shows which package requries a dependency\n"
91 " repolist Show all configured repositories\n"
92 " clean Cleans up no longer needed resources\n",
93 program_invocation_short_name
94 );
95
96 exit(0);
97 }
98
99 static int parse_argv(struct config* config, int argc, char* argv[]) {
100 enum {
101 ARG_DEBUG,
102 ARG_DISTRO,
103 ARG_VERSION,
104
105 // Repos
106 ARG_ENABLE_REPO,
107 ARG_DISABLE_REPO,
108 };
109
110 static const struct option options[] = {
111 { "arch", required_argument, NULL, 'a' },
112 { "debug", no_argument, NULL, ARG_DEBUG },
113 { "distro", required_argument, NULL, ARG_DISTRO },
114 { "help", no_argument, NULL, 'h' },
115 { "version", no_argument, NULL, ARG_VERSION },
116
117 // Repos
118 { "enable-repo", required_argument, NULL, ARG_ENABLE_REPO },
119 { "disable-repo", required_argument, NULL, ARG_DISABLE_REPO },
120 { NULL },
121 };
122 int c;
123
124 for (;;) {
125 c = getopt_long(argc, argv, "ah", options, NULL);
126 if (c < 0)
127 break;
128
129 switch (c) {
130 case 'a':
131 config->arch = optarg;
132 break;
133
134 case 'h':
135 help();
136
137 case ARG_DEBUG:
138 config->flags |= PAKFIRE_FLAGS_DEBUG;
139 break;
140
141 case ARG_DISTRO:
142 config->distro = optarg;
143 break;
144
145 case ARG_VERSION:
146 cli_version();
147 exit(0);
148
149 case ARG_ENABLE_REPO:
150 if (config->num_enable_repos >= MAX_REPOS)
151 return -ENOBUFS;
152
153 config->enable_repos[config->num_enable_repos++] = optarg;
154 break;
155
156 case ARG_DISABLE_REPO:
157 if (config->num_disable_repos >= MAX_REPOS)
158 return -ENOBUFS;
159
160 config->disable_repos[config->num_disable_repos++] = optarg;
161 break;
162
163 case '?':
164 return -EINVAL;
165
166 default:
167 break;
168 }
169 }
170
171 return 0;
172 }
173
174 static void cli_set_repo_enabled(struct pakfire* pakfire, const char* name, int enabled) {
175 struct pakfire_repo* repo = NULL;
176
177 // Find the repository
178 repo = pakfire_get_repo(pakfire, name);
179
180 // Ignore if the repository could not be found
181 if (!repo)
182 return;
183
184 // Set status
185 pakfire_repo_set_enabled(repo, enabled);
186 pakfire_repo_unref(repo);
187 }
188
189 static FILE* open_distro_config(const char* distro) {
190 char path[PATH_MAX];
191 FILE* f = NULL;
192 int r;
193
194 // XXX hard-coded path
195
196 // Make the path
197 r = snprintf(path, sizeof(path), "/etc/pakfire/distros/%s.conf", distro);
198 if (r < 0)
199 return NULL;
200
201 // Open the configuration file
202 f = fopen(path, "r");
203 if (!f) {
204 switch (errno) {
205 case ENOENT:
206 fprintf(stderr, "Could not find distro '%s': %m\n", distro);
207 break;
208
209 default:
210 break;
211 }
212 }
213
214 return f;
215 }
216
217 static int setup_pakfire(const struct config* config, struct pakfire** pakfire) {
218 struct pakfire* p = NULL;
219 FILE* f = NULL;
220 int r;
221
222 // Open the distro configuration
223 f = open_distro_config(config->distro);
224 if (!f) {
225 r = 1;
226 goto ERROR;
227 }
228
229 // Initialize Pakfire
230 r = pakfire_create(&p, NULL, config->arch, f, config->flags, NULL, NULL);
231 if (r)
232 goto ERROR;
233
234 // Enable repositories
235 for (unsigned int i = 0; i < config->num_enable_repos; i++)
236 cli_set_repo_enabled(p, config->enable_repos[i], 1);
237
238 // Disable repositories
239 for (unsigned int i = 0; i < config->num_disable_repos; i++)
240 cli_set_repo_enabled(p, config->disable_repos[i], 0);
241
242 // Return pointer
243 *pakfire = p;
244
245 ERROR:
246 if (f)
247 fclose(f);
248
249 return r;
250 }
251
252 int main(int argc, char* argv[]) {
253 struct pakfire* pakfire = NULL;
254 int r;
255
256 struct config config = {
257 // XXX hard-coded distro
258 .distro = "ipfire3",
259 .arch = NULL,
260 .flags = PAKFIRE_FLAGS_BUILD,
261 };
262
263 // Parse command line arguments
264 r = parse_argv(&config, argc, argv);
265 if (r)
266 goto ERROR;
267
268 // Setup Pakfire
269 r = setup_pakfire(&config, &pakfire);
270 if (r)
271 goto ERROR;
272
273 // Run a command
274 r = cli_main(pakfire, argc - optind + 1, argv + optind - 1);
275
276 ERROR:
277 if (pakfire)
278 pakfire_unref(pakfire);
279
280 return r;
281 }