Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
##### sorted by Precedence

- zig.ver: A file that contains the zig version, nothing more.
- build.zig.zon: More specifically the minimum_zig_version option
- (zigd directory)/config

### In the config there is also an order
Expand All @@ -49,6 +50,10 @@ default=0.13.0

### Fun fact, if you are in `/home/john/work/some_project/some_deeper_project`, it will still return 0.5.0, because zigd searches for paths recursively! :O

## Build

### `zig build`

## An Example Usage

```
Expand Down
12 changes: 12 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.{
.name = "zigd",
.version = "0.0.2",
.minimum_zig_version = "0.13.0",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"LICENSE",
"README.md",
},
}
14 changes: 14 additions & 0 deletions src/utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ pub inline fn createDirectoryIgnoreExist(path: []const u8) !void {
};
}

pub inline fn existsReadFileCwd(allocator: std.mem.Allocator, cwd_path: []const u8) !?[]u8 {
return std.fs.cwd().readFileAlloc(allocator, cwd_path, std.math.maxInt(usize)) catch |e| switch (e) {
std.fs.File.OpenError.FileNotFound => null,
else => e,
};
}

pub inline fn existsReadFileCwdSentinel(allocator: std.mem.Allocator, cwd_path: [:0]const u8) !?[:0]u8 {
return std.fs.cwd().readFileAllocOptions(allocator, cwd_path, std.math.maxInt(usize), null, 1, 0) catch |e| switch (e) {
std.fs.File.OpenError.FileNotFound => null,
else => e,
};
}

pub inline fn createDirectoryIfNotExist(path: []const u8) !void {
try std.fs.cwd().makePath(path);
}
Expand Down
2 changes: 1 addition & 1 deletion src/zigd.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.1
0.0.2
4 changes: 2 additions & 2 deletions src/zigdcli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn install(allocator: std.mem.Allocator, args: []const []const u8) !void {
}

var zig_version = try zigdcore.ZigVersion.parse(allocator, args[2], &user_arg, false);
defer zig_version.deinitIfMasterOrZigver(allocator);
defer zig_version.deinitIfMasterOrZigverOrZonver(allocator);

try std.io.getStdOut().writer().print("Installing zig version {s}\n", .{zig_version});

Expand Down Expand Up @@ -95,7 +95,7 @@ fn exists(allocator: std.mem.Allocator, args: []const []const u8) !void {
defer allocator.free(zigd_path);

var zig_version = try zigdcore.ZigVersion.parse(allocator, args[2], &user_arg, false);
defer zig_version.deinitIfMasterOrZigver(allocator);
defer zig_version.deinitIfMasterOrZigverOrZonver(allocator);

const version_path = try std.fs.path.join(allocator, &.{ zigd_path, "versions", args[2] });
defer allocator.free(version_path);
Expand Down
19 changes: 10 additions & 9 deletions src/zigdcore.zig
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,19 @@ pub fn install_zig(allocator: std.mem.Allocator, download_url: []const u8, insta
const w_path_duped = try allocator.dupe(u8, w_path.name);
defer allocator.free(w_path_duped);

if ((try tempstrg.next()) != null)
if ((try tempstrg.next()) != null)
return error.InstallationWasSabotaged;

try temporary_storage.rename(w_path_duped, final_destination);
temporary_storage.close();
try std.fs.cwd().deleteDir(temp_name);
} else {
} else {
var final_dest_dir = try std.fs.openDirAbsolute(final_destination, .{});
defer final_dest_dir.close();

var xz_decompressor = try std.compress.xz.decompress(allocator, req.reader());
defer xz_decompressor.deinit();

try std.tar.pipeToFileSystem(final_dest_dir, xz_decompressor.reader(), .{ .strip_components = 1 });
}
return;
Expand Down Expand Up @@ -121,9 +121,10 @@ pub const ZigVersion = struct {

pub const Source = union(enum) {
UserArg, // Zigd Cli exclusive
Zigver,
WorkspaceVer,
DefaultVer,
Zigver, // zig.ver file
Zonver, // build.zig.zon, minimum_zig_version field
WorkspaceVer, // config, path
DefaultVer, // config, default
Master: *Source,
};

Expand Down Expand Up @@ -164,9 +165,9 @@ pub const ZigVersion = struct {
}
}

pub fn deinitIfMasterOrZigver(self: @This(), allocator: std.mem.Allocator) void {
pub fn deinitIfMasterOrZigverOrZonver(self: @This(), allocator: std.mem.Allocator) void {
switch (self.source) {
.Master, .Zigver => allocator.free(self.as_string),
.Master, .Zigver, .Zonver => allocator.free(self.as_string),
else => {},
}
}
Expand All @@ -186,7 +187,7 @@ pub fn getZigdPath(allocator: std.mem.Allocator) ![]u8 {
break :v try std.fs.path.join(allocator, &.{ userprofile, ".zigd" });
}
}

if (env_map.get("HOME")) |home| {
break :v try std.fs.path.join(allocator, &.{ home, ".zigd" });
}
Expand Down
120 changes: 91 additions & 29 deletions src/zigdemu.zig
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,48 @@ pub fn main() !void {
defer config.deinit();

var zig_version: zigdcore.ZigVersion = v: {
const zig_ver = std.fs.cwd().readFileAlloc(allocator, "zig.ver", 1 << 21) catch |e| switch (e) {
std.fs.File.OpenError.FileNotFound => {
const absolute_cwd = try std.fs.cwd().realpathAlloc(allocator, ".");
defer allocator.free(absolute_cwd);

if (config.recursive_search_for_workspace_version(absolute_cwd)) |workspace_version| {
break :v zigdcore.ZigVersion{
.as_string = workspace_version,
.source = .WorkspaceVer,
};
}

if (config.default) |default_version| {
break :v zigdcore.ZigVersion{
.as_string = default_version,
.source = .DefaultVer,
};
}

std.log.err("No default, workspace, or zig.ver version was found.", .{});
return;
},
else => return e,
};
if (try utils.existsReadFileCwd(allocator, "zig.ver")) |zig_ver| {
// Can't error so no need for errdefer in this scope
break :v zigdcore.ZigVersion{
.as_string = zig_ver,
.source = .Zigver,
};
}

break :v zigdcore.ZigVersion{
.as_string = zig_ver,
.source = .Zigver,
};
if (try utils.existsReadFileCwdSentinel(allocator, "build.zig.zon")) |build_zig_zon| {
defer allocator.free(build_zig_zon);

if (try zon_minimum_version(allocator, build_zig_zon)) |zonver| {
break :v zigdcore.ZigVersion{
.as_string = zonver,
.source = .Zonver,
};
}
}

const absolute_cwd = try std.fs.cwd().realpathAlloc(allocator, ".");
defer allocator.free(absolute_cwd);

if (config.recursive_search_for_workspace_version(absolute_cwd)) |workspace_version| {
break :v zigdcore.ZigVersion{
.as_string = workspace_version,
.source = .WorkspaceVer,
};
}

if (config.default) |default_version| {
break :v zigdcore.ZigVersion{
.as_string = default_version,
.source = .DefaultVer,
};
}

std.log.err("No default, workspace, or zig.ver version was found.", .{});
return;
};

zig_version = try zigdcore.ZigVersion.parse(allocator, zig_version.as_string, &zig_version.source, true);
defer zig_version.deinitIfMasterOrZigver(allocator);
defer zig_version.deinitIfMasterOrZigverOrZonver(allocator);

const zig_binary_path = try std.fs.path.join(allocator, &.{ zigd_path, "versions", zig_version.as_string, "zig" ++ utils.binary_ext });
defer allocator.free(zig_binary_path);
Expand Down Expand Up @@ -176,3 +185,56 @@ const Config = struct {
self.allocator.free(self.contents);
}
};

// Caller frees the returned memory
fn zon_minimum_version(allocator: std.mem.Allocator, zon_contents: [:0]u8) !?[]const u8 {
var ast = try std.zig.Ast.parse(allocator, zon_contents, .zon);
defer ast.deinit(allocator);

var ast_buf: [2]std.zig.Ast.Node.Index = undefined;
const root = ast.fullStructInit(&ast_buf, ast.nodes.items(.data)[0].lhs) orelse return error.ZonParseError;

for (root.ast.fields) |field_idx| {
const field_name = try parseFieldName(allocator, ast, field_idx);
defer allocator.free(field_name);

if (std.mem.eql(u8, field_name, "minimum_zig_version")) {
return try parseString(allocator, ast, field_idx);
}
}

return null;
}

// Caller frees memory
fn parseString(allocator: std.mem.Allocator, ast: std.zig.Ast, idx: std.zig.Ast.Node.Index) ![]const u8 {
const node_tags = ast.nodes.items(.tag);
const main_tokens = ast.nodes.items(.main_token);
if (node_tags[idx] != .string_literal) {
return error.ExpectedStringLiteral;
}
const str_lit_token = main_tokens[idx];
const token_bytes = ast.tokenSlice(str_lit_token);
return try parseStrLit(allocator, token_bytes, 0);
}

// Caller frees memory
inline fn parseStrLit(
allocator: std.mem.Allocator,
bytes: []const u8,
offset: u32,
) ![]u8 {
return try std.zig.string_literal.parseAlloc(allocator, bytes[offset..]);
}

fn parseFieldName(
alloc: std.mem.Allocator,
ast: std.zig.Ast,
idx: std.zig.Ast.Node.Index,
) ![]const u8 {
const name = ast.tokenSlice(ast.firstToken(idx) - 2);
return if (name[0] == '@') // Escaping something, like @"hello bois"
try std.zig.string_literal.parseAlloc(alloc, name[1..])
else
try alloc.dupe(u8, name);
}