summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.org1
-rw-r--r--build.zig3
-rw-r--r--build.zig.zon4
-rw-r--r--src/EasyHttp.zig32
-rw-r--r--src/Installation.zig22
-rw-r--r--src/install.zig30
-rw-r--r--src/main.zig1
7 files changed, 56 insertions, 37 deletions
diff --git a/README.org b/README.org
index f680594..66bec38 100644
--- a/README.org
+++ b/README.org
@@ -9,7 +9,6 @@
9** System libraries 9** System libraries
10 10
11- libarchive 11- libarchive
12- libcurl
13 12
14** Zig version 13** Zig version
15 14
diff --git a/build.zig b/build.zig
index b953275..762eb67 100644
--- a/build.zig
+++ b/build.zig
@@ -14,7 +14,6 @@ pub fn build(b: *Build) void {
14 config.addOption(SemanticVersion, "version", version); 14 config.addOption(SemanticVersion, "version", version);
15 15
16 const clap = b.dependency("clap", .{}); 16 const clap = b.dependency("clap", .{});
17 const curl = b.dependency("curl", .{});
18 const libarchive = b.dependency("libarchive", .{}); 17 const libarchive = b.dependency("libarchive", .{});
19 const xdg = b.dependency("xdg", .{}); 18 const xdg = b.dependency("xdg", .{});
20 19
@@ -27,12 +26,10 @@ pub fn build(b: *Build) void {
27 }); 26 });
28 exe.addOptions("zup-config", config); 27 exe.addOptions("zup-config", config);
29 exe.addModule("clap", clap.module("clap")); 28 exe.addModule("clap", clap.module("clap"));
30 exe.addModule("curl", curl.module("curl"));
31 exe.addModule("libarchive", libarchive.module("libarchive")); 29 exe.addModule("libarchive", libarchive.module("libarchive"));
32 exe.addModule("xdg", xdg.module("xdg")); 30 exe.addModule("xdg", xdg.module("xdg"));
33 exe.linkLibC(); 31 exe.linkLibC();
34 exe.linkSystemLibrary("libarchive"); 32 exe.linkSystemLibrary("libarchive");
35 exe.linkSystemLibrary("libcurl");
36 b.installArtifact(exe); 33 b.installArtifact(exe);
37 34
38 const run_cmd = b.addRunArtifact(exe); 35 const run_cmd = b.addRunArtifact(exe);
diff --git a/build.zig.zon b/build.zig.zon
index 151d3f2..31a3ad8 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -7,10 +7,6 @@
7 .url = "https://github.com/Hejsil/zig-clap/archive/bdb5853b678d68f342ec65b04a6785af522ca6c9.tar.gz", 7 .url = "https://github.com/Hejsil/zig-clap/archive/bdb5853b678d68f342ec65b04a6785af522ca6c9.tar.gz",
8 .hash = "12202af04ec78191f2018458a7be29f54e0d9118f7688e7a226857acf754d68b8473", 8 .hash = "12202af04ec78191f2018458a7be29f54e0d9118f7688e7a226857acf754d68b8473",
9 }, 9 },
10 .curl = .{
11 .url = "https://git.sr.ht/~ukko/zig-curl/archive/aa55a3d061fceebf737c0af25a6df2d05f83bcad.tar.gz",
12 .hash = "12208fc84cbd67383b6fe7e3f65a965cead4577ca27cd59660a2812c9f4edc545c5e",
13 },
14 .libarchive = .{ 10 .libarchive = .{
15 .url = "https://git.sr.ht/~ukko/zig-libarchive/archive/b70c51b8555e68e73c36b0e691dff65c0092baf6.tar.gz", 11 .url = "https://git.sr.ht/~ukko/zig-libarchive/archive/b70c51b8555e68e73c36b0e691dff65c0092baf6.tar.gz",
16 .hash = "12206a8120d9a7550112f2fcc908c46900d6882c95156f900d5e0b39fcdb6a64a065", 12 .hash = "12206a8120d9a7550112f2fcc908c46900d6882c95156f900d5e0b39fcdb6a64a065",
diff --git a/src/EasyHttp.zig b/src/EasyHttp.zig
new file mode 100644
index 0000000..197cf9d
--- /dev/null
+++ b/src/EasyHttp.zig
@@ -0,0 +1,32 @@
1const std = @import("std");
2
3const Allocator = std.mem.Allocator;
4const ArenaAllocator = std.heap.ArenaAllocator;
5const Client = std.http.Client;
6const Headers = std.http.Headers;
7const Reader = Request.Reader;
8const Request = Client.Request;
9const Uri = std.Uri;
10
11pub fn get(parent_allocator: Allocator, uri: Uri) ![]u8 {
12 var arena = ArenaAllocator.init(parent_allocator);
13 defer arena.deinit();
14
15 const allocator = arena.allocator();
16
17 var client = Client{
18 .allocator = allocator,
19 };
20 defer client.deinit();
21
22 var headers = Headers.init(allocator);
23 defer headers.deinit();
24
25 var request = try client.request(.GET, uri, headers, .{});
26 defer request.deinit();
27
28 try request.start();
29 try request.wait();
30
31 return request.reader().readAllAlloc(parent_allocator, std.math.maxInt(usize));
32}
diff --git a/src/Installation.zig b/src/Installation.zig
index 54b870c..8218f23 100644
--- a/src/Installation.zig
+++ b/src/Installation.zig
@@ -1,4 +1,3 @@
1const curl = @import("curl");
2const std = @import("std"); 1const std = @import("std");
3const xdg = @import("xdg"); 2const xdg = @import("xdg");
4const zup = @import("root"); 3const zup = @import("root");
@@ -7,9 +6,11 @@ const Allocator = std.mem.Allocator;
7const ArenaAllocator = std.heap.ArenaAllocator; 6const ArenaAllocator = std.heap.ArenaAllocator;
8const Config = zup.Config; 7const Config = zup.Config;
9const ChildProcess = std.ChildProcess; 8const ChildProcess = std.ChildProcess;
9const EasyHttp = zup.EasyHttp;
10const JsonValue = std.json.Value; 10const JsonValue = std.json.Value;
11const SemanticVersion = std.SemanticVersion; 11const SemanticVersion = std.SemanticVersion;
12const StringHashMap = std.StringHashMap; 12const StringHashMap = std.StringHashMap;
13const Uri = std.Uri;
13 14
14const Installation = @This(); 15const Installation = @This();
15 16
@@ -18,11 +19,12 @@ pub const Installations = StringHashMap(Installation);
18allocator: Allocator, 19allocator: Allocator,
19ver_str: []u8, 20ver_str: []u8,
20version: SemanticVersion, 21version: SemanticVersion,
21url: ?[:0]u8, 22url_str: ?[]u8,
23url: ?Uri,
22 24
23pub fn deinit(self: *Installation) void { 25pub fn deinit(self: *Installation) void {
24 self.allocator.free(self.ver_str); 26 self.allocator.free(self.ver_str);
25 if (self.url) |url| self.allocator.free(url); 27 if (self.url_str) |str| self.allocator.free(str);
26 28
27 self.* = undefined; 29 self.* = undefined;
28} 30}
@@ -118,6 +120,7 @@ pub fn getInstalledList(allocator: Allocator) !Installations {
118 .allocator = allocator, 120 .allocator = allocator,
119 .ver_str = res.stdout, 121 .ver_str = res.stdout,
120 .version = version, 122 .version = version,
123 .url_str = null,
121 .url = null, 124 .url = null,
122 }); 125 });
123 } 126 }
@@ -133,18 +136,21 @@ pub fn isInstalled(allocator: Allocator, name: []const u8) !bool {
133 return true; 136 return true;
134} 137}
135 138
139const index_json_uri = Uri.parse("https://ziglang.org/download/index.json") catch unreachable;
140
136pub fn getAvailableList(config: Config) !Installations { 141pub fn getAvailableList(config: Config) !Installations {
137 var arena = ArenaAllocator.init(config.allocator); 142 var arena = ArenaAllocator.init(config.allocator);
138 defer arena.deinit(); 143 defer arena.deinit();
139 144
140 const allocator = arena.allocator(); 145 const allocator = arena.allocator();
141 146
142 const json_str = try curl.easyDownload(allocator, "https://ziglang.org/download/index.json"); 147 var data = try EasyHttp.get(allocator, index_json_uri);
148 defer allocator.free(data);
143 149
144 const parsed = try std.json.parseFromSliceLeaky( 150 const parsed = try std.json.parseFromSliceLeaky(
145 JsonValue, 151 JsonValue,
146 allocator, 152 allocator,
147 json_str, 153 data,
148 .{}, 154 .{},
149 ); 155 );
150 156
@@ -203,8 +209,9 @@ fn parseInstallation(config: Config, name: []const u8, value: JsonValue) !?Insta
203 if (url_src != .string) { 209 if (url_src != .string) {
204 return error.JsonSchema; 210 return error.JsonSchema;
205 } 211 }
206 var url = try allocator.dupeZ(u8, url_src.string); 212 var url_str = try allocator.dupe(u8, url_src.string);
207 errdefer allocator.free(url); 213 errdefer allocator.free(url_str);
214 const url = try Uri.parse(url_str);
208 215
209 const version_src = if (map.get("version")) |ver| blk: { 216 const version_src = if (map.get("version")) |ver| blk: {
210 if (ver != .string) { 217 if (ver != .string) {
@@ -223,6 +230,7 @@ fn parseInstallation(config: Config, name: []const u8, value: JsonValue) !?Insta
223 .allocator = allocator, 230 .allocator = allocator,
224 .ver_str = ver_str, 231 .ver_str = ver_str,
225 .version = version, 232 .version = version,
233 .url_str = url_str,
226 .url = url, 234 .url = url,
227 }; 235 };
228} 236}
diff --git a/src/install.zig b/src/install.zig
index 2e3efab..a459aa6 100644
--- a/src/install.zig
+++ b/src/install.zig
@@ -1,12 +1,13 @@
1const libarchive = @import("libarchive"); 1const libarchive = @import("libarchive");
2const curl = @import("curl");
3const std = @import("std"); 2const std = @import("std");
4const xdg = @import("xdg"); 3const xdg = @import("xdg");
5const zup = @import("root"); 4const zup = @import("root");
6 5
7const Allocator = std.mem.Allocator; 6const Allocator = std.mem.Allocator;
8const Config = zup.Config;
9const ArchiveRead = libarchive.Read; 7const ArchiveRead = libarchive.Read;
8const ArenaAllocator = std.heap.ArenaAllocator;
9const Config = zup.Config;
10const EasyHttp = zup.EasyHttp;
10const Installation = zup.Installation; 11const Installation = zup.Installation;
11const Installations = zup.Installations; 12const Installations = zup.Installations;
12 13
@@ -51,26 +52,11 @@ pub fn perform(allocator: Allocator, name: []const u8, force: bool, available: I
51 defer allocator.free(installation_dir); 52 defer allocator.free(installation_dir);
52 53
53 std.log.info("Installing {s}, version {}", .{ name, installation.version }); 54 std.log.info("Installing {s}, version {}", .{ name, installation.version });
54 const filename = std.fs.path.basename(installation.url.?);
55
56 // TODO: Platform-agnostic tempfile creation
57 var tmpname = try std.fmt.allocPrintZ(allocator, "/tmp/{s}", .{filename});
58 defer allocator.free(tmpname);
59
60 var tmpdir = try std.fs.openDirAbsolute(std.fs.path.dirname(tmpname).?, .{});
61 defer tmpdir.close();
62
63 var tmpfile = try tmpdir.createFile(filename, .{});
64 defer {
65 tmpfile.close();
66 std.log.info("Deleting /tmp/{s}...", .{filename});
67 tmpdir.deleteFile(filename) catch |err| {
68 std.log.warn("Failed to delete /tmp/{s}: {}", .{ filename, err });
69 };
70 }
71 55
72 std.log.info("Downloading to /tmp/{s}...", .{filename}); 56 std.log.info("Downloading from {s}...", .{installation.url_str.?});
73 try curl.easyDownloadToFile(&tmpfile, installation.url.?); 57
58 var data = try EasyHttp.get(allocator, installation.url.?);
59 defer allocator.free(data);
74 60
75 std.log.info("Extracting...", .{}); 61 std.log.info("Extracting...", .{});
76 var archive = try ArchiveRead.init(); 62 var archive = try ArchiveRead.init();
@@ -78,7 +64,7 @@ pub fn perform(allocator: Allocator, name: []const u8, force: bool, available: I
78 64
79 try archive.supportFilter(.all); 65 try archive.supportFilter(.all);
80 try archive.supportFormat(.all); 66 try archive.supportFormat(.all);
81 try archive.openFilename(tmpname, 10240); 67 try archive.openMemory(data);
82 68
83 while (try archive.nextHeader()) |entry_c| { 69 while (try archive.nextHeader()) |entry_c| {
84 var entry = entry_c; 70 var entry = entry_c;
diff --git a/src/main.zig b/src/main.zig
index 93cd5d4..5522915 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,4 +1,5 @@
1pub const Config = @import("Config.zig"); 1pub const Config = @import("Config.zig");
2pub const EasyHttp = @import("EasyHttp.zig");
2pub const Installation = @import("Installation.zig"); 3pub const Installation = @import("Installation.zig");
3pub const Installations = Installation.Installations; 4pub const Installations = Installation.Installations;
4pub const SubCommand = @import("subcommand.zig").SubCommand; 5pub const SubCommand = @import("subcommand.zig").SubCommand;