-
Notifications
You must be signed in to change notification settings - Fork 0
/
liza.zig
220 lines (196 loc) · 7.67 KB
/
liza.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
const std = @import("std");
// Common paths.
const LICENSE = "LICENSE";
const CD_WORKFLOW = "cd.yaml";
const CI_WORKFLOW = "ci.yaml";
const TEMPLATES = "templates/";
const GITIGNORE = ".gitignore";
const WORKFLOWS = ".github/workflows/";
const GITATTRIBUTES = ".gitattributes";
// Custom paths.
const SRC = "src/";
const EXE = "exe/";
const LIB = "lib/";
const PRT = "prt/";
const README = "README.md";
const LIB_ROOT = "lib.zig";
const EXE_ROOT = "main.zig";
const EXAMPLES = "examples/";
const BUILD_ZIG = "build.zig";
const BUILD_ZON = "build.zig.zon";
const EXAMPLE1 = EXAMPLES ++ "example1/";
const EXAMPLE2 = EXAMPLES ++ "example2/";
// Common templates.
const ALL_LICENSE = @embedFile(TEMPLATES ++ LICENSE);
const ALL_GITIGNORE = @embedFile(TEMPLATES ++ GITIGNORE);
const ALL_GITATTRIBUTES = @embedFile(TEMPLATES ++ GITATTRIBUTES);
const ALL_CD_WORKFLOW = @embedFile(TEMPLATES ++ WORKFLOWS ++ CD_WORKFLOW);
const ALL_CI_WORKFLOW = @embedFile(TEMPLATES ++ WORKFLOWS ++ CI_WORKFLOW);
// Executable templates.
const EXE_CI_STEP = "exe";
const EXE_README = @embedFile(TEMPLATES ++ EXE ++ README);
const EXE_BUILD_ZIG = @embedFile(TEMPLATES ++ EXE ++ BUILD_ZIG);
const EXE_BUILD_ZON = @embedFile(TEMPLATES ++ EXE ++ BUILD_ZON);
const EXE_TEXT = @embedFile(TEMPLATES ++ EXE ++ SRC ++ EXE_ROOT);
// Library templates.
const LIB_CI_STEP = "example";
const LIB_README = @embedFile(TEMPLATES ++ LIB ++ README);
const LIB_BUILD_ZIG = @embedFile(TEMPLATES ++ LIB ++ BUILD_ZIG);
const LIB_BUILD_ZON = @embedFile(TEMPLATES ++ LIB ++ BUILD_ZON);
const LIB_TEXT = @embedFile(TEMPLATES ++ LIB ++ SRC ++ LIB_ROOT);
const LIB_EXAMPLE1 = @embedFile(TEMPLATES ++ LIB ++ EXAMPLE1 ++ EXE_ROOT);
const LIB_EXAMPLE2 = @embedFile(TEMPLATES ++ LIB ++ EXAMPLE2 ++ EXE_ROOT);
// Port templates.
const PRT_CI_STEP = "lib";
const PRT_README = @embedFile(TEMPLATES ++ PRT ++ README);
const PRT_BUILD_ZIG = @embedFile(TEMPLATES ++ PRT ++ BUILD_ZIG);
const PRT_BUILD_ZON = @embedFile(TEMPLATES ++ PRT ++ BUILD_ZON);
const PRT_TEXT = @embedFile(TEMPLATES ++ PRT ++ SRC ++ LIB_ROOT);
pub const Codebase = enum {
exe,
lib,
prt,
};
pub fn initialize(
code_type: Codebase,
code_vrsn: std.SemanticVersion,
code_vrsn_str: []const u8,
repo_name: []const u8,
repo_desc: []const u8,
user_hndl: []const u8,
user_name: []const u8,
) !void {
var repo_dir = blk: {
const cur_dir = std.fs.cwd();
_ = cur_dir.access(repo_name, .{}) catch break :blk try cur_dir.makeOpenPath(repo_name, .{});
@panic("Directory already exists!");
};
defer repo_dir.close();
var workflows_dir = try repo_dir.makeOpenPath(WORKFLOWS, .{});
defer workflows_dir.close();
var src_dir = try repo_dir.makeOpenPath(SRC, .{});
defer src_dir.close();
try createLicense(user_name, repo_dir);
try createPlain(GITIGNORE, ALL_GITIGNORE, repo_dir);
try createPlain(GITATTRIBUTES, ALL_GITATTRIBUTES, repo_dir);
if (code_type != .prt) {
try createPlain(CD_WORKFLOW, ALL_CD_WORKFLOW, workflows_dir);
}
switch (code_type) {
.exe => {
try createCi(EXE_CI_STEP, workflows_dir);
try createPlain(EXE_ROOT, EXE_TEXT, src_dir);
try createBuild(.zig, .exe, repo_name, user_hndl, code_vrsn, repo_dir);
try createBuild(.zon, .exe, repo_name, user_hndl, code_vrsn_str, repo_dir);
try createReadme(EXE_README, repo_name, repo_desc, user_hndl, repo_dir);
},
.lib => {
var example1_dir = try repo_dir.makeOpenPath(EXAMPLE1, .{});
defer example1_dir.close();
var example2_dir = try repo_dir.makeOpenPath(EXAMPLE2, .{});
defer example2_dir.close();
try createCi(LIB_CI_STEP, workflows_dir);
try createPlain(LIB_ROOT, LIB_TEXT, src_dir);
try createPlain(EXE_ROOT, LIB_EXAMPLE1, example1_dir);
try createPlain(EXE_ROOT, LIB_EXAMPLE2, example2_dir);
try createBuild(.zig, .lib, repo_name, user_hndl, code_vrsn, repo_dir);
try createBuild(.zon, .lib, repo_name, user_hndl, code_vrsn_str, repo_dir);
try createReadme(LIB_README, repo_name, repo_desc, user_hndl, repo_dir);
},
.prt => {
try createCi(PRT_CI_STEP, workflows_dir);
try createPlain(LIB_ROOT, PRT_TEXT, src_dir);
try createBuild(.zig, .prt, repo_name, user_hndl, code_vrsn, repo_dir);
try createBuild(.zon, .prt, repo_name, user_hndl, code_vrsn_str, repo_dir);
try createReadme(PRT_README, repo_name, repo_desc, user_hndl, repo_dir);
},
}
}
fn createReadme(
comptime text: []const u8,
repo_name: []const u8,
repo_desc: []const u8,
user_hndl: []const u8,
repo_dir: std.fs.Dir,
) !void {
var readme_file = try repo_dir.createFile(README, .{});
defer readme_file.close();
var idx: usize = 0;
while (std.mem.indexOfScalar(u8, text[idx..], '?')) |i| : (idx += i + 2) {
try readme_file.writeAll(text[idx .. idx + i]);
switch (text[idx + i + 1]) {
'r' => try readme_file.writeAll(repo_name),
'd' => try readme_file.writeAll(repo_desc),
'u' => try readme_file.writeAll(user_hndl),
else => try readme_file.writeAll(text[idx + i .. idx + i + 2]),
}
}
try readme_file.writeAll(text[idx..]);
}
fn createBuild(
comptime mode: std.zig.Ast.Mode,
comptime codebase: Codebase,
repo_name: []const u8,
user_hndl: []const u8,
version: anytype,
repo_dir: std.fs.Dir,
) !void {
const text = switch (codebase) {
.exe => if (mode == .zig) EXE_BUILD_ZIG else EXE_BUILD_ZON,
.lib => if (mode == .zig) LIB_BUILD_ZIG else LIB_BUILD_ZON,
.prt => if (mode == .zig) PRT_BUILD_ZIG else PRT_BUILD_ZON,
};
var build_file = try repo_dir.createFile(if (mode == .zig) BUILD_ZIG else BUILD_ZON, .{});
const build_writer = build_file.writer();
defer build_file.close();
var idx: usize = 0;
while (std.mem.indexOfScalar(u8, text[idx..], '?')) |i| : (idx += i + 2) {
try build_file.writeAll(text[idx .. idx + i]);
switch (text[idx + i + 1]) {
'r' => try build_writer.writeAll(repo_name),
'v' => switch (mode) {
.zig => try build_writer.print(
" .major = {}, .minor = {}, .patch = {} ",
.{ version.major, version.minor, version.patch },
),
.zon => try build_writer.writeAll(version),
},
'u' => try build_writer.writeAll(user_hndl),
else => try build_writer.writeAll(text[idx + i .. idx + i + 2]),
}
}
try build_file.writeAll(text[idx..]);
}
fn createCi(
comptime step: []const u8,
workflows_dir: std.fs.Dir,
) !void {
var ci_file = try workflows_dir.createFile(CI_WORKFLOW, .{});
defer ci_file.close();
var idx: usize = 0;
while (std.mem.indexOfScalar(u8, ALL_CI_WORKFLOW[idx..], '?')) |i| : (idx += i + 1) {
try ci_file.writeAll(ALL_CI_WORKFLOW[idx .. idx + i]);
try ci_file.writeAll(step);
}
try ci_file.writeAll(ALL_CI_WORKFLOW[idx..]);
}
fn createLicense(
user_name: []const u8,
repo_dir: std.fs.Dir,
) !void {
var license_file = try repo_dir.createFile(LICENSE, .{});
defer license_file.close();
const idx = std.mem.indexOfScalar(u8, ALL_LICENSE, '?').?;
try license_file.writeAll(ALL_LICENSE[0..idx]);
try license_file.writeAll(user_name);
try license_file.writeAll(ALL_LICENSE[idx + 1 ..]);
}
fn createPlain(
comptime path: []const u8,
comptime text: []const u8,
dir: std.fs.Dir,
) !void {
var plain_file = try dir.createFile(path, .{});
defer plain_file.close();
try plain_file.writeAll(text);
}