| ... | ... | @@ -4648,14 +4648,14 @@ const usage_init = |
| 4648 | 4648 | fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 4649 | 4649 | dev.check(.init_command); |
| 4650 | 4650 | |
| 4651 | | var strip = false; |
| 4651 | var template: enum { example, minimal } = .example; |
| 4652 | 4652 | { |
| 4653 | 4653 | var i: usize = 0; |
| 4654 | 4654 | while (i < args.len) : (i += 1) { |
| 4655 | 4655 | const arg = args[i]; |
| 4656 | 4656 | if (mem.startsWith(u8, arg, "-")) { |
| 4657 | | if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip")) { |
| 4658 | | strip = true; |
| 4657 | if (mem.eql(u8, arg, "-m") or mem.eql(u8, arg, "--minimal")) { |
| 4658 | template = .minimal; |
| 4659 | 4659 | } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 4660 | 4660 | try fs.File.stdout().writeAll(usage_init); |
| 4661 | 4661 | return cleanExit(); |
| ... | ... | @@ -4668,40 +4668,79 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 4668 | 4668 | } |
| 4669 | 4669 | } |
| 4670 | 4670 | |
| 4671 | | var templates = findTemplates(gpa, arena, strip); |
| 4672 | | defer templates.deinit(); |
| 4673 | | |
| 4674 | 4671 | const cwd_path = try introspect.getResolvedCwd(arena); |
| 4675 | 4672 | const cwd_basename = fs.path.basename(cwd_path); |
| 4676 | 4673 | const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename); |
| 4677 | 4674 | |
| 4678 | | const s = fs.path.sep_str; |
| 4679 | | const template_paths = [_][]const u8{ |
| 4680 | | Package.build_zig_basename, |
| 4681 | | Package.Manifest.basename, |
| 4682 | | "src" ++ s ++ "main.zig", |
| 4683 | | "src" ++ s ++ "root.zig", |
| 4684 | | }; |
| 4685 | | var ok_count: usize = 0; |
| 4686 | | |
| 4687 | 4675 | const fingerprint: Package.Fingerprint = .generate(sanitized_root_name); |
| 4688 | 4676 | |
| 4689 | | for (template_paths) |template_path| { |
| 4690 | | if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { |
| 4691 | | std.log.info("created {s}", .{template_path}); |
| 4692 | | ok_count += 1; |
| 4693 | | } else |err| switch (err) { |
| 4694 | | error.PathAlreadyExists => std.log.info("preserving already existing file: {s}", .{ |
| 4695 | | template_path, |
| 4696 | | }), |
| 4697 | | else => std.log.err("unable to write {s}: {s}\n", .{ template_path, @errorName(err) }), |
| 4698 | | } |
| 4699 | | } |
| 4677 | switch (template) { |
| 4678 | .example => { |
| 4679 | var templates = findTemplates(gpa, arena); |
| 4680 | defer templates.deinit(); |
| 4681 | |
| 4682 | const s = fs.path.sep_str; |
| 4683 | const template_paths = [_][]const u8{ |
| 4684 | Package.build_zig_basename, |
| 4685 | Package.Manifest.basename, |
| 4686 | "src" ++ s ++ "main.zig", |
| 4687 | "src" ++ s ++ "root.zig", |
| 4688 | }; |
| 4689 | var ok_count: usize = 0; |
| 4690 | |
| 4691 | for (template_paths) |template_path| { |
| 4692 | if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { |
| 4693 | std.log.info("created {s}", .{template_path}); |
| 4694 | ok_count += 1; |
| 4695 | } else |err| switch (err) { |
| 4696 | error.PathAlreadyExists => std.log.info("preserving already existing file: {s}", .{ |
| 4697 | template_path, |
| 4698 | }), |
| 4699 | else => std.log.err("unable to write {s}: {s}\n", .{ template_path, @errorName(err) }), |
| 4700 | } |
| 4701 | } |
| 4700 | 4702 | |
| 4701 | | if (ok_count == template_paths.len) { |
| 4702 | | std.log.info("see `zig build --help` for a menu of options", .{}); |
| 4703 | if (ok_count == template_paths.len) { |
| 4704 | std.log.info("see `zig build --help` for a menu of options", .{}); |
| 4705 | } |
| 4706 | return cleanExit(); |
| 4707 | }, |
| 4708 | .minimal => { |
| 4709 | writeSimpleTemplateFile(Package.Manifest.basename, |
| 4710 | \\.{{ |
| 4711 | \\ .name = .{s}, |
| 4712 | \\ .version = "{s}", |
| 4713 | \\ .paths = .{{""}}, |
| 4714 | \\ .fingerprint = 0x{x}, |
| 4715 | \\}} |
| 4716 | \\ |
| 4717 | , .{ |
| 4718 | sanitized_root_name, |
| 4719 | build_options.version, |
| 4720 | fingerprint.int(), |
| 4721 | }) catch |err| switch (err) { |
| 4722 | else => fatal("failed to create '{s}': {s}", .{ Package.Manifest.basename, @errorName(err) }), |
| 4723 | error.PathAlreadyExists => fatal("refusing to overwrite '{s}'", .{Package.Manifest.basename}), |
| 4724 | }; |
| 4725 | writeSimpleTemplateFile(Package.build_zig_basename, |
| 4726 | \\const std = @import("std"); |
| 4727 | \\pub fn build(b: *std.Build) void {{ |
| 4728 | \\ _ = b; // stub |
| 4729 | \\}} |
| 4730 | \\ |
| 4731 | , .{}) catch |err| switch (err) { |
| 4732 | else => fatal("failed to create '{s}': {s}", .{ Package.build_zig_basename, @errorName(err) }), |
| 4733 | // `build.zig` already existing is okay: the user has just used `zig init` to set up |
| 4734 | // their `build.zig.zon` *after* writing their `build.zig`. So this one isn't fatal. |
| 4735 | error.PathAlreadyExists => { |
| 4736 | std.log.info("successfully populated '{s}', preserving existing '{s}'", .{ Package.Manifest.basename, Package.build_zig_basename }); |
| 4737 | return cleanExit(); |
| 4738 | }, |
| 4739 | }; |
| 4740 | std.log.info("successfully populated '{s}' and '{s}'", .{ Package.Manifest.basename, Package.build_zig_basename }); |
| 4741 | return cleanExit(); |
| 4742 | }, |
| 4703 | 4743 | } |
| 4704 | | return cleanExit(); |
| 4705 | 4744 | } |
| 4706 | 4745 | |
| 4707 | 4746 | fn sanitizeExampleName(arena: Allocator, bytes: []const u8) error{OutOfMemory}![]const u8 { |
| ... | ... | @@ -7229,13 +7268,20 @@ fn loadManifest( |
| 7229 | 7268 | 0, |
| 7230 | 7269 | ) catch |err| switch (err) { |
| 7231 | 7270 | error.FileNotFound => { |
| 7232 | | const fingerprint: Package.Fingerprint = .generate(options.root_name); |
| 7233 | | var templates = findTemplates(gpa, arena, true); |
| 7234 | | defer templates.deinit(); |
| 7235 | | templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, fingerprint) catch |e| { |
| 7236 | | fatal("unable to write {s}: {s}", .{ |
| 7237 | | Package.Manifest.basename, @errorName(e), |
| 7238 | | }); |
| 7271 | writeSimpleTemplateFile(Package.Manifest.basename, |
| 7272 | \\.{{ |
| 7273 | \\ .name = .{s}, |
| 7274 | \\ .version = "{s}", |
| 7275 | \\ .paths = .{{""}}, |
| 7276 | \\ .fingerprint = 0x{x}, |
| 7277 | \\}} |
| 7278 | \\ |
| 7279 | , .{ |
| 7280 | options.root_name, |
| 7281 | build_options.version, |
| 7282 | Package.Fingerprint.generate(options.root_name).int(), |
| 7283 | }) catch |e| { |
| 7284 | fatal("unable to write {s}: {s}", .{ Package.Manifest.basename, @errorName(e) }); |
| 7239 | 7285 | }; |
| 7240 | 7286 | continue; |
| 7241 | 7287 | }, |
| ... | ... | @@ -7276,7 +7322,6 @@ const Templates = struct { |
| 7276 | 7322 | zig_lib_directory: Cache.Directory, |
| 7277 | 7323 | dir: fs.Dir, |
| 7278 | 7324 | buffer: std.ArrayList(u8), |
| 7279 | | strip: bool, |
| 7280 | 7325 | |
| 7281 | 7326 | fn deinit(templates: *Templates) void { |
| 7282 | 7327 | templates.zig_lib_directory.handle.close(); |
| ... | ... | @@ -7305,23 +7350,9 @@ const Templates = struct { |
| 7305 | 7350 | }; |
| 7306 | 7351 | templates.buffer.clearRetainingCapacity(); |
| 7307 | 7352 | try templates.buffer.ensureUnusedCapacity(contents.len); |
| 7308 | | var new_line = templates.strip; |
| 7309 | 7353 | var i: usize = 0; |
| 7310 | 7354 | while (i < contents.len) { |
| 7311 | | if (new_line) { |
| 7312 | | const trimmed = std.mem.trimLeft(u8, contents[i..], " "); |
| 7313 | | if (std.mem.startsWith(u8, trimmed, "//")) { |
| 7314 | | i += std.mem.indexOfScalar(u8, contents[i..], '\n') orelse break; |
| 7315 | | i += 1; |
| 7316 | | continue; |
| 7317 | | } else { |
| 7318 | | new_line = false; |
| 7319 | | } |
| 7320 | | } |
| 7321 | | |
| 7322 | | if (templates.strip and contents[i] == '\n') { |
| 7323 | | new_line = true; |
| 7324 | | } else if (contents[i] == '_' or contents[i] == '.') { |
| 7355 | if (contents[i] == '_' or contents[i] == '.') { |
| 7325 | 7356 | // Both '_' and '.' are allowed because depending on the context |
| 7326 | 7357 | // one prefix will be valid, while the other might not. |
| 7327 | 7358 | if (std.mem.startsWith(u8, contents[i + 1 ..], "NAME")) { |
| ... | ... | @@ -7350,8 +7381,16 @@ const Templates = struct { |
| 7350 | 7381 | }); |
| 7351 | 7382 | } |
| 7352 | 7383 | }; |
| 7384 | fn writeSimpleTemplateFile(file_name: []const u8, comptime fmt: []const u8, args: anytype) !void { |
| 7385 | const f = try fs.cwd().createFile(file_name, .{ .exclusive = true }); |
| 7386 | defer f.close(); |
| 7387 | var buf: [4096]u8 = undefined; |
| 7388 | var fw = f.writer(&buf); |
| 7389 | try fw.interface.print(fmt, args); |
| 7390 | try fw.interface.flush(); |
| 7391 | } |
| 7353 | 7392 | |
| 7354 | | fn findTemplates(gpa: Allocator, arena: Allocator, strip: bool) Templates { |
| 7393 | fn findTemplates(gpa: Allocator, arena: Allocator) Templates { |
| 7355 | 7394 | const cwd_path = introspect.getResolvedCwd(arena) catch |err| { |
| 7356 | 7395 | fatal("unable to get cwd: {s}", .{@errorName(err)}); |
| 7357 | 7396 | }; |
| ... | ... | @@ -7375,7 +7414,6 @@ fn findTemplates(gpa: Allocator, arena: Allocator, strip: bool) Templates { |
| 7375 | 7414 | .zig_lib_directory = zig_lib_directory, |
| 7376 | 7415 | .dir = template_dir, |
| 7377 | 7416 | .buffer = std.ArrayList(u8).init(gpa), |
| 7378 | | .strip = strip, |
| 7379 | 7417 | }; |
| 7380 | 7418 | } |
| 7381 | 7419 | |