const Environment = @import("../env.zig"); const PackageManager = @import("./install.zig").PackageManager; const Semver = @import("./semver.zig"); const ExternalString = Semver.ExternalString; const String = Semver.String; const std = @import("std"); const string = @import("../string_types.zig").string; const GitSHA = String; pub const Repository = extern struct { owner: String = String{}, repo: String = String{}, committish: GitSHA = GitSHA{}, resolved: String = String{}, package_name: String = String{}, pub fn verify(this: *const Repository) void { this.owner.assertDefined(); this.repo.assertDefined(); this.committish.assertDefined(); this.resolved.assertDefined(); this.package_name.assertDefined(); } pub fn order(lhs: *const Repository, rhs: *const Repository, lhs_buf: []const u8, rhs_buf: []const u8) std.math.Order { const owner_order = lhs.owner.order(&rhs.owner, lhs_buf, rhs_buf); if (owner_order != .eq) return owner_order; const repo_order = lhs.repo.order(&rhs.repo, lhs_buf, rhs_buf); if (repo_order != .eq) return repo_order; return lhs.committish.order(&rhs.committish, lhs_buf, rhs_buf); } pub fn count(this: *const Repository, buf: []const u8, comptime StringBuilder: type, builder: StringBuilder) void { builder.count(this.owner.slice(buf)); builder.count(this.repo.slice(buf)); builder.count(this.committish.slice(buf)); builder.count(this.resolved.slice(buf)); builder.count(this.package_name.slice(buf)); } pub fn clone(this: *const Repository, buf: []const u8, comptime StringBuilder: type, builder: StringBuilder) Repository { return Repository{ .owner = builder.append(String, this.owner.slice(buf)), .repo = builder.append(String, this.repo.slice(buf)), .committish = builder.append(GitSHA, this.committish.slice(buf)), .resolved = builder.append(String, this.resolved.slice(buf)), .package_name = builder.append(String, this.package_name.slice(buf)), }; } pub fn eql(lhs: *const Repository, rhs: *const Repository, lhs_buf: []const u8, rhs_buf: []const u8) bool { return lhs.owner.eql(rhs.owner, lhs_buf, rhs_buf) and lhs.repo.eql(rhs.repo, lhs_buf, rhs_buf) and lhs.committish.eql(rhs.committish, lhs_buf, rhs_buf); } pub fn formatAs(this: *const Repository, label: string, buf: []const u8, comptime layout: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void { const formatter = Formatter{ .label = label, .repository = this, .buf = buf }; return try formatter.format(layout, opts, writer); } pub const Formatter = struct { label: []const u8 = "", buf: []const u8, repository: *const Repository, pub fn format(formatter: Formatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { if (Environment.allow_assert) std.debug.assert(formatter.label.len > 0); try writer.writeAll(formatter.label); try writer.writeAll(":"); try writer.writeAll(formatter.repository.owner.slice(formatter.buf)); try writer.writeAll("/"); try writer.writeAll(formatter.repository.repo.slice(formatter.buf)); if (!formatter.repository.resolved.isEmpty()) { try writer.writeAll("#"); var resolved = formatter.repository.resolved.slice(formatter.buf); if (std.mem.lastIndexOfScalar(u8, resolved, '-')) |i| { resolved = resolved[i + 1 ..]; } try writer.writeAll(resolved); } else if (!formatter.repository.committish.isEmpty()) { try writer.writeAll("#"); try writer.writeAll(formatter.repository.committish.slice(formatter.buf)); } } }; };