Initial Commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
./index
|
||||||
|
.zig-cache
|
||||||
|
zig-out
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "xpk",
|
||||||
|
.root_module = b.createModule(.{ .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize }),
|
||||||
|
});
|
||||||
|
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.{
|
||||||
|
.name = .xpk,
|
||||||
|
.version = "0.0.0",
|
||||||
|
|
||||||
|
.fingerprint = 0x50fc21dcc3f3cc25,
|
||||||
|
.minimum_zig_version = "0.16.0",
|
||||||
|
.dependencies = .{},
|
||||||
|
|
||||||
|
.paths = .{ "build.zig", "build.zig.zon", "src", ".gitignore" },
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
description A small example package
|
||||||
|
license MIT
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
pub const installed_directory = "./installed";
|
||||||
|
pub const index_directory = "./index";
|
||||||
|
|
||||||
|
pub const arch = "x86_64";
|
||||||
|
|
||||||
|
pub const repos = .{
|
||||||
|
.main = "http://localhost:3000",
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const config = @import("config.zig");
|
||||||
|
|
||||||
|
pub fn load(
|
||||||
|
init: std.process.Init,
|
||||||
|
repo_name: []const u8,
|
||||||
|
package_name: []const u8,
|
||||||
|
) ![]u8 {
|
||||||
|
const allocator = init.gpa;
|
||||||
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
|
const path = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}/{s}/{s}.mt",
|
||||||
|
.{
|
||||||
|
config.index_directory,
|
||||||
|
repo_name,
|
||||||
|
package_name,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
defer allocator.free(path);
|
||||||
|
|
||||||
|
return try cwd.readFileAlloc(
|
||||||
|
init.io,
|
||||||
|
path,
|
||||||
|
allocator,
|
||||||
|
.limited(1024 * 1024),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const index = @import("index.zig");
|
||||||
|
|
||||||
|
pub fn run(init: std.process.Init, args: []const [:0]const u8) !void {
|
||||||
|
if (args.len < 3) {
|
||||||
|
std.debug.print("usage: xpk install <package>\n", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const package_name = args[2];
|
||||||
|
|
||||||
|
const metadata = index.load(
|
||||||
|
init,
|
||||||
|
"main",
|
||||||
|
package_name,
|
||||||
|
) catch |err| {
|
||||||
|
if (err == error.FileNotFound) {
|
||||||
|
std.debug.print(
|
||||||
|
"package '{s}' is not in the local index\n",
|
||||||
|
.{package_name},
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
defer init.gpa.free(metadata);
|
||||||
|
|
||||||
|
std.debug.print(
|
||||||
|
"metadata for {s}:\n{s}\n",
|
||||||
|
.{
|
||||||
|
package_name,
|
||||||
|
metadata,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Io = std.Io;
|
||||||
|
|
||||||
|
const config = @import("config.zig");
|
||||||
|
const network = @import("network.zig");
|
||||||
|
const install = @import("install.zig");
|
||||||
|
const repo = @import("repo.zig");
|
||||||
|
|
||||||
|
const Command = enum {
|
||||||
|
install,
|
||||||
|
remove,
|
||||||
|
sync,
|
||||||
|
search,
|
||||||
|
info,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn parse_command(name: []const u8) !Command {
|
||||||
|
if (std.mem.eql(u8, name, "install")) return .install;
|
||||||
|
if (std.mem.eql(u8, name, "remove")) return .remove;
|
||||||
|
if (std.mem.eql(u8, name, "sync")) return .sync;
|
||||||
|
if (std.mem.eql(u8, name, "search")) return .search;
|
||||||
|
if (std.mem.eql(u8, name, "info")) return .info;
|
||||||
|
|
||||||
|
return error.UnknownCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main(init: std.process.Init) !void {
|
||||||
|
const arena = init.arena.allocator();
|
||||||
|
|
||||||
|
const args = try init.minimal.args.toSlice(arena);
|
||||||
|
|
||||||
|
if (args.len < 2) {
|
||||||
|
std.debug.print("usage: xpk <command>\n", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const command = try parse_command(args[1]);
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
.install => try install.run(init, args),
|
||||||
|
|
||||||
|
.remove => {
|
||||||
|
// later
|
||||||
|
},
|
||||||
|
|
||||||
|
.sync => try repo.sync(init),
|
||||||
|
|
||||||
|
.search => {
|
||||||
|
// later
|
||||||
|
},
|
||||||
|
|
||||||
|
.info => {
|
||||||
|
// later
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn download(
|
||||||
|
io: std.Io,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
url: []const u8,
|
||||||
|
path: []const u8,
|
||||||
|
) !void {
|
||||||
|
var client = std.http.Client{
|
||||||
|
.allocator = allocator,
|
||||||
|
.io = io,
|
||||||
|
};
|
||||||
|
defer client.deinit();
|
||||||
|
|
||||||
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
|
var file = try cwd.createFile(io, path, .{});
|
||||||
|
defer file.close(io);
|
||||||
|
|
||||||
|
var writer_buffer: [64 * 1024]u8 = undefined;
|
||||||
|
var writer = file.writer(io, &writer_buffer);
|
||||||
|
|
||||||
|
const response = try client.fetch(.{
|
||||||
|
.location = .{ .url = url },
|
||||||
|
.response_writer = &writer.interface,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status != .ok) {
|
||||||
|
return error.HttpError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(
|
||||||
|
io: std.Io,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
url: []const u8,
|
||||||
|
) ![]u8 {
|
||||||
|
var client = std.http.Client{
|
||||||
|
.allocator = allocator,
|
||||||
|
.io = io,
|
||||||
|
};
|
||||||
|
defer client.deinit();
|
||||||
|
|
||||||
|
var body = std.Io.Writer.Allocating.init(allocator);
|
||||||
|
defer body.deinit();
|
||||||
|
|
||||||
|
const response = try client.fetch(.{
|
||||||
|
.location = .{ .url = url },
|
||||||
|
.response_writer = &body.writer,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status != .ok) {
|
||||||
|
return error.HttpError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return body.toOwnedSlice();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const Package = struct {
|
||||||
|
name: []const u8,
|
||||||
|
version: []const u8,
|
||||||
|
description: ?[]const u8,
|
||||||
|
license: ?[]const u8,
|
||||||
|
};
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const config = @import("config.zig");
|
||||||
|
const network = @import("network.zig");
|
||||||
|
|
||||||
|
pub fn sync(init: std.process.Init) !void {
|
||||||
|
const allocator = init.gpa;
|
||||||
|
const repo = "main";
|
||||||
|
|
||||||
|
const list_url = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}/{s}/{s}/.mt",
|
||||||
|
.{
|
||||||
|
config.repos.main,
|
||||||
|
repo,
|
||||||
|
config.arch,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
defer allocator.free(list_url);
|
||||||
|
|
||||||
|
std.debug.print("syncing {s}\n", .{list_url});
|
||||||
|
|
||||||
|
const list = try network.get(
|
||||||
|
init.io,
|
||||||
|
allocator,
|
||||||
|
list_url,
|
||||||
|
);
|
||||||
|
defer allocator.free(list);
|
||||||
|
|
||||||
|
const cwd = std.Io.Dir.cwd();
|
||||||
|
|
||||||
|
cwd.createDir(
|
||||||
|
init.io,
|
||||||
|
config.index_directory,
|
||||||
|
.default_dir,
|
||||||
|
) catch |err| switch (err) {
|
||||||
|
error.PathAlreadyExists => {},
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
|
|
||||||
|
const index_path = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}/{s}",
|
||||||
|
.{
|
||||||
|
config.index_directory,
|
||||||
|
repo,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
defer allocator.free(index_path);
|
||||||
|
|
||||||
|
cwd.createDir(
|
||||||
|
init.io,
|
||||||
|
index_path,
|
||||||
|
.default_dir,
|
||||||
|
) catch |err| switch (err) {
|
||||||
|
error.PathAlreadyExists => {},
|
||||||
|
else => return err,
|
||||||
|
};
|
||||||
|
|
||||||
|
var lines = std.mem.splitScalar(u8, list, '\n');
|
||||||
|
|
||||||
|
while (lines.next()) |line| {
|
||||||
|
const package = std.mem.trim(u8, line, " \r\t");
|
||||||
|
|
||||||
|
if (package.len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const url = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}/{s}/{s}/{s}/.mt",
|
||||||
|
.{
|
||||||
|
config.repos.main,
|
||||||
|
repo,
|
||||||
|
config.arch,
|
||||||
|
package,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
defer allocator.free(url);
|
||||||
|
|
||||||
|
std.debug.print(" {s}\n", .{package});
|
||||||
|
|
||||||
|
const metadata = try network.get(
|
||||||
|
init.io,
|
||||||
|
init.gpa,
|
||||||
|
url,
|
||||||
|
);
|
||||||
|
defer init.gpa.free(metadata);
|
||||||
|
|
||||||
|
const path = try std.fmt.allocPrint(
|
||||||
|
allocator,
|
||||||
|
"{s}/{s}.mt",
|
||||||
|
.{
|
||||||
|
index_path,
|
||||||
|
package,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
defer allocator.free(path);
|
||||||
|
|
||||||
|
var file = try cwd.createFile(
|
||||||
|
init.io,
|
||||||
|
path,
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
defer file.close(init.io);
|
||||||
|
|
||||||
|
try file.writeStreamingAll(
|
||||||
|
init.io,
|
||||||
|
metadata,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.print("sync complete\n", .{});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user