Compare commits
2 Commits
dd32db056e
...
b4f82ebfda
| Author | SHA1 | Date | |
|---|---|---|---|
| b4f82ebfda | |||
| 21a4c231a3 |
56
build.zig
56
build.zig
@@ -1,11 +1,16 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
// TODO TODO
|
// Must match the version in build.zig.zon
|
||||||
|
const totp_version: std.SemanticVersion = .{ .major = 0, .minor = 1, .patch = 0, .pre = "dev" };
|
||||||
|
|
||||||
// Although this function looks imperative, note that its job is to
|
// Although this function looks imperative, note that its job is to
|
||||||
// declaratively construct a build graph that will be executed by an external
|
// declaratively construct a build graph that will be executed by an external
|
||||||
// runner.
|
// runner.
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
|
const version = getVersion(b);
|
||||||
|
const options = b.addOptions();
|
||||||
|
options.addOption(std.SemanticVersion, "version", version);
|
||||||
|
|
||||||
// Standard target options allows the person running `zig build` to choose
|
// Standard target options allows the person running `zig build` to choose
|
||||||
// what target to build for. Here we do not override the defaults, which
|
// what target to build for. Here we do not override the defaults, which
|
||||||
// means any target is allowed, and the default is native. Other options
|
// means any target is allowed, and the default is native. Other options
|
||||||
@@ -37,6 +42,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
exe.root_module.addOptions("config", options);
|
||||||
|
|
||||||
// This declares intent for the executable to be installed into the
|
// This declares intent for the executable to be installed into the
|
||||||
// standard location when the user invokes the "install" step (the default
|
// standard location when the user invokes the "install" step (the default
|
||||||
@@ -91,3 +97,51 @@ pub fn build(b: *std.Build) void {
|
|||||||
test_step.dependOn(&run_lib_unit_tests.step);
|
test_step.dependOn(&run_lib_unit_tests.step);
|
||||||
test_step.dependOn(&run_exe_unit_tests.step);
|
test_step.dependOn(&run_exe_unit_tests.step);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn getVersion(b: *std.Build) std.SemanticVersion {
|
||||||
|
// if this is a release version , aka this is not a pre-release or build version,
|
||||||
|
// then use the specified version
|
||||||
|
if (totp_version.pre == null and totp_version.build == null) return totp_version;
|
||||||
|
|
||||||
|
// for pre-release version we use the git version
|
||||||
|
const args: []const []const u8 = &.{ "git", "-C", b.pathFromRoot("."), "describe", "--match", "*.*.*", "--tags" };
|
||||||
|
var out_code: u8 = undefined;
|
||||||
|
const output_untrimmed = b.runAllowFail(args, &out_code, .Ignore) catch |err| {
|
||||||
|
std.log.warn(
|
||||||
|
\\ failed to run git describe: {}
|
||||||
|
, .{err});
|
||||||
|
return totp_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
const output_trimmed = std.mem.trim(u8, output_untrimmed, " \r\n");
|
||||||
|
switch (std.mem.count(u8, output_trimmed, "-")) {
|
||||||
|
0 => {
|
||||||
|
// release version, e.g. 1.0.0
|
||||||
|
if (!std.mem.eql(u8, output_trimmed, b.fmt("{}", .{totp_version}))) {
|
||||||
|
std.debug.panic("the version in build.zig and build.zig.zon must match the tag in git", .{});
|
||||||
|
}
|
||||||
|
return totp_version;
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
// development version, e.g. 1.0.0-7-64es356
|
||||||
|
var iter = std.mem.splitScalar(u8, output_trimmed, '-');
|
||||||
|
const tag = iter.first();
|
||||||
|
const commits_since_tag = iter.next().?;
|
||||||
|
const commit_hash = iter.next().?;
|
||||||
|
|
||||||
|
const v: std.SemanticVersion = std.SemanticVersion.parse(tag) catch unreachable;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.major = v.major,
|
||||||
|
.minor = v.minor,
|
||||||
|
.patch = v.patch,
|
||||||
|
.pre = b.fmt("dev.{s}", .{commits_since_tag}),
|
||||||
|
.build = commit_hash[1..],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
std.debug.print("unexpected output of git describe: '{s}'\n", .{output_untrimmed});
|
||||||
|
std.process.exit(1);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.name = "zig-totp",
|
.name = "zig-totp",
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
.version = "0.0.0",
|
.version = "0.1.0-dev",
|
||||||
|
|
||||||
// This field is optional.
|
// This field is optional.
|
||||||
// This is currently advisory only; Zig does not yet do anything
|
// This is currently advisory only; Zig does not yet do anything
|
||||||
|
|||||||
15
src/main.zig
15
src/main.zig
@@ -10,6 +10,7 @@ const expect = testing.expect;
|
|||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const Base32 = @import("base32.zig").Base32;
|
const Base32 = @import("base32.zig").Base32;
|
||||||
const Base32Error = @import("base32.zig").Base32Error;
|
const Base32Error = @import("base32.zig").Base32Error;
|
||||||
|
const options = @import("config");
|
||||||
|
|
||||||
// otpauth://totp/AWS+Dev?secret=47STA47VFCMMLLWOLHWO3KY7MYNC36MLCDTHOLIYKJCTTSSAMKVM7YA3VWT2AJEP&digits=6&icon=Amazon
|
// otpauth://totp/AWS+Dev?secret=47STA47VFCMMLLWOLHWO3KY7MYNC36MLCDTHOLIYKJCTTSSAMKVM7YA3VWT2AJEP&digits=6&icon=Amazon
|
||||||
// otpauth://totp/Gitea%20%28git.lucares.de%29:andi?algorithm=SHA1&digits=6&issuer=Gitea&period=30&secret=MSP53Q672UJMSCLQVRCJKMMZKK7MWSMYFL77OQ24JBM65RZWY7F2Y45FMTNLYM36
|
// otpauth://totp/Gitea%20%28git.lucares.de%29:andi?algorithm=SHA1&digits=6&issuer=Gitea&period=30&secret=MSP53Q672UJMSCLQVRCJKMMZKK7MWSMYFL77OQ24JBM65RZWY7F2Y45FMTNLYM36
|
||||||
@@ -49,7 +50,9 @@ fn mainInternal() !void {
|
|||||||
|
|
||||||
const arg: Args = try parseArgs(allocator, args);
|
const arg: Args = try parseArgs(allocator, args);
|
||||||
//print("parsed Args: {?any}\n", arg);
|
//print("parsed Args: {?any}\n", arg);
|
||||||
if (arg.list) {
|
if (arg.print_version) {
|
||||||
|
try std.io.getStdOut().writer().print("{}", .{options.version});
|
||||||
|
} else if (arg.list) {
|
||||||
const names = try executeGetList(allocator, arg.config_location);
|
const names = try executeGetList(allocator, arg.config_location);
|
||||||
|
|
||||||
for (0..names.items.len) |i| {
|
for (0..names.items.len) |i| {
|
||||||
@@ -85,12 +88,14 @@ fn printHelp() void {
|
|||||||
\\ eval "$(zig-totp --bash)"
|
\\ eval "$(zig-totp --bash)"
|
||||||
\\ to your ~/.bashrc
|
\\ to your ~/.bashrc
|
||||||
\\ --config [path] The path to a config file (default is $XDG_CONFIG_HOME/zig-totp or $HOME/.zig-totp).
|
\\ --config [path] The path to a config file (default is $XDG_CONFIG_HOME/zig-totp or $HOME/.zig-totp).
|
||||||
|
\\ --help Show this help
|
||||||
|
\\ --version Print the version number
|
||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
std.debug.print("{s}", .{msg});
|
std.debug.print("{s}", .{msg});
|
||||||
}
|
}
|
||||||
|
|
||||||
const Args = struct { list: bool, show: ?[]const u8, config_location: []const u8, validateAuthenticator: ?[]const u8, validateCode: ?[]const u8 };
|
const Args = struct { list: bool, show: ?[]const u8, config_location: []const u8, validateAuthenticator: ?[]const u8, validateCode: ?[]const u8, print_version: bool, show_help: bool };
|
||||||
|
|
||||||
const OtpAuthUrl = struct { name: []const u8, secretEncoded: []const u8, url: []const u8, period: u32, digits: u4, algorithm: []const u8 };
|
const OtpAuthUrl = struct { name: []const u8, secretEncoded: []const u8, url: []const u8, period: u32, digits: u4, algorithm: []const u8 };
|
||||||
|
|
||||||
@@ -186,7 +191,7 @@ fn zeroPad(allocator: Allocator, digits: u4, x: anytype) ![]u8 {
|
|||||||
const ArgumentError = error{ InvalidOtpAuthUrl, UnknownParameter, MissingConfigLocation, AuthenticatorNotFound, MissingAuthenticatorParam, FailedToOpenConfigFile, TooManyParsinErrors };
|
const ArgumentError = error{ InvalidOtpAuthUrl, UnknownParameter, MissingConfigLocation, AuthenticatorNotFound, MissingAuthenticatorParam, FailedToOpenConfigFile, TooManyParsinErrors };
|
||||||
|
|
||||||
fn parseArgs(allocator: Allocator, args: []const []const u8) !Args {
|
fn parseArgs(allocator: Allocator, args: []const []const u8) !Args {
|
||||||
var result = Args{ .list = false, .show = null, .config_location = try configLocation(allocator), .validateAuthenticator = null, .validateCode = null };
|
var result = Args{ .list = false, .show = null, .config_location = try configLocation(allocator), .validateAuthenticator = null, .validateCode = null, .print_version = false, .show_help = false };
|
||||||
var i: u17 = 1;
|
var i: u17 = 1;
|
||||||
while (i < args.len) : (i += 1) {
|
while (i < args.len) : (i += 1) {
|
||||||
const arg = args[i];
|
const arg = args[i];
|
||||||
@@ -220,6 +225,10 @@ fn parseArgs(allocator: Allocator, args: []const []const u8) !Args {
|
|||||||
return error.MissingConfigLocation;
|
return error.MissingConfigLocation;
|
||||||
}
|
}
|
||||||
result.config_location = args[i];
|
result.config_location = args[i];
|
||||||
|
} else if (eql(u8, "--help", arg) or eql(u8, "help", arg)) {
|
||||||
|
result.show_help = true;
|
||||||
|
} else if (eql(u8, "--version", arg)) {
|
||||||
|
result.print_version = true;
|
||||||
} else if (eql(u8, "list", arg)) {
|
} else if (eql(u8, "list", arg)) {
|
||||||
result.list = true;
|
result.list = true;
|
||||||
} else if (eql(u8, "show", arg)) {
|
} else if (eql(u8, "show", arg)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user