Skip to content

Instantly share code, notes, and snippets.

@doccaico
Last active November 9, 2023 01:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save doccaico/cd5108160e1ded01144b67f0026b623b to your computer and use it in GitHub Desktop.
Save doccaico/cd5108160e1ded01144b67f0026b623b to your computer and use it in GitHub Desktop.
Ziglang Updater in Ziglang
// Date: 2023/11/09
// Zig version: 0.12.0-dev.1513+77bc8e7b6
// Build: zig build-exe -Doptimize=ReleaseFast zig_update.zig
// 必要なソフト
// Windows: curl, 7za
// その他(Linux、Macなど): curl, 7z
// zigディレクトリの位置
// Windows: c:\zig
// その他(Linux、Macなど): ~/bin/zig
// Windows上でしかテストしていません
const builtin = @import("builtin");
const std = @import("std");
const ChildProcess = std.ChildProcess;
const fs = std.fs;
const heap = std.heap;
const json = std.json;
const math = std.math;
const mem = std.mem;
const os = std.os;
const print = std.debug.print;
const process = std.process;
const zig_dirname = "zig";
const home_env = if (builtin.os.tag == .windows) "USERPROFILE" else "HOME";
const seven_zip = if (builtin.os.tag == .windows) "7za" else "7z";
const ext = if (builtin.os.tag == .windows) ".zip" else ".tar.xz";
const os_tag = if (builtin.os.tag == .windows)
"x86_64-windows"
else if (builtin.os.tag == .linux)
"x86_64-linux"
else if (builtin.os.tag == .macos)
"x86_64-macos"
else
@compileError("Unsupported OS.");
pub fn main() !void {
var arena_instance = heap.ArenaAllocator.init(heap.page_allocator);
defer arena_instance.deinit();
const arena = arena_instance.allocator();
// ディレクトリを~/Downloadsに変更
const home = try process.getEnvVarOwned(arena, home_env);
const current_dir_path = try fs.path.join(arena, &[_][]const u8{ home, "Downloads" });
try os.chdir(current_dir_path);
// index.jsonをダウンロード
const curl_json = [_][]const u8{ "curl", "-OL", "https://ziglang.org/download/index.json" };
_ = try ChildProcess.run(.{ .allocator = arena, .argv = &curl_json });
// index.jsonを読み込む
const json_path = try fs.path.join(arena, &[_][]const u8{ current_dir_path, "index.json" });
const file = try fs.cwd().readFileAlloc(arena, json_path, math.maxInt(usize));
// index.jsonをパースしてURLを取得
var parsed = try json.parseFromSlice(json.Value, arena, file, .{});
const url =
parsed.value.object.get("master").?.object.get(os_tag).?.object.get("tarball").?.string;
// ファイル(.zip or .tar.xz)をダウンロード
const curl_zig = [_][]const u8{ "curl", "-OL", url };
_ = try ChildProcess.run(.{ .allocator = arena, .argv = &curl_zig });
// URLからファイル名を取得
var iter = mem.splitBackwardsScalar(u8, url, '/');
const filename = iter.next().?;
// ファイルを解凍
// https://qiita.com/h_pon_heapon/items/d7f7d38d11bfe15eebf8
const extraction = [_][]const u8{ seven_zip, "x", "-aoa", filename };
const ret = try ChildProcess.run(.{ .allocator = arena, .argv = &extraction });
print("{s}\n", .{ret.stdout});
// 移動先のパスを決定
const new_path = if (builtin.os.tag == .windows) blk: {
const system_drive = try process.getEnvVarOwned(arena, "SystemDrive");
const path = try fs.path.join(arena, &[_][]const u8{ system_drive, zig_dirname });
break :blk path;
} else blk: {
const path = try fs.path.join(arena, &[_][]const u8{ home, "bin", zig_dirname });
break :blk path;
};
// 既にzigディレクトリが存在すれば削除
try fs.cwd().deleteTree(new_path);
// ファイル名から拡張子(.zip or .tar.xz)を除去
var iter_fn = mem.splitSequence(u8, filename, ext);
const filename_without_ext = iter_fn.next().?;
// zigディレクトリを移動
try os.rename(filename_without_ext, new_path);
// index.jsonとzig-windows-x86_64-0.12.0-dev.1388+d89266569.zipを削除
fs.cwd().deleteFile(json_path) catch {};
fs.cwd().deleteFile(filename) catch {};
}
@rofrol
Copy link

rofrol commented Jul 3, 2023

My fork https://gist.github.com/rofrol/9e7aa84ad027426d46b574359e756017 uses tar as it is available on newer Windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment