]> git.ipfire.org Git - pakfire.git/blame - src/cli/pakfire-builder.c
path: Correctly set and return absolute paths
[pakfire.git] / src / cli / pakfire-builder.c
CommitLineData
fa640ef1
MT
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
817f7557 31#include "lib/assert.h"
060a1182 32#include "lib/build.h"
d20b1a83 33#include "lib/clean.h"
2c80538d 34#include "lib/command.h"
5f9bc3d2 35#include "lib/dist.h"
0a333c90 36#include "lib/image.h"
ecdd76bd 37#include "lib/info.h"
32bbeefc 38#include "lib/progressbar.h"
d20b1a83 39#include "lib/provides.h"
3467dd08 40#include "lib/repo.h"
418f36f6 41#include "lib/repolist.h"
d20b1a83 42#include "lib/requires.h"
beee2bda 43#include "lib/shell.h"
d20b1a83 44#include "lib/search.h"
2c80538d
MT
45#include "lib/terminal.h"
46#include "lib/version.h"
fa640ef1
MT
47
48#define MAX_REPOS 16
49
50struct config {
51 const char* distro;
52 char* arch;
53 int flags;
54
55 // Repos
56 const char* enable_repos[MAX_REPOS];
57 unsigned int num_enable_repos;
58 const char* disable_repos[MAX_REPOS];
59 unsigned int num_disable_repos;
60};
61
62static int cli_main(struct pakfire* pakfire, int argc, char* argv[]) {
63 static const struct command commands[] = {
060a1182 64 { "build", 0, cli_build },
d20b1a83 65 { "clean", 0, cli_clean },
5f9bc3d2 66 { "dist", 0, cli_dist },
0a333c90 67 { "image", 0, cli_image },
ecdd76bd 68 { "info", 0, cli_info },
d20b1a83 69 { "provides", 0, cli_provides },
3467dd08 70 { "repo", 0, cli_repo },
d20b1a83
MT
71 { "repolist", 0, cli_repolist },
72 { "requires", 0, cli_requires },
beee2bda 73 { "shell", 0, cli_shell },
d20b1a83 74 { "search", 0, cli_search },
fa640ef1
MT
75 { NULL },
76 };
77
78 return command_dispatch(pakfire, commands, argc, argv);
79}
80
81static void help(void) {
82 printf(
83 "%s [OPTIONS...] COMMAND\n\n"
84 "Options:\n"
85 " -a --arch Run in different architecture\n"
3537c6d1 86 " --distro Selects the distribution to compile for\n"
fa640ef1
MT
87 " --debug Run in debug mode\n"
88 " -h --help Show help\n"
fa640ef1 89 " --version Show version\n"
fa640ef1
MT
90 "\n"
91 "Commands:\n"
fa640ef1
MT
92 " search Search for packages\n"
93 " provides Shows which package provides a dependency\n"
94 " requires Shows which package requries a dependency\n"
95 " repolist Show all configured repositories\n"
96 " clean Cleans up no longer needed resources\n",
97 program_invocation_short_name
98 );
99
100 exit(0);
101}
102
103static int parse_argv(struct config* config, int argc, char* argv[]) {
104 enum {
105 ARG_DEBUG,
106 ARG_DISTRO,
107 ARG_VERSION,
108
109 // Repos
110 ARG_ENABLE_REPO,
111 ARG_DISABLE_REPO,
112 };
113
114 static const struct option options[] = {
115 { "arch", required_argument, NULL, 'a' },
116 { "debug", no_argument, NULL, ARG_DEBUG },
117 { "distro", required_argument, NULL, ARG_DISTRO },
118 { "help", no_argument, NULL, 'h' },
119 { "version", no_argument, NULL, ARG_VERSION },
120
121 // Repos
122 { "enable-repo", required_argument, NULL, ARG_ENABLE_REPO },
123 { "disable-repo", required_argument, NULL, ARG_DISABLE_REPO },
124 { NULL },
125 };
126 int c;
127
128 for (;;) {
129 c = getopt_long(argc, argv, "ah", options, NULL);
130 if (c < 0)
131 break;
132
133 switch (c) {
134 case 'a':
135 config->arch = optarg;
136 break;
137
138 case 'h':
139 help();
140
141 case ARG_DEBUG:
142 config->flags |= PAKFIRE_FLAGS_DEBUG;
143 break;
144
145 case ARG_DISTRO:
146 config->distro = optarg;
147 break;
148
149 case ARG_VERSION:
150 cli_version();
151 exit(0);
152
153 case ARG_ENABLE_REPO:
154 if (config->num_enable_repos >= MAX_REPOS)
155 return -ENOBUFS;
156
157 config->enable_repos[config->num_enable_repos++] = optarg;
158 break;
159
160 case ARG_DISABLE_REPO:
161 if (config->num_disable_repos >= MAX_REPOS)
162 return -ENOBUFS;
163
164 config->disable_repos[config->num_disable_repos++] = optarg;
165 break;
166
167 case '?':
101b03bb 168 break;
fa640ef1
MT
169
170 default:
817f7557 171 assert_unreachable();
fa640ef1
MT
172 }
173 }
174
175 return 0;
176}
177
178static void cli_set_repo_enabled(struct pakfire* pakfire, const char* name, int enabled) {
179 struct pakfire_repo* repo = NULL;
180
181 // Find the repository
182 repo = pakfire_get_repo(pakfire, name);
183
184 // Ignore if the repository could not be found
185 if (!repo)
186 return;
187
188 // Set status
189 pakfire_repo_set_enabled(repo, enabled);
190 pakfire_repo_unref(repo);
191}
192
193static FILE* open_distro_config(const char* distro) {
194 char path[PATH_MAX];
195 FILE* f = NULL;
196 int r;
197
198 // XXX hard-coded path
199
200 // Make the path
201 r = snprintf(path, sizeof(path), "/etc/pakfire/distros/%s.conf", distro);
202 if (r < 0)
203 return NULL;
204
205 // Open the configuration file
206 f = fopen(path, "r");
207 if (!f) {
208 switch (errno) {
209 case ENOENT:
210 fprintf(stderr, "Could not find distro '%s': %m\n", distro);
211 break;
212
213 default:
214 break;
215 }
216 }
217
218 return f;
219}
220
221static int setup_pakfire(const struct config* config, struct pakfire** pakfire) {
222 struct pakfire* p = NULL;
223 FILE* f = NULL;
224 int r;
225
226 // Open the distro configuration
227 f = open_distro_config(config->distro);
228 if (!f) {
fa640ef1
MT
229 r = 1;
230 goto ERROR;
231 }
232
233 // Initialize Pakfire
234 r = pakfire_create(&p, NULL, config->arch, f, config->flags, NULL, NULL);
235 if (r)
236 goto ERROR;
237
32bbeefc
MT
238 // Setup progress callback
239 pakfire_set_setup_progress_callback(p, cli_setup_progressbar, NULL);
240
fa640ef1
MT
241 // Enable repositories
242 for (unsigned int i = 0; i < config->num_enable_repos; i++)
243 cli_set_repo_enabled(p, config->enable_repos[i], 1);
244
245 // Disable repositories
246 for (unsigned int i = 0; i < config->num_disable_repos; i++)
247 cli_set_repo_enabled(p, config->disable_repos[i], 0);
248
249 // Return pointer
250 *pakfire = p;
251
252ERROR:
253 if (f)
254 fclose(f);
255
256 return r;
257}
258
259int main(int argc, char* argv[]) {
260 struct pakfire* pakfire = NULL;
261 int r;
262
263 struct config config = {
264 // XXX hard-coded distro
265 .distro = "ipfire3",
266 .arch = NULL,
0d54159f 267 .flags = PAKFIRE_FLAGS_BUILD,
fa640ef1
MT
268 };
269
270 // Parse command line arguments
271 r = parse_argv(&config, argc, argv);
272 if (r)
273 goto ERROR;
274
275 // Setup Pakfire
276 r = setup_pakfire(&config, &pakfire);
277 if (r)
278 goto ERROR;
279
280 // Run a command
101b03bb 281 r = cli_main(pakfire, argc, argv);
fa640ef1
MT
282
283ERROR:
284 if (pakfire)
285 pakfire_unref(pakfire);
286
287 return r;
288}