mirror of
https://github.com/ziglang/zig.git
synced 2026-01-01 11:03:11 +00:00
Support symlinks for git+http(s) dependencies
This commit is contained in:
parent
21181181bf
commit
573a13f8be
@ -778,7 +778,7 @@ pub const ReadableResource = struct {
|
||||
.tar => try unpackTarball(allocator, prog_reader.reader(), tmp_directory.handle, dep_location_tok, report),
|
||||
.@"tar.gz" => try unpackTarballCompressed(allocator, prog_reader, tmp_directory.handle, dep_location_tok, report, std.compress.gzip),
|
||||
.@"tar.xz" => try unpackTarballCompressed(allocator, prog_reader, tmp_directory.handle, dep_location_tok, report, std.compress.xz),
|
||||
.git_pack => try unpackGitPack(allocator, &prog_reader, git.parseOid(rr.path) catch unreachable, tmp_directory.handle),
|
||||
.git_pack => try unpackGitPack(allocator, &prog_reader, git.parseOid(rr.path) catch unreachable, tmp_directory.handle, dep_location_tok, report),
|
||||
}
|
||||
} else {
|
||||
// Recursive directory copy.
|
||||
@ -1220,6 +1220,8 @@ fn unpackGitPack(
|
||||
reader: anytype,
|
||||
want_oid: git.Oid,
|
||||
out_dir: fs.Dir,
|
||||
dep_location_tok: std.zig.Ast.TokenIndex,
|
||||
report: Report,
|
||||
) !void {
|
||||
// The .git directory is used to store the packfile and associated index, but
|
||||
// we do not attempt to replicate the exact structure of a real .git
|
||||
@ -1251,7 +1253,32 @@ fn unpackGitPack(
|
||||
checkout_prog_node.activate();
|
||||
var repository = try git.Repository.init(gpa, pack_file, index_file);
|
||||
defer repository.deinit();
|
||||
try repository.checkout(out_dir, want_oid);
|
||||
var diagnostics: git.Diagnostics = .{ .allocator = gpa };
|
||||
defer diagnostics.deinit();
|
||||
try repository.checkout(out_dir, want_oid, &diagnostics);
|
||||
|
||||
if (diagnostics.errors.items.len > 0) {
|
||||
const notes_len: u32 = @intCast(diagnostics.errors.items.len);
|
||||
try report.addErrorWithNotes(notes_len, .{
|
||||
.tok = dep_location_tok,
|
||||
.off = 0,
|
||||
.msg = "unable to unpack packfile",
|
||||
});
|
||||
const eb = report.error_bundle;
|
||||
const notes_start = try eb.reserveNotes(notes_len);
|
||||
for (diagnostics.errors.items, notes_start..) |item, note_i| {
|
||||
switch (item) {
|
||||
.unable_to_create_sym_link => |info| {
|
||||
eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{
|
||||
.msg = try eb.printString("unable to create symlink from '{s}' to '{s}': {s}", .{
|
||||
info.file_name, info.link_name, @errorName(info.code),
|
||||
}),
|
||||
}));
|
||||
},
|
||||
}
|
||||
}
|
||||
return error.InvalidGitPack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
53
src/git.zig
53
src/git.zig
@ -38,6 +38,32 @@ test parseOid {
|
||||
try testing.expectError(error.InvalidOid, parseOid("HEAD"));
|
||||
}
|
||||
|
||||
pub const Diagnostics = struct {
|
||||
allocator: Allocator,
|
||||
errors: std.ArrayListUnmanaged(Error) = .{},
|
||||
|
||||
pub const Error = union(enum) {
|
||||
unable_to_create_sym_link: struct {
|
||||
code: anyerror,
|
||||
file_name: []const u8,
|
||||
link_name: []const u8,
|
||||
},
|
||||
};
|
||||
|
||||
pub fn deinit(d: *Diagnostics) void {
|
||||
for (d.errors.items) |item| {
|
||||
switch (item) {
|
||||
.unable_to_create_sym_link => |info| {
|
||||
d.allocator.free(info.file_name);
|
||||
d.allocator.free(info.link_name);
|
||||
},
|
||||
}
|
||||
}
|
||||
d.errors.deinit(d.allocator);
|
||||
d.* = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Repository = struct {
|
||||
odb: Odb,
|
||||
|
||||
@ -55,6 +81,7 @@ pub const Repository = struct {
|
||||
repository: *Repository,
|
||||
worktree: std.fs.Dir,
|
||||
commit_oid: Oid,
|
||||
diagnostics: *Diagnostics,
|
||||
) !void {
|
||||
try repository.odb.seekOid(commit_oid);
|
||||
const tree_oid = tree_oid: {
|
||||
@ -62,7 +89,7 @@ pub const Repository = struct {
|
||||
if (commit_object.type != .commit) return error.NotACommit;
|
||||
break :tree_oid try getCommitTree(commit_object.data);
|
||||
};
|
||||
try repository.checkoutTree(worktree, tree_oid);
|
||||
try repository.checkoutTree(worktree, tree_oid, "", diagnostics);
|
||||
}
|
||||
|
||||
/// Checks out the tree at `tree_oid` to `worktree`.
|
||||
@ -70,6 +97,8 @@ pub const Repository = struct {
|
||||
repository: *Repository,
|
||||
dir: std.fs.Dir,
|
||||
tree_oid: Oid,
|
||||
current_path: []const u8,
|
||||
diagnostics: *Diagnostics,
|
||||
) !void {
|
||||
try repository.odb.seekOid(tree_oid);
|
||||
const tree_object = try repository.odb.readObject();
|
||||
@ -87,7 +116,9 @@ pub const Repository = struct {
|
||||
try dir.makeDir(entry.name);
|
||||
var subdir = try dir.openDir(entry.name, .{});
|
||||
defer subdir.close();
|
||||
try repository.checkoutTree(subdir, entry.oid);
|
||||
const sub_path = try std.fs.path.join(repository.odb.allocator, &.{ current_path, entry.name });
|
||||
defer repository.odb.allocator.free(sub_path);
|
||||
try repository.checkoutTree(subdir, entry.oid, sub_path, diagnostics);
|
||||
},
|
||||
.file => {
|
||||
var file = try dir.createFile(entry.name, .{});
|
||||
@ -98,7 +129,23 @@ pub const Repository = struct {
|
||||
try file.writeAll(file_object.data);
|
||||
try file.sync();
|
||||
},
|
||||
.symlink => return error.SymlinkNotSupported,
|
||||
.symlink => {
|
||||
try repository.odb.seekOid(entry.oid);
|
||||
var symlink_object = try repository.odb.readObject();
|
||||
if (symlink_object.type != .blob) return error.InvalidFile;
|
||||
const link_name = symlink_object.data;
|
||||
dir.symLink(link_name, entry.name, .{}) catch |e| {
|
||||
const file_name = try std.fs.path.join(diagnostics.allocator, &.{ current_path, entry.name });
|
||||
errdefer diagnostics.allocator.free(file_name);
|
||||
const link_name_dup = try diagnostics.allocator.dupe(u8, link_name);
|
||||
errdefer diagnostics.allocator.free(link_name_dup);
|
||||
try diagnostics.errors.append(diagnostics.allocator, .{ .unable_to_create_sym_link = .{
|
||||
.code = e,
|
||||
.file_name = file_name,
|
||||
.link_name = link_name_dup,
|
||||
} });
|
||||
};
|
||||
},
|
||||
.gitlink => {
|
||||
// Consistent with git archive behavior, create the directory but
|
||||
// do nothing else
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user