123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- const builtin = @import("builtin");
- const std = @import("std");
- const fixdeletetree = @import("fixdeletetree.zig");
- const exe_ext = builtin.os.tag.exeFileExt(builtin.cpu.arch);
- pub fn main() !void {
- var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
- const arena = arena_instance.allocator();
- const all_args = try std.process.argsAlloc(arena);
- if (all_args.len < 7) @panic("not enough cmdline args");
- const test_name = all_args[1];
- const add_path_option = all_args[2];
- const in_env_dir = all_args[3];
- const out_env_dir = all_args[4];
- const setup_option = all_args[5];
- const zigup_exe = all_args[6];
- const zigup_args = all_args[7..];
- const add_path = blk: {
- if (std.mem.eql(u8, add_path_option, "--with-path")) break :blk true;
- if (std.mem.eql(u8, add_path_option, "--no-path")) break :blk false;
- std.log.err("expected '--with-path' or '--no-path' but got '{s}'", .{add_path_option});
- std.process.exit(0xff);
- };
- try fixdeletetree.deleteTree(std.fs.cwd(), out_env_dir);
- try std.fs.cwd().makeDir(out_env_dir);
- // make a file named after the test so we can find this directory in the cache
- _ = test_name;
- // {
- // const test_marker_file = try std.fs.path.join(arena, &.{ out_env_dir, test_name});
- // defer arena.free(test_marker_file);
- // var file = try std.fs.cwd().createFile(test_marker_file, .{});
- // defer file.close();
- // try file.writer().print("this file marks this directory as the output for test: {s}\n", .{test_name});
- // }
- const path_link = try std.fs.path.join(arena, &.{ out_env_dir, "zig" ++ exe_ext });
- const install_dir = try std.fs.path.join(arena, &.{ out_env_dir, "install" });
- if (std.mem.eql(u8, in_env_dir, "--no-input-environment")) {
- try std.fs.cwd().makeDir(install_dir);
- } else {
- try copyEnvDir(arena, in_env_dir, out_env_dir, in_env_dir, out_env_dir);
- }
- var maybe_second_bin_dir: ?[]const u8 = null;
- if (std.mem.eql(u8, setup_option, "no-extra-setup")) {
- // nothing extra to setup
- } else if (std.mem.eql(u8, setup_option, "path-link-is-directory")) {
- if (std.fs.cwd().access(path_link, .{})) {
- try std.fs.cwd().deleteFile(path_link);
- } else |err| switch (err) {
- error.FileNotFound => {},
- else => |e| return e,
- }
- try std.fs.cwd().makeDir(path_link);
- } else if (std.mem.eql(u8, setup_option, "another-zig")) {
- maybe_second_bin_dir = try std.fs.path.join(arena, &.{ out_env_dir, "bin2" });
- try std.fs.cwd().makeDir(maybe_second_bin_dir.?);
- const fake_zig = try std.fs.path.join(arena, &.{
- maybe_second_bin_dir.?,
- "zig" ++ comptime builtin.target.exeFileExt(),
- });
- defer arena.free(fake_zig);
- var file = try std.fs.cwd().createFile(fake_zig, .{});
- defer file.close();
- try file.writer().writeAll("a fake executable");
- } else {
- std.log.err("unknown setup option '{s}'", .{setup_option});
- std.process.exit(0xff);
- }
- var argv = std.ArrayList([]const u8).init(arena);
- try argv.append(zigup_exe);
- try argv.append("--path-link");
- try argv.append(path_link);
- try argv.append("--install-dir");
- try argv.append(install_dir);
- try argv.appendSlice(zigup_args);
- var child = std.process.Child.init(argv.items, arena);
- if (add_path) {
- var env_map = try std.process.getEnvMap(arena);
- // make sure the directory with our path-link comes first in PATH
- var new_path = std.ArrayList(u8).init(arena);
- if (maybe_second_bin_dir) |second_bin_dir| {
- try new_path.appendSlice(second_bin_dir);
- try new_path.append(std.fs.path.delimiter);
- }
- try new_path.appendSlice(out_env_dir);
- try new_path.append(std.fs.path.delimiter);
- if (env_map.get("PATH")) |path| {
- try new_path.appendSlice(path);
- }
- try env_map.put("PATH", new_path.items);
- child.env_map = &env_map;
- } else if (maybe_second_bin_dir) |_| @panic("invalid config");
- try child.spawn();
- const result = try child.wait();
- switch (result) {
- .Exited => |c| std.process.exit(c),
- else => |sig| {
- std.log.err("zigup terminated from '{s}' with {}", .{ @tagName(result), sig });
- std.process.exit(0xff);
- },
- }
- }
- fn copyEnvDir(
- allocator: std.mem.Allocator,
- in_root: []const u8,
- out_root: []const u8,
- in_path: []const u8,
- out_path: []const u8,
- ) !void {
- var in_dir = try std.fs.cwd().openDir(in_path, .{ .iterate = true });
- defer in_dir.close();
- var it = in_dir.iterate();
- while (try it.next()) |entry| {
- const in_sub_path = try std.fs.path.join(allocator, &.{ in_path, entry.name });
- defer allocator.free(in_sub_path);
- const out_sub_path = try std.fs.path.join(allocator, &.{ out_path, entry.name });
- defer allocator.free(out_sub_path);
- switch (entry.kind) {
- .directory => {
- try std.fs.cwd().makeDir(out_sub_path);
- try copyEnvDir(allocator, in_root, out_root, in_sub_path, out_sub_path);
- },
- .file => try std.fs.cwd().copyFile(in_sub_path, std.fs.cwd(), out_sub_path, .{}),
- .sym_link => {
- var target_buf: [std.fs.max_path_bytes]u8 = undefined;
- const in_target = try std.fs.cwd().readLink(in_sub_path, &target_buf);
- var out_target_buf: [std.fs.max_path_bytes]u8 = undefined;
- const out_target = blk: {
- if (std.fs.path.isAbsolute(in_target)) {
- if (!std.mem.startsWith(u8, in_target, in_root)) std.debug.panic(
- "expected symlink target to start with '{s}' but got '{s}'",
- .{ in_root, in_target },
- );
- break :blk try std.fmt.bufPrint(
- &out_target_buf,
- "{s}{s}",
- .{ out_root, in_target[in_root.len..] },
- );
- }
- break :blk in_target;
- };
- if (builtin.os.tag == .windows) @panic(
- "we got a symlink on windows?",
- ) else try std.posix.symlink(out_target, out_sub_path);
- },
- else => std.debug.panic("copy {}", .{entry}),
- }
- }
- }
|