mirror of
https://github.com/jetzig-framework/jetzig.git
synced 2025-05-14 14:06:08 +00:00
97 lines
3.1 KiB
Zig
97 lines
3.1 KiB
Zig
const std = @import("std");
|
|
|
|
/// Decode a base64 string, used for parsing out build artifacts generated by the CLI program's
|
|
/// build.zig which are stored in the executable as a module.
|
|
pub fn base64Decode(allocator: std.mem.Allocator, input: []const u8) ![]const u8 {
|
|
const decoder = std.base64.Base64Decoder.init(
|
|
std.base64.url_safe_no_pad.alphabet_chars,
|
|
std.base64.url_safe_no_pad.pad_char,
|
|
);
|
|
const size = try decoder.calcSizeForSlice(input);
|
|
const ptr = try allocator.alloc(u8, size);
|
|
try decoder.decode(ptr, input);
|
|
return ptr;
|
|
}
|
|
|
|
/// Print a success confirmation.
|
|
pub fn printSuccess() void {
|
|
std.debug.print(" ✅\n", .{});
|
|
}
|
|
|
|
/// Print a failure confirmation.
|
|
pub fn printFailure() void {
|
|
std.debug.print(" ❌\n", .{});
|
|
}
|
|
|
|
/// Verifies that cwd is the root of a Jetzig project
|
|
pub fn detectJetzigProjectDir() !std.fs.Dir {
|
|
var dir = try std.fs.cwd().openDir(".", .{});
|
|
const max_parent_dirs: usize = 100; // Prevent symlink loops or other weird stuff.
|
|
|
|
for (0..max_parent_dirs) |_| {
|
|
if (try isPath(dir, "build.zig", .file) and try isPath(dir, "src/app/views", .dir)) return dir;
|
|
|
|
dir = dir.openDir("..", .{}) catch |err| {
|
|
switch (err) {
|
|
error.FileNotFound, error.NotDir => {
|
|
std.debug.print(
|
|
"Encountered unexpected detecting Jetzig project directory: {s}\n",
|
|
.{@errorName(err)},
|
|
);
|
|
return error.JetzigCommandError;
|
|
},
|
|
else => return err,
|
|
}
|
|
};
|
|
continue;
|
|
}
|
|
|
|
std.debug.print(
|
|
\\Exceeded maximum parent directory depth.
|
|
\\Unable to detect Jetzig project directory.
|
|
\\
|
|
,
|
|
.{},
|
|
);
|
|
return error.JetzigCommandError;
|
|
}
|
|
|
|
fn isPath(dir: std.fs.Dir, sub_path: []const u8, path_type: enum { file, dir }) !bool {
|
|
switch (path_type) {
|
|
.file => {
|
|
_ = dir.statFile(sub_path) catch |err| {
|
|
switch (err) {
|
|
error.FileNotFound => return false,
|
|
else => return err,
|
|
}
|
|
};
|
|
return true;
|
|
},
|
|
.dir => {
|
|
var test_dir = dir.openDir(sub_path, .{}) catch |err| {
|
|
switch (err) {
|
|
error.FileNotFound, error.NotDir => return false,
|
|
else => return err,
|
|
}
|
|
};
|
|
test_dir.close();
|
|
return true;
|
|
},
|
|
}
|
|
}
|
|
|
|
// Strip leading and trailing whitespace from a u8 slice.
|
|
pub fn strip(input: []const u8) []const u8 {
|
|
return std.mem.trim(u8, input, &std.ascii.whitespace);
|
|
}
|
|
|
|
/// Attempts to confirm if a string input is in CamelCase. False if the first character is
|
|
/// not alphabetic lower-case or if the input contains underscores.
|
|
pub fn isCamelCase(input: []const u8) bool {
|
|
if (input.len == 0) return false;
|
|
if (!std.mem.containsAtLeast(u8, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1, &[_]u8{input[0]})) return false;
|
|
if (std.mem.containsAtLeast(u8, input, 1, "_")) return false;
|
|
|
|
return true;
|
|
}
|