]> git.ipfire.org Git - pakfire.git/blame - src/cli/lib/build.c
cli: Check for root privileges when needed
[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
MT
30
31#include <pakfire/build.h>
32#include <pakfire/pakfire.h>
33
ee8a3a64
MT
34#define MAX_MAKEFILES 32
35
060a1182
MT
36struct config {
37 const char* id;
38 const char* target;
39 int flags;
ee8a3a64
MT
40
41 // Makefiles
42 char* makefiles[MAX_MAKEFILES];
43 unsigned int num_makefiles;
060a1182
MT
44};
45
ee8a3a64
MT
46enum {
47 OPT_DISABLE_CCACHE = 1,
48 OPT_DISABLE_SNAPSHOT = 2,
49 OPT_DISABLE_TESTS = 3,
50 OPT_ID = 4,
51 OPT_NON_INTERACTIVE = 5,
52 OPT_TARGET = 6,
53};
060a1182 54
ee8a3a64
MT
55static struct argp_option options[] = {
56 { "disable-ccache", OPT_DISABLE_CCACHE, NULL, 0, "Disable the ccache", 0 },
57 { "disable-snapshot", OPT_DISABLE_SNAPSHOT, NULL, 0, "Do not use the snapshot", 0 },
58 { "disable-tests", OPT_DISABLE_TESTS, NULL, 0, "Do not run tests", 0 },
59 { "id", OPT_ID, "ID", 0, "Use this build ID", 1 },
60 { "non-interactive", OPT_NON_INTERACTIVE, NULL, 0, "Run the build non-interactively", 0 },
61 { "target", OPT_TARGET, "TARGET", 0, "Output all packages into this directory", 0 },
62 { NULL },
63};
060a1182 64
d673ca6c 65static error_t parse(int key, char* arg, struct argp_state* state, void* data) {
ee8a3a64 66 struct config* config = data;
060a1182 67
ee8a3a64
MT
68 switch (key) {
69 case OPT_DISABLE_CCACHE:
70 config->flags |= PAKFIRE_BUILD_DISABLE_CCACHE;
060a1182
MT
71 break;
72
ee8a3a64
MT
73 case OPT_DISABLE_SNAPSHOT:
74 config->flags |= PAKFIRE_BUILD_DISABLE_SNAPSHOT;
75 break;
060a1182 76
ee8a3a64
MT
77 case OPT_DISABLE_TESTS:
78 config->flags |= PAKFIRE_BUILD_DISABLE_TESTS;
79 break;
060a1182 80
ee8a3a64
MT
81 case OPT_ID:
82 config->id = arg;
83 break;
060a1182 84
ee8a3a64
MT
85 case OPT_NON_INTERACTIVE:
86 config->flags &= ~PAKFIRE_BUILD_INTERACTIVE;
87 break;
060a1182 88
ee8a3a64
MT
89 case OPT_TARGET:
90 config->target = arg;
91 break;
060a1182 92
ee8a3a64
MT
93 case ARGP_KEY_ARG:
94 if (config->num_makefiles >= MAX_MAKEFILES)
95 return -ENOBUFS;
060a1182 96
ee8a3a64
MT
97 config->makefiles[config->num_makefiles++] = arg;
98 break;
060a1182 99
ee8a3a64
MT
100 default:
101 return ARGP_ERR_UNKNOWN;
060a1182
MT
102 }
103
104 return 0;
105}
106
dc173159
MT
107static int log_callback(struct pakfire_build* build, void* data,
108 int priority, int error, const char* file, int line, const char* function, const char* format, ...) {
109 char* buffer = NULL;
110 va_list args;
111 int r;
112
113 // Format the message
114 va_start(args, format);
115 r = vasprintf(&buffer, format, args);
116 va_end(args);
117
118 // Fail if we could not format the message
119 if (r < 0)
120 return r;
121
6bda496c 122 switch (priority) {
dc173159 123 // Highlight any error messages
6bda496c 124 case LOG_ERR:
dc173159 125 fprintf(stderr, "%s%s%s", color_highlight(), buffer, color_reset());
6bda496c
MT
126 break;
127
dc173159 128 // Print the rest to stdout
6bda496c 129 default:
dc173159 130 fprintf(stdout, "%s", buffer);
6bda496c
MT
131 break;
132 }
133
dc173159
MT
134 // Cleanup
135 if (buffer)
136 free(buffer);
137
6bda496c
MT
138 return 0;
139}
140
ee8a3a64
MT
141int cli_build(void* data, int argc, char* argv[]) {
142 struct pakfire* pakfire = NULL;
060a1182
MT
143 struct pakfire_build* build = NULL;
144 struct config config = {
145 .id = NULL,
146 .target = NULL,
147 .flags = PAKFIRE_BUILD_INTERACTIVE,
148 };
149 int r;
150
ee8a3a64
MT
151 struct cli_config* cli_config = data;
152
153 // Parse the command line
9b8d2c6e 154 r = cli_parse(options, NULL, NULL, NULL, parse, 0, argc, argv, &config);
060a1182 155 if (r)
ee8a3a64
MT
156 goto ERROR;
157
158 // Setup pakfire
159 r = cli_setup_pakfire(&pakfire, cli_config);
160 if (r)
161 goto ERROR;
060a1182
MT
162
163 // Setup the build environment
164 r = pakfire_build_create(&build, pakfire, config.id, config.flags);
165 if (r) {
166 fprintf(stderr, "Could not setup the build environment: %m\n");
167 goto ERROR;
168 }
169
6bda496c
MT
170 // Set log callback
171 pakfire_build_set_log_callback(build, log_callback, NULL);
172
060a1182
MT
173 // Set target
174 if (config.target) {
175 r = pakfire_build_set_target(build, config.target);
176 if (r) {
177 fprintf(stderr, "Could not set target directory %s: %m\n", config.target);
178 goto ERROR;
179 }
180 }
181
182 // Process all packages
ee8a3a64 183 for (unsigned int i = 0; i < config.num_makefiles; i++) {
060a1182 184 // Run the build
ee8a3a64 185 r = pakfire_build_exec(build, config.makefiles[i]);
060a1182 186 if (r) {
ee8a3a64 187 fprintf(stderr, "Could not build %s\n", config.makefiles[i]);
060a1182
MT
188 goto ERROR;
189 }
190 }
191
192ERROR:
193 if (build)
194 pakfire_build_unref(build);
ee8a3a64
MT
195 if (pakfire)
196 pakfire_unref(pakfire);
060a1182
MT
197
198 return r;
199}