]> git.ipfire.org Git - pakfire.git/blame - src/cli/lib/build.c
cli: Show the repo description when listing repositories
[pakfire.git] / src / cli / lib / build.c
CommitLineData
060a1182
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
ee8a3a64 21#include <argp.h>
060a1182 22#include <errno.h>
060a1182 23#include <stdlib.h>
6bda496c 24#include <sys/syslog.h>
060a1182
MT
25
26#include "build.h"
6bda496c 27#include "color.h"
060a1182 28#include "command.h"
ee8a3a64 29#include "pakfire.h"
060a1182 30
3c486a7f 31#include <pakfire/archive.h>
060a1182 32#include <pakfire/build.h>
18ac96e3 33#include <pakfire/log_file.h>
3c486a7f 34#include <pakfire/package.h>
e0ad83d5 35#include <pakfire/root.h>
3c486a7f
MT
36#include <pakfire/path.h>
37#include <pakfire/repo.h>
060a1182 38
ee8a3a64
MT
39#define MAX_MAKEFILES 32
40
343d9736 41struct cli_local_args {
90566df0 42 const char* distro;
060a1182 43 const char* target;
842bd2ba
MT
44 enum {
45 BUILD_INTERACTIVE = (1 << 0),
46 BUILD_ENABLE_CCACHE = (1 << 1),
47 BUILD_ENABLE_SNAPSHOT = (1 << 2),
48 BUILD_ENABLE_TESTS = (1 << 3),
49 } flags;
ee8a3a64 50
18ac96e3 51 // Log file
bd7d97a7 52 pakfire_log_file* log_file;
18ac96e3
MT
53 const char* log_path;
54
ee8a3a64
MT
55 // Makefiles
56 char* makefiles[MAX_MAKEFILES];
57 unsigned int num_makefiles;
060a1182
MT
58};
59
ee8a3a64 60enum {
24e9c0e0
MT
61 OPT_DISABLE_CCACHE = 1,
62 OPT_DISABLE_SNAPSHOT = 2,
63 OPT_DISABLE_TESTS = 3,
18ac96e3
MT
64 OPT_LOG_FILE = 4,
65 OPT_NON_INTERACTIVE = 5,
66 OPT_TARGET = 6,
ee8a3a64 67};
060a1182 68
ee8a3a64
MT
69static struct argp_option options[] = {
70 { "disable-ccache", OPT_DISABLE_CCACHE, NULL, 0, "Disable the ccache", 0 },
71 { "disable-snapshot", OPT_DISABLE_SNAPSHOT, NULL, 0, "Do not use the snapshot", 0 },
72 { "disable-tests", OPT_DISABLE_TESTS, NULL, 0, "Do not run tests", 0 },
18ac96e3 73 { "log-file", OPT_LOG_FILE, "PATH", 0, "Writes the log to a file", 0 },
ee8a3a64
MT
74 { "non-interactive", OPT_NON_INTERACTIVE, NULL, 0, "Run the build non-interactively", 0 },
75 { "target", OPT_TARGET, "TARGET", 0, "Output all packages into this directory", 0 },
76 { NULL },
77};
060a1182 78
d673ca6c 79static error_t parse(int key, char* arg, struct argp_state* state, void* data) {
343d9736 80 struct cli_local_args* args = data;
060a1182 81
ee8a3a64
MT
82 switch (key) {
83 case OPT_DISABLE_CCACHE:
343d9736 84 args->flags &= ~BUILD_ENABLE_CCACHE;
060a1182
MT
85 break;
86
ee8a3a64 87 case OPT_DISABLE_SNAPSHOT:
343d9736 88 args->flags &= ~BUILD_ENABLE_SNAPSHOT;
ee8a3a64 89 break;
060a1182 90
ee8a3a64 91 case OPT_DISABLE_TESTS:
343d9736 92 args->flags &= ~BUILD_ENABLE_TESTS;
ee8a3a64 93 break;
060a1182 94
18ac96e3
MT
95 case OPT_LOG_FILE:
96 args->log_path = arg;
97 break;
98
ee8a3a64 99 case OPT_NON_INTERACTIVE:
343d9736 100 args->flags &= ~BUILD_INTERACTIVE;
ee8a3a64 101 break;
060a1182 102
ee8a3a64 103 case OPT_TARGET:
343d9736 104 args->target = arg;
ee8a3a64 105 break;
060a1182 106
ee8a3a64 107 case ARGP_KEY_ARG:
343d9736 108 if (args->num_makefiles >= MAX_MAKEFILES)
ee8a3a64 109 return -ENOBUFS;
060a1182 110
343d9736 111 args->makefiles[args->num_makefiles++] = arg;
ee8a3a64 112 break;
060a1182 113
ee8a3a64
MT
114 default:
115 return ARGP_ERR_UNKNOWN;
060a1182
MT
116 }
117
118 return 0;
119}
120
d5b92ec9
MT
121static void log_callback(void* data, int priority, const char* file, int line,
122 const char* function, const char* format, va_list args)
123 __attribute__((format(printf, 6, 0)));
124
e0e57930
MT
125static void log_callback(void* data, int priority, const char* file, int line,
126 const char* function, const char* format, va_list args) {
18ac96e3
MT
127 const struct cli_local_args* local_args = data;
128 char* buffer = NULL;
129 ssize_t length;
18ac96e3
MT
130
131 // Format the line
132 length = vasprintf(&buffer, format, args);
133 if (length < 0)
134 return;
dc173159 135
6bda496c 136 switch (priority) {
1ac9f900
MT
137 // Highlight any warnings
138 case LOG_WARNING:
139 fputs(color_yellow(), stderr);
18ac96e3 140 fprintf(stderr, "%s", buffer);
1ac9f900
MT
141 fputs(color_reset(), stderr);
142 break;
143
bde60bc5
MT
144 // Highlight any error messages
145 case LOG_ERR:
146 fputs(color_highlight(), stderr);
18ac96e3 147 fprintf(stderr, "%s", buffer);
bde60bc5 148 fputs(color_reset(), stderr);
6bda496c 149 break;
cba07c0a
MT
150
151 // Print anything to standard output
152 default:
153 fprintf(stdout, "%s", buffer);
154 break;
6bda496c
MT
155 }
156
18ac96e3
MT
157 // Write to the log file
158 if (local_args->log_file)
fe878bea 159 pakfire_log_file_write(local_args->log_file, priority, buffer, length);
18ac96e3
MT
160
161 if (buffer)
162 free(buffer);
6bda496c
MT
163}
164
c87e1399 165static int result_callback(pakfire_ctx* ctx, pakfire_root* root,
0ecfa7b1 166 pakfire_build* build, pakfire_archive* archive, void* data) {
3c486a7f 167 const struct cli_local_args* local_args = data;
c4d26cd6 168 pakfire_package* pkg = NULL;
21d186ba 169 pakfire_repo* local = NULL;
3c486a7f
MT
170 char path[PATH_MAX];
171 int r;
172
173 // Fetch the package metadata
174 r = pakfire_archive_make_package(archive, NULL, &pkg);
175 if (r < 0)
176 goto ERROR;
177
178 // Fetch NEVRA
179 const char* nevra = pakfire_package_get_string(pkg, PAKFIRE_PKG_NEVRA);
180
181 // Fetch the local repository & import the archive
c87e1399 182 local = pakfire_root_get_repo(root, PAKFIRE_REPO_LOCAL);
3c486a7f 183 if (local) {
84337f75 184 r = pakfire_repo_import_archive(local, archive, NULL);
3c486a7f
MT
185 if (r < 0) {
186 ERROR(ctx, "Could not import %s to the local repository: %s\n",
187 nevra, strerror(-r));
188 goto ERROR;
189 }
190 }
191
192 // Copy to the target (if given)
193 if (local_args->target) {
194 // Fetch the filename
195 const char* filename = pakfire_package_get_filename(pkg);
196
197 // Make the absolute target path
198 r = pakfire_path_append(path, local_args->target, filename);
199 if (r < 0)
200 goto ERROR;
201
202 // Copy (or link) the package to the target path
203 r = pakfire_archive_link_or_copy(archive, path);
204 if (r < 0) {
205 ERROR(ctx, "Could not copy %s to %s: %s\n",
206 nevra, path, strerror(-r));
207 goto ERROR;
208 }
209 }
210
211ERROR:
212 if (local)
213 pakfire_repo_unref(local);
214 if (pkg)
215 pakfire_package_unref(pkg);
216
217 return r;
218}
219
ee8a3a64 220int cli_build(void* data, int argc, char* argv[]) {
343d9736
MT
221 struct cli_global_args* global_args = data;
222 struct cli_local_args local_args = {
842bd2ba
MT
223 .flags =
224 BUILD_INTERACTIVE |
225 BUILD_ENABLE_CCACHE |
226 BUILD_ENABLE_SNAPSHOT |
227 BUILD_ENABLE_TESTS,
060a1182 228 };
0ecfa7b1 229 pakfire_build* build = NULL;
6e68f7a8 230 int flags = PAKFIRE_BUILD_LOCAL;
060a1182
MT
231 int r;
232
ee8a3a64 233 // Parse the command line
343d9736 234 r = cli_parse(options, NULL, NULL, NULL, parse, 0, argc, argv, &local_args);
060a1182 235 if (r)
ee8a3a64
MT
236 goto ERROR;
237
e0e57930 238 // Replace the logger
18ac96e3 239 pakfire_ctx_set_log_callback(global_args->ctx, log_callback, &local_args);
e0e57930 240
eccc1d5b 241 // Use the snapshot?
343d9736 242 if (local_args.flags & BUILD_ENABLE_SNAPSHOT)
d8751c8d 243 flags |= PAKFIRE_BUILD_ENABLE_SNAPSHOT;
060a1182 244
842bd2ba 245 // Is the build interactive?
343d9736 246 if (local_args.flags & BUILD_INTERACTIVE)
2a81deb4 247 flags |= PAKFIRE_BUILD_INTERACTIVE;
842bd2ba
MT
248
249 // Enable ccache?
343d9736 250 if (!(local_args.flags & BUILD_ENABLE_CCACHE))
d8751c8d 251 flags |= PAKFIRE_BUILD_DISABLE_CCACHE;
842bd2ba
MT
252
253 // Enable tests?
343d9736 254 if (!(local_args.flags & BUILD_ENABLE_TESTS))
d8751c8d 255 flags |= PAKFIRE_BUILD_DISABLE_TESTS;
90566df0 256
18ac96e3
MT
257 // Create the log file
258 if (local_args.log_path) {
259 r = pakfire_log_file_create(&local_args.log_file,
260 global_args->ctx, local_args.log_path, NULL, 0);
261 if (r < 0)
262 goto ERROR;
263 }
264
060a1182 265 // Setup the build environment
d8751c8d
MT
266 r = cli_setup_build(&build, global_args, flags);
267 if (r < 0)
060a1182 268 goto ERROR;
060a1182 269
060a1182 270 // Process all packages
343d9736 271 for (unsigned int i = 0; i < local_args.num_makefiles; i++) {
060a1182 272 // Run the build
3c486a7f 273 r = pakfire_build_exec(build, local_args.makefiles[i], result_callback, &local_args);
060a1182 274 if (r) {
343d9736 275 fprintf(stderr, "Could not build %s\n", local_args.makefiles[i]);
060a1182
MT
276 goto ERROR;
277 }
278 }
279
280ERROR:
18ac96e3
MT
281 if (local_args.log_file)
282 pakfire_log_file_unref(local_args.log_file);
060a1182
MT
283 if (build)
284 pakfire_build_unref(build);
285
286 return r;
287}