Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ to [Semantic Versioning][semver].
- Print usage details to standard output if a help flag is used in command.
- Document more detailed usage with manual pages for even better reference.
- Include installation instruction for moving a release download into path.
- Pick an upstream project according to the saved git remotes using a flag.

### Maintenance

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ $ git coverage # https://app.codecov.io/gh/zimeg/git-coverage
Options are available for customization:

- `--help`: boolean. Print these usage details. Default: `false`
- `--remote`: string. Pick an upstream project. Default: `origin`

## Installation

Expand Down
2 changes: 2 additions & 0 deletions man/git-coverage.1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ The \fBgit-coverage\fP program opens test coverage results uploaded to \fBcodeco
.
.IP "-h, --help"
Print these usage details.
.IP "--remote"
Pick an upstream project. Default: "origin"
.
.
.SH EXIT STATUS
Expand Down
70 changes: 60 additions & 10 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ const std = @import("std");

const Flags = struct {
help: bool,
remote: []const u8,

pub fn init(allocator: std.mem.Allocator) !Flags {
var flags = Flags{
.help = false,
.remote = "origin",
};
var args = try std.process.argsWithAllocator(allocator);
_ = args.next();
Expand All @@ -15,6 +17,8 @@ const Flags = struct {
if (std.mem.eql(u8, arg, "-h") or std.mem.eql(u8, arg, "--help")) {
flags.help = true;
break;
} else if (std.mem.eql(u8, arg, "--remote")) {
flags.remote = try parse(&args);
} else {
return error.FlagOptionMissing;
}
Expand All @@ -24,6 +28,15 @@ const Flags = struct {
}
return flags;
}

fn parse(args: *std.process.ArgIterator) ![]const u8 {
const path = args.next();
if (path) |value| {
return value;
} else {
return error.FlagValueMissing;
}
}
};

pub fn main() !void {
Expand All @@ -40,6 +53,7 @@ pub fn main() !void {
\\Open test coverage uploaded to codecov in a web browser.
\\
\\ --help boolean print these usage details (default: false)
\\ --remote string pick an upstream project (default: "origin")
\\
, .{});
return;
Expand All @@ -51,7 +65,7 @@ pub fn main() !void {
if (proc.stdout.len <= 0) {
return error.GitRemoteMissing;
}
const remote = try origin(proc.stdout);
const remote = try origin(proc.stdout, flags.remote);
const project = try repo(remote);
const url = try coverage(allocator, project);
_ = std.process.Child.run(.{
Expand All @@ -62,32 +76,68 @@ pub fn main() !void {
};
}

fn origin(remotes: []const u8) ![]const u8 {
fn origin(remotes: []const u8, upstream: []const u8) ![]const u8 {
var remote = std.mem.splitScalar(u8, remotes, '\n');
while (true) {
const line = remote.next();
if (line) |val| {
if (std.mem.startsWith(u8, val, "origin") and std.mem.endsWith(u8, val, "(push)")) {
return std.mem.trim(u8, val[7 .. val.len - 6], " ");
if (std.mem.startsWith(u8, val, upstream) and std.mem.endsWith(u8, val, "(push)")) {
return std.mem.trim(u8, val[upstream.len + 1 .. val.len - 6], " ");
}
} else {
return error.GitOriginMissing;
}
}
}

test "origin http" {
const remotes = "origin https://github.com/zimeg/git-coverage.git (fetch)\norigin https://github.com/zimeg/git-coverage.git (push)";
const remote = try origin(remotes);
test "origin http default" {
const remotes =
\\origin https://github.com/example/git-coverage.git (fetch)
\\origin https://github.com/example/git-coverage.git (push)
\\upstream https://github.com/zimeg/git-coverage.git (fetch)
\\upstream https://github.com/zimeg/git-coverage.git (push)
\\
;
const remote = try origin(remotes, "origin");
try std.testing.expectEqualStrings(remote, "https://github.com/example/git-coverage.git");
}

test "origin http custom" {
const remotes =
\\origin https://github.com/example/git-coverage.git (fetch)
\\origin https://github.com/example/git-coverage.git (push)
\\upstream https://github.com/zimeg/git-coverage.git (fetch)
\\upstream https://github.com/zimeg/git-coverage.git (push)
\\
;
const remote = try origin(remotes, "upstream");
try std.testing.expectEqualStrings(remote, "https://github.com/zimeg/git-coverage.git");
}

test "origin ssh" {
const remotes = "origin git@github.com:zimeg/git-coverage.git (fetch)\norigin git@github.com:zimeg/git-coverage.git (push)";
const remote = try origin(remotes);
test "origin ssh default" {
const remotes =
\\fork git@github.com:example/git-coverage.git (fetch)
\\fork git@github.com:example/git-coverage.git (push)
\\origin git@github.com:zimeg/git-coverage.git (fetch)
\\origin git@github.com:zimeg/git-coverage.git (push)
\\
;
const remote = try origin(remotes, "origin");
try std.testing.expectEqualStrings(remote, "git@github.com:zimeg/git-coverage.git");
}

test "origin ssh custom" {
const remotes =
\\fork git@github.com:example/git-coverage.git (fetch)
\\fork git@github.com:example/git-coverage.git (push)
\\origin git@github.com:zimeg/git-coverage.git (fetch)
\\origin git@github.com:zimeg/git-coverage.git (push)
\\
;
const remote = try origin(remotes, "fork");
try std.testing.expectEqualStrings(remote, "git@github.com:example/git-coverage.git");
}

fn repo(remote: []const u8) ![]const u8 {
if (std.mem.startsWith(u8, remote, "https://github.com/")) {
return remote[19 .. remote.len - 4];
Expand Down