summaryrefslogtreecommitdiff
path: root/src/Config.zig
diff options
context:
space:
mode:
authorGravatar Uko Kokņevičs2022-04-28 15:27:11 +0300
committerGravatar Uko Kokņevičs2022-04-28 15:29:33 +0300
commit53af0877444ea6c14b1ad5baec94afbeebc5e5e0 (patch)
tree837fba9d78c895243f598c95916bff4a4c56f609 /src/Config.zig
parentAdd Installation.isActive, use it (diff)
downloadzup-53af0877444ea6c14b1ad5baec94afbeebc5e5e0.tar.gz
zup-53af0877444ea6c14b1ad5baec94afbeebc5e5e0.tar.xz
zup-53af0877444ea6c14b1ad5baec94afbeebc5e5e0.zip
Added support for config files
Diffstat (limited to 'src/Config.zig')
-rw-r--r--src/Config.zig92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/Config.zig b/src/Config.zig
new file mode 100644
index 0000000..a7affa0
--- /dev/null
+++ b/src/Config.zig
@@ -0,0 +1,92 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const xdg = @import("xdg");
4
5const Allocator = std.mem.Allocator;
6const ArrayList = std.ArrayList;
7const Config = @This();
8const CrossTarget = std.zig.CrossTarget;
9const File = std.fs.File;
10const NativeTargetInfo = std.zig.system.NativeTargetInfo;
11const Target = std.Target;
12
13allocator: Allocator,
14/// Earlier in the list means more preferred.
15supported_targets: ArrayList(Target),
16
17pub fn init(allocator: Allocator) !Config {
18 var self = Config{
19 .allocator = allocator,
20 .supported_targets = ArrayList(Target).init(allocator),
21 };
22 errdefer self.deinit();
23
24 // Native target is always supported and at highest priority
25 try self.supported_targets.append(builtin.target);
26
27 const config_dirs = try xdg.getAllConfigDirs(allocator, "zup");
28 defer {
29 for (config_dirs) |s| allocator.free(s);
30 allocator.free(config_dirs);
31 }
32
33 for (config_dirs) |config_dir| {
34 const file_name = try std.fs.path.join(allocator, &.{ config_dir, "zup.json" });
35 defer allocator.free(file_name);
36 var file = std.fs.openFileAbsolute(file_name, .{}) catch |err| {
37 if (err == error.FileNotFound) {
38 continue;
39 } else {
40 return err;
41 }
42 };
43 defer file.close();
44
45 try self.readConfig(file);
46 }
47
48 return self;
49}
50
51pub fn deinit(self: *Config) void {
52 self.supported_targets.deinit();
53
54 self.* = undefined;
55}
56
57fn readConfig(self: *Config, file: File) !void {
58 const allocator = self.allocator;
59 const reader = file.reader();
60
61 var json_str = try reader.readAllAlloc(allocator, std.math.maxInt(u64));
62 defer allocator.free(json_str);
63
64 var parser = std.json.Parser.init(allocator, false);
65 defer parser.deinit();
66
67 var vt = try parser.parse(json_str);
68 defer vt.deinit();
69
70 if (vt.root != .Object) {
71 std.log.warn("Failed at reading config, root isn't object.", .{});
72 return;
73 }
74
75 if (vt.root.Object.get("supported_targets")) |supported_targets| blk: {
76 if (supported_targets != .Array) {
77 break :blk;
78 }
79
80 for (supported_targets.Array.items) |supported_target| {
81 if (supported_target != .String) {
82 continue;
83 }
84
85 const cross_target = try CrossTarget.parse(.{
86 .arch_os_abi = supported_target.String,
87 });
88 const native_target_info = try NativeTargetInfo.detect(allocator, cross_target);
89 try self.supported_targets.append(native_target_info.target);
90 }
91 }
92}