srctree

Gregory Mullen parent 1f830ee0 670ab55c
refactor printings into new Git.Remote.format

inlinesplit
src/endpoints/network.zig added: 79, removed: 89, total 0
@@ -1,4 +1,5 @@
const std = @import("std");
 
const DOM = @import("../dom.zig");
const Context = @import("../context.zig");
@@ -10,6 +11,7 @@ const UriIter = Route.UriIter;
const HTML = @import("../html.zig");
const Repos = @import("../repos.zig");
const Ini = @import("../ini.zig");
 
const ROUTE = Route.ROUTE;
@@ -24,17 +26,16 @@ fn default(ctx: *Context) Error!void {
const cwd = std.fs.cwd();
for (list) |reponame| {
var b: [0x800]u8 = undefined;
const confname = std.fmt.bufPrint(&b, "repos/{s}/", .{reponame}) catch unreachable;
var rdir = cwd.openDir(confname, .{}) catch unreachable;
defer rdir.close();
const cffd = rdir.openFile("config", .{}) catch rdir.openFile(".git/config", .{}) catch continue;
defer cffd.close();
const conf = Ini.fromFile(ctx.alloc, cffd) catch unreachable;
if (conf.get("remote \"upstream\"")) |ns| {
if (ns.get("url")) |url| {
const purl = try Repos.parseGitRemoteUrl(ctx.alloc, url);
dom = dom.open(HTML.h3(null, &HTML.Attr.class("upstream")));
dom.push(HTML.text("Upstream: "));
 
dom.push(HTML.anch(purl, try HTML.Attr.create(ctx.alloc, "href", purl)));
dom = dom.close();
}
@@ -1,4 +1,5 @@
const std = @import("std");
const allocPrint = std.fmt.allocPrint;
const DOM = @import("../dom.zig");
const Context = @import("../context.zig");
@@ -10,6 +11,7 @@ const UriIter = Route.UriIter;
const HTML = @import("../html.zig");
const Repos = @import("../repos.zig");
const Ini = @import("../ini.zig");
const Git = @import("../git.zig");
const ROUTE = Route.ROUTE;
@@ -24,17 +26,16 @@ fn default(ctx: *Context) Error!void {
const cwd = std.fs.cwd();
for (list) |reponame| {
var b: [0x800]u8 = undefined;
const confname = std.fmt.bufPrint(&b, "repos/{s}/", .{reponame}) catch continue;
const rdir = cwd.openDir(confname, .{}) catch continue;
var repo = Git.Repo.init(rdir) catch continue;
repo.loadData(ctx.alloc) catch continue;
defer repo.raze();
if (repo.findRemote("upstream") catch continue) |remote| {
if (remote.url) |_| {
 
 
dom = dom.open(HTML.h3(null, &HTML.Attr.class("upstream")));
dom.push(HTML.text("Upstream: "));
const purl = try allocPrint(ctx.alloc, "{link}", .{remote});
dom.push(HTML.anch(purl, try HTML.Attr.create(ctx.alloc, "href", purl)));
dom = dom.close();
}
src/endpoints/repos.zig added: 79, removed: 89, total 0
@@ -1,7 +1,6 @@
const std = @import("std");
 
const Allocator = std.mem.Allocator;
const aPrint = std.fmt.allocPrint;
const bPrint = std.fmt.bufPrint;
const eql = std.mem.eql;
@@ -108,13 +107,13 @@ pub fn navButtons(ctx: *Context) ![2]Template.Structs.NavButtons {
const btns = [2]Template.Structs.NavButtons{
.{
.name = "issues",
.extra = try aPrint(ctx.alloc, "{}", .{i_count}),
.url = try aPrint(ctx.alloc, "/repos/{s}/issues/", .{rd.name}),
},
.{
.name = "diffs",
.extra = try aPrint(ctx.alloc, "{}", .{d_count}),
.url = try aPrint(ctx.alloc, "/repos/{s}/diffs/", .{rd.name}),
},
};
@@ -227,14 +226,14 @@ fn repoBlock(a: Allocator, name: []const u8, repo: Git.Repo) !Template.Structs.R
}
var upstream: ?[]const u8 = null;
if (try Repos.hasUpstream(a, repo)) |url| {
upstream = try Repos.parseGitRemoteUrl(a, url);
}
var updated: []const u8 = "new repo";
if (repo.headCommit(a)) |cmt| {
defer cmt.raze();
const committer = cmt.committer;
updated = try aPrint(
a,
"updated about {}",
.{Humanize.unix(committer.timestamp)},
@@ -246,14 +245,14 @@ fn repoBlock(a: Allocator, name: []const u8, repo: Git.Repo) !Template.Structs.R
if (repo.tags) |tags| {
tag = .{
.tag = tags[0].name,
.title = try aPrint(a, "created {}", .{Humanize.unix(tags[0].tagger.timestamp)}),
.uri = try aPrint(a, "/repo/{s}/tags", .{name}),
};
}
return .{
.name = name,
.uri = try aPrint(a, "/repo/{s}", .{name}),
.desc = desc,
.upstream = upstream,
.updated = updated,
@@ -356,17 +355,17 @@ fn treeBlob(ctx: *Context) Error!void {
_ = ctx.uri.next();
var cwd = std.fs.cwd();
const filename = try aPrint(ctx.alloc, "./repos/{s}", .{rd.name});
const dir = cwd.openDir(filename, .{}) catch return error.Unknown;
var repo = Git.Repo.init(dir) catch return error.Unknown;
repo.loadData(ctx.alloc) catch return error.Unknown;
defer repo.raze();
if (Repos.hasUpstream(ctx.alloc, repo) catch return error.Unknown) |up| {
var upstream = [_]Template.Context{
Template.Context.init(ctx.alloc),
};
upstream[0].putSlice("URI", up) catch return error.Unknown;
ctx.putContext("Upstream", .{ .block = upstream[0..] }) catch return error.Unknown;
}
@@ -377,7 +376,7 @@ fn treeBlob(ctx: *Context) Error!void {
opengraph[0].putSlice("Title", rd.name) catch return error.Unknown;
var desc = repo.description(ctx.alloc) catch return error.Unknown;
if (std.mem.startsWith(u8, desc, "Unnamed repository; edit this file")) {
desc = try aPrint(ctx.alloc, "An Indescribable repo with {s} commits", .{"[todo count commits]"});
}
try opengraph[0].putSlice("Desc", desc);
try ctx.putContext("OpenGraph", .{ .block = opengraph[0..] });
@@ -481,7 +480,7 @@ fn blame(ctx: *Context) Error!void {
const blame_file = ctx.uri.rest();
var cwd = std.fs.cwd();
const fname = try aPrint(ctx.alloc, "./repos/{s}", .{rd.name});
const dir = cwd.openDir(fname, .{}) catch return error.Unknown;
var repo = Git.Repo.init(dir) catch return error.Unknown;
defer repo.raze();
@@ -620,7 +619,7 @@ fn blob(ctx: *Context, repo: *Git.Repo, pfiles: Git.Tree) Error!void {
dom = try wrapLineNumbers(ctx.alloc, dom, formatted);
const data = dom.done();
const filestr = try aPrint(
ctx.alloc,
"{pretty}",
.{HTML.div(data, &HTML.Attr.class("code-block"))},
@@ -699,16 +698,16 @@ fn drawFileLine(
// I know... I KNOW!!!
dom = dom.open(HTML.div(null, null));
const commit_href = try aPrint(a, "/repo/{s}/commit/{s}", .{ rname, ch.sha.hex[0..8] });
dom.push(try HTML.aHrefAlloc(a, ch.commit_title, commit_href));
dom.dupe(HTML.span(try aPrint(a, "{}", .{Humanize.unix(ch.timestamp)}), null));
dom = dom.close();
return dom.close();
}
fn drawBlob(a: Allocator, ddom: *DOM, rname: []const u8, base: []const u8, obj: Git.Blob) !*DOM {
var dom = ddom.open(HTML.element("file", null, null));
const file_link = try aPrint(a, "/repo/{s}/blob/{s}{s}", .{ rname, base, obj.name });
const href = &[_]HTML.Attribute{.{
.key = "href",
@@ -721,7 +720,7 @@ fn drawBlob(a: Allocator, ddom: *DOM, rname: []const u8, base: []const u8, obj:
fn drawTree(a: Allocator, ddom: *DOM, rname: []const u8, base: []const u8, obj: Git.Blob) !*DOM {
var dom = ddom.open(HTML.element("tree", null, null));
const file_link = try aPrint(a, "/repo/{s}/tree/{s}{s}/", .{ rname, base, obj.name });
const href = &[_]HTML.Attribute{.{
.key = "href",
@@ -754,14 +753,14 @@ fn tree(ctx: *Context, repo: *Git.Repo, files: *Git.Tree) Error!void {
dom = dom.open(HTML.element("intro", null, null));
dom.push(HTML.h3(rd.name, null));
const branches = try aPrint(ctx.alloc, "{} branches", .{repo.refs.len});
dom.push(HTML.span(branches, null));
const c = repo.headCommit(ctx.alloc) catch return error.Unknown;
dom.push(HTML.span(c.title[0..@min(c.title.len, 50)], null));
const commit_time = try aPrint(ctx.alloc, " {}", .{Humanize.unix(c.committer.timestamp)});
dom = dom.open(HTML.span(null, &HTML.Attr.class("muted")));
const commit_href = try aPrint(ctx.alloc, "/repo/{s}/commit/{s}", .{ rd.name, c.sha.hex[0..8] });
dom.push(HTML.text(commit_time));
dom.push(try HTML.aHrefAlloc(ctx.alloc, c.sha.hex[0..8], commit_href));
dom = dom.close();
@@ -773,7 +772,7 @@ fn tree(ctx: *Context, repo: *Git.Repo, files: *Git.Tree) Error!void {
dom = dom.open(HTML.element("tree", null, null));
const dd_href = &[_]HTML.Attribute{.{
.key = "href",
.value = try aPrint(
ctx.alloc,
"/repo/{s}/tree/{s}",
.{ rd.name, uri_base[0..end] },
@@ -835,7 +834,7 @@ fn tagsList(ctx: *Context) Error!void {
const rd = RouteData.make(&ctx.uri) orelse return error.Unrouteable;
var cwd = std.fs.cwd();
const filename = try aPrint(ctx.alloc, "./repos/{s}", .{rd.name});
const dir = cwd.openDir(filename, .{}) catch return error.Unknown;
var repo = Git.Repo.init(dir) catch return error.Unknown;
repo.loadData(ctx.alloc) catch return error.Unknown;
@@ -1,7 +1,6 @@
const std = @import("std");
 
const Allocator = std.mem.Allocator;
const allocPrint = std.fmt.allocPrint;
const bPrint = std.fmt.bufPrint;
const eql = std.mem.eql;
@@ -108,13 +107,13 @@ pub fn navButtons(ctx: *Context) ![2]Template.Structs.NavButtons {
const btns = [2]Template.Structs.NavButtons{
.{
.name = "issues",
.extra = try allocPrint(ctx.alloc, "{}", .{i_count}),
.url = try allocPrint(ctx.alloc, "/repos/{s}/issues/", .{rd.name}),
},
.{
.name = "diffs",
.extra = try allocPrint(ctx.alloc, "{}", .{d_count}),
.url = try allocPrint(ctx.alloc, "/repos/{s}/diffs/", .{rd.name}),
},
};
@@ -227,14 +226,14 @@ fn repoBlock(a: Allocator, name: []const u8, repo: Git.Repo) !Template.Structs.R
}
var upstream: ?[]const u8 = null;
if (try repo.findRemote("upstream")) |remote| {
upstream = try allocPrint(a, "{link}", .{remote});
}
var updated: []const u8 = "new repo";
if (repo.headCommit(a)) |cmt| {
defer cmt.raze();
const committer = cmt.committer;
updated = try allocPrint(
a,
"updated about {}",
.{Humanize.unix(committer.timestamp)},
@@ -246,14 +245,14 @@ fn repoBlock(a: Allocator, name: []const u8, repo: Git.Repo) !Template.Structs.R
if (repo.tags) |tags| {
tag = .{
.tag = tags[0].name,
.title = try allocPrint(a, "created {}", .{Humanize.unix(tags[0].tagger.timestamp)}),
.uri = try allocPrint(a, "/repo/{s}/tags", .{name}),
};
}
return .{
.name = name,
.uri = try allocPrint(a, "/repo/{s}", .{name}),
.desc = desc,
.upstream = upstream,
.updated = updated,
@@ -356,17 +355,17 @@ fn treeBlob(ctx: *Context) Error!void {
_ = ctx.uri.next();
var cwd = std.fs.cwd();
const filename = try allocPrint(ctx.alloc, "./repos/{s}", .{rd.name});
const dir = cwd.openDir(filename, .{}) catch return error.Unknown;
var repo = Git.Repo.init(dir) catch return error.Unknown;
repo.loadData(ctx.alloc) catch return error.Unknown;
defer repo.raze();
if (repo.findRemote("upstream") catch return error.Unknown) |remote| {
var upstream = [_]Template.Context{
Template.Context.init(ctx.alloc),
};
upstream[0].putSlice("URI", remote.url orelse "") catch return error.Unknown;
ctx.putContext("Upstream", .{ .block = upstream[0..] }) catch return error.Unknown;
}
@@ -377,7 +376,7 @@ fn treeBlob(ctx: *Context) Error!void {
opengraph[0].putSlice("Title", rd.name) catch return error.Unknown;
var desc = repo.description(ctx.alloc) catch return error.Unknown;
if (std.mem.startsWith(u8, desc, "Unnamed repository; edit this file")) {
desc = try allocPrint(ctx.alloc, "An Indescribable repo with {s} commits", .{"[todo count commits]"});
}
try opengraph[0].putSlice("Desc", desc);
try ctx.putContext("OpenGraph", .{ .block = opengraph[0..] });
@@ -481,7 +480,7 @@ fn blame(ctx: *Context) Error!void {
const blame_file = ctx.uri.rest();
var cwd = std.fs.cwd();
const fname = try allocPrint(ctx.alloc, "./repos/{s}", .{rd.name});
const dir = cwd.openDir(fname, .{}) catch return error.Unknown;
var repo = Git.Repo.init(dir) catch return error.Unknown;
defer repo.raze();
@@ -620,7 +619,7 @@ fn blob(ctx: *Context, repo: *Git.Repo, pfiles: Git.Tree) Error!void {
dom = try wrapLineNumbers(ctx.alloc, dom, formatted);
const data = dom.done();
const filestr = try allocPrint(
ctx.alloc,
"{pretty}",
.{HTML.div(data, &HTML.Attr.class("code-block"))},
@@ -699,16 +698,16 @@ fn drawFileLine(
// I know... I KNOW!!!
dom = dom.open(HTML.div(null, null));
const commit_href = try allocPrint(a, "/repo/{s}/commit/{s}", .{ rname, ch.sha.hex[0..8] });
dom.push(try HTML.aHrefAlloc(a, ch.commit_title, commit_href));
dom.dupe(HTML.span(try allocPrint(a, "{}", .{Humanize.unix(ch.timestamp)}), null));
dom = dom.close();
return dom.close();
}
fn drawBlob(a: Allocator, ddom: *DOM, rname: []const u8, base: []const u8, obj: Git.Blob) !*DOM {
var dom = ddom.open(HTML.element("file", null, null));
const file_link = try allocPrint(a, "/repo/{s}/blob/{s}{s}", .{ rname, base, obj.name });
const href = &[_]HTML.Attribute{.{
.key = "href",
@@ -721,7 +720,7 @@ fn drawBlob(a: Allocator, ddom: *DOM, rname: []const u8, base: []const u8, obj:
fn drawTree(a: Allocator, ddom: *DOM, rname: []const u8, base: []const u8, obj: Git.Blob) !*DOM {
var dom = ddom.open(HTML.element("tree", null, null));
const file_link = try allocPrint(a, "/repo/{s}/tree/{s}{s}/", .{ rname, base, obj.name });
const href = &[_]HTML.Attribute{.{
.key = "href",
@@ -754,14 +753,14 @@ fn tree(ctx: *Context, repo: *Git.Repo, files: *Git.Tree) Error!void {
dom = dom.open(HTML.element("intro", null, null));
dom.push(HTML.h3(rd.name, null));
const branches = try allocPrint(ctx.alloc, "{} branches", .{repo.refs.len});
dom.push(HTML.span(branches, null));
const c = repo.headCommit(ctx.alloc) catch return error.Unknown;
dom.push(HTML.span(c.title[0..@min(c.title.len, 50)], null));
const commit_time = try allocPrint(ctx.alloc, " {}", .{Humanize.unix(c.committer.timestamp)});
dom = dom.open(HTML.span(null, &HTML.Attr.class("muted")));
const commit_href = try allocPrint(ctx.alloc, "/repo/{s}/commit/{s}", .{ rd.name, c.sha.hex[0..8] });
dom.push(HTML.text(commit_time));
dom.push(try HTML.aHrefAlloc(ctx.alloc, c.sha.hex[0..8], commit_href));
dom = dom.close();
@@ -773,7 +772,7 @@ fn tree(ctx: *Context, repo: *Git.Repo, files: *Git.Tree) Error!void {
dom = dom.open(HTML.element("tree", null, null));
const dd_href = &[_]HTML.Attribute{.{
.key = "href",
.value = try allocPrint(
ctx.alloc,
"/repo/{s}/tree/{s}",
.{ rd.name, uri_base[0..end] },
@@ -835,7 +834,7 @@ fn tagsList(ctx: *Context) Error!void {
const rd = RouteData.make(&ctx.uri) orelse return error.Unrouteable;
var cwd = std.fs.cwd();
const filename = try allocPrint(ctx.alloc, "./repos/{s}", .{rd.name});
const dir = cwd.openDir(filename, .{}) catch return error.Unknown;
var repo = Git.Repo.init(dir) catch return error.Unknown;
repo.loadData(ctx.alloc) catch return error.Unknown;
src/git.zig added: 79, removed: 89, total 0
@@ -194,6 +194,16 @@ pub const Repo = struct {
self.remotes = try list.toOwnedSlice();
}
 
 
 
 
 
 
 
 
 
 
fn loadFile(self: Repo, a: Allocator, sha: SHA) !Object {
var fb = [_]u8{0} ** 2048;
const grouped = try bufPrint(&fb, "./objects/{s}/{s}", .{ sha.hex[0..2], sha.hex[2..] });
@@ -194,6 +194,16 @@ pub const Repo = struct {
self.remotes = try list.toOwnedSlice();
}
pub fn findRemote(self: Repo, name: []const u8) !?*const Remote {
const remotes = self.remotes orelse unreachable;
for (remotes) |*remote| {
if (eql(u8, remote.name, name)) {
return remote;
}
}
return null;
}
 
fn loadFile(self: Repo, a: Allocator, sha: SHA) !Object {
var fb = [_]u8{0} ** 2048;
const grouped = try bufPrint(&fb, "./objects/{s}/{s}", .{ sha.hex[0..2], sha.hex[2..] });
src/git/remote.zig added: 79, removed: 89, total 0
@@ -11,7 +11,7 @@ url: ?[]const u8,
fetch: ?[]const u8,
pub fn format(r: Remote, comptime fmt: []const u8, _: std.fmt.FormatOptions, out: anytype) !void {
if (std.mem.eql(u8, fmt, "diff")) {
if (r.url) |url| {
var printable = url;
if (startsWith(u8, printable, "https://")) {
@@ -28,7 +28,29 @@ pub fn format(r: Remote, comptime fmt: []const u8, _: std.fmt.FormatOptions, out
try out.writeAll(r.name);
try out.writeAll("]");
}
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
}
/// Half supported alloc function
@@ -11,7 +11,7 @@ url: ?[]const u8,
fetch: ?[]const u8,
pub fn format(r: Remote, comptime fmt: []const u8, _: std.fmt.FormatOptions, out: anytype) !void {
if (eql(u8, fmt, "diff")) {
if (r.url) |url| {
var printable = url;
if (startsWith(u8, printable, "https://")) {
@@ -28,7 +28,29 @@ pub fn format(r: Remote, comptime fmt: []const u8, _: std.fmt.FormatOptions, out
try out.writeAll(r.name);
try out.writeAll("]");
}
} else if (eql(u8, fmt, "link")) {
if (r.url) |url| {
var printable = url;
if (startsWith(u8, printable, "https://")) {
printable = printable[8..];
}
if (indexOf(u8, printable, "@")) |i| {
printable = printable[i + 1 ..];
}
if (endsWith(u8, printable, ".git")) {
printable = printable[0 .. printable.len - 4];
}
if (indexOf(u8, printable, ":")) |i| {
try out.writeAll("https://"); // LOL, sorry
try out.writeAll(printable[0..i]);
try out.writeAll("/");
try out.writeAll(printable[i + 1 ..]);
} else {
try out.writeAll("https://"); // LOL, sorry
try out.writeAll(printable);
}
}
} else unreachable;
}
/// Half supported alloc function
src/repos.zig added: 79, removed: 89, total 0
@@ -28,47 +28,6 @@ pub fn containsName(name: []const u8) bool {
return if (name.len > 0) true else false;
}
pub fn parseGitRemoteUrl(a: Allocator, url: []const u8) ![]u8 {
if (std.mem.startsWith(u8, url, "https://")) return try a.dupe(u8, url);
 
if (std.mem.startsWith(u8, url, "git@")) {
const end = if (std.mem.endsWith(u8, url, ".git")) url.len - 4 else url.len;
var p = try a.dupe(u8, url[4..end]);
if (std.mem.indexOf(u8, p, ":")) |i| p[i] = '/';
const joiner = [_][]const u8{ "https://", p };
const http = try std.mem.join(a, "", &joiner);
return http;
}
 
return try a.dupe(u8, url);
}
 
pub fn hasUpstream(a: Allocator, r: Git.Repo) !?[]u8 {
var conffd = try r.dir.openFile("config", .{});
defer conffd.close();
const conf = try Ini.fromFile(a, conffd);
defer conf.raze();
if (conf.get("remote \"upstream\"")) |ns| {
if (ns.get("url")) |url| {
return try a.dupe(u8, url);
}
}
return null;
}
 
pub fn hasDownstream(a: Allocator, r: Git.Repo) !?[]u8 {
var conffd = try r.dir.openFile("config", .{});
defer conffd.close();
const conf = try Ini.fromFile(a, conffd);
defer conf.raze();
if (conf.get("remote \"downstream\"")) |ns| {
if (ns.get("url")) |url| {
return try a.dupe(u8, url);
}
}
return null;
}
 
pub const AgentConfig = struct {
running: bool = true,
sleep_for: usize = 60 * 60 * 1000 * 1000 * 1000,
@@ -83,15 +42,15 @@ fn pushUpstream(a: Allocator, name: []const u8, repo: *Git.Repo) !void {
.{std.time.timestamp()},
) catch unreachable;
const rhead = try repo.*.HEAD(a);
const head: []const u8 = switch (rhead) {
.branch => |b| b.name[std.mem.lastIndexOf(u8, b.name, "/") orelse 0 ..][1..],
.tag => |t| t.name,
else => "main",
};
if (try hasUpstream(a, repo.*)) |up| {
 
repo.dir.writeFile(.{ .sub_path = "srctree_last_update", .data = update }) catch {};
a.free(up);
var agent = repo.getAgent(a);
const updated = agent.updateUpstream(head) catch er: {
std.debug.print("Warning, unable to update repo {s}\n", .{name});
@@ -161,9 +120,8 @@ pub fn updateThread(cfg: *AgentConfig) void {
) catch unreachable;
if (repo_update > last_push) {
if (hasDownstream(a, repo) catch continue) |down| {
repo.dir.writeFile(.{ .sub_path = "srctree_last_downdate", .data = update }) catch {};
a.free(down);
var agent = repo.getAgent(a);
const updated = agent.updateDownstream() catch er: {
std.debug.print("Warning, unable to push to downstream repo {s}\n", .{rname});
@@ -28,47 +28,6 @@ pub fn containsName(name: []const u8) bool {
return if (name.len > 0) true else false;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pub const AgentConfig = struct {
running: bool = true,
sleep_for: usize = 60 * 60 * 1000 * 1000 * 1000,
@@ -83,15 +42,15 @@ fn pushUpstream(a: Allocator, name: []const u8, repo: *Git.Repo) !void {
.{std.time.timestamp()},
) catch unreachable;
const rhead = try repo.HEAD(a);
const head: []const u8 = switch (rhead) {
.branch => |b| b.name[std.mem.lastIndexOf(u8, b.name, "/") orelse 0 ..][1..],
.tag => |t| t.name,
else => "main",
};
 
if (try repo.findRemote("upstream")) |_| {
repo.dir.writeFile(.{ .sub_path = "srctree_last_update", .data = update }) catch {};
 
var agent = repo.getAgent(a);
const updated = agent.updateUpstream(head) catch er: {
std.debug.print("Warning, unable to update repo {s}\n", .{name});
@@ -161,9 +120,8 @@ pub fn updateThread(cfg: *AgentConfig) void {
) catch unreachable;
if (repo_update > last_push) {
if (repo.findRemote("downstream") catch continue) |_| {
repo.dir.writeFile(.{ .sub_path = "srctree_last_downdate", .data = update }) catch {};
 
var agent = repo.getAgent(a);
const updated = agent.updateDownstream() catch er: {
std.debug.print("Warning, unable to push to downstream repo {s}\n", .{rname});