| ... | @@ -4648,14 +4648,14 @@ const usage_init = | ... | @@ -4648,14 +4648,14 @@ const usage_init = |
| 4648 | fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | 4648 | fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { |
| 4649 | dev.check(.init_command); | 4649 | dev.check(.init_command); |
| 4650 | | 4650 | |
| 4651 | var strip = false; | 4651 | var template: enum { example, minimal } = .example; |
| 4652 | { | 4652 | { |
| 4653 | var i: usize = 0; | 4653 | var i: usize = 0; |
| 4654 | while (i < args.len) : (i += 1) { | 4654 | while (i < args.len) : (i += 1) { |
| 4655 | const arg = args[i]; | 4655 | const arg = args[i]; |
| 4656 | if (mem.startsWith(u8, arg, "-")) { | 4656 | if (mem.startsWith(u8, arg, "-")) { |
| 4657 | if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip")) { | 4657 | if (mem.eql(u8, arg, "-m") or mem.eql(u8, arg, "--minimal")) { |
| 4658 | strip = true; | 4658 | template = .minimal; |
| 4659 | } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { | 4659 | } else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 4660 | try fs.File.stdout().writeAll(usage_init); | 4660 | try fs.File.stdout().writeAll(usage_init); |
| 4661 | return cleanExit(); | 4661 | return cleanExit(); |
| ... | @@ -4668,40 +4668,79 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { | ... | @@ -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 | const cwd_path = try introspect.getResolvedCwd(arena); | 4671 | const cwd_path = try introspect.getResolvedCwd(arena); |
| 4675 | const cwd_basename = fs.path.basename(cwd_path); | 4672 | const cwd_basename = fs.path.basename(cwd_path); |
| 4676 | const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename); | 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 | const fingerprint: Package.Fingerprint = .generate(sanitized_root_name); | 4675 | const fingerprint: Package.Fingerprint = .generate(sanitized_root_name); |
| 4688 | | 4676 | |
| 4689 | for (template_paths) |template_path| { | 4677 | switch (template) { |
| 4690 | if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| { | 4678 | .example => { |
| 4691 | std.log.info("created {s}", .{template_path}); | 4679 | var templates = findTemplates(gpa, arena); |
| 4692 | ok_count += 1; | 4680 | defer templates.deinit(); |
| 4693 | } else |err| switch (err) { | 4681 | |
| 4694 | error.PathAlreadyExists => std.log.info("preserving already existing file: {s}", .{ | 4682 | const s = fs.path.sep_str; |
| 4695 | template_path, | 4683 | const template_paths = [_][]const u8{ |
| 4696 | }), | 4684 | Package.build_zig_basename, |
| 4697 | else => std.log.err("unable to write {s}: {s}\n", .{ template_path, @errorName(err) }), | 4685 | Package.Manifest.basename, |
| 4698 | } | 4686 | "src" ++ s ++ "main.zig", |
| 4699 | } | 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) { | 4703 | if (ok_count == template_paths.len) { |
| 4702 | std.log.info("see `zig build --help` for a menu of options", .{}); | 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 | fn sanitizeExampleName(arena: Allocator, bytes: []const u8) error{OutOfMemory}![]const u8 { | 4746 | fn sanitizeExampleName(arena: Allocator, bytes: []const u8) error{OutOfMemory}![]const u8 { |
| ... | @@ -7229,13 +7268,20 @@ fn loadManifest( | ... | @@ -7229,13 +7268,20 @@ fn loadManifest( |
| 7229 | 0, | 7268 | 0, |
| 7230 | ) catch |err| switch (err) { | 7269 | ) catch |err| switch (err) { |
| 7231 | error.FileNotFound => { | 7270 | error.FileNotFound => { |
| 7232 | const fingerprint: Package.Fingerprint = .generate(options.root_name); | 7271 | writeSimpleTemplateFile(Package.Manifest.basename, |
| 7233 | var templates = findTemplates(gpa, arena, true); | 7272 | \\.{{ |
| 7234 | defer templates.deinit(); | 7273 | \\ .name = .{s}, |
| 7235 | templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, fingerprint) catch |e| { | 7274 | \\ .version = "{s}", |
| 7236 | fatal("unable to write {s}: {s}", .{ | 7275 | \\ .paths = .{{""}}, |
| 7237 | Package.Manifest.basename, @errorName(e), | 7276 | \\ .fingerprint = 0x{x}, |
| 7238 | }); | 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 | continue; | 7286 | continue; |
| 7241 | }, | 7287 | }, |
| ... | @@ -7276,7 +7322,6 @@ const Templates = struct { | ... | @@ -7276,7 +7322,6 @@ const Templates = struct { |
| 7276 | zig_lib_directory: Cache.Directory, | 7322 | zig_lib_directory: Cache.Directory, |
| 7277 | dir: fs.Dir, | 7323 | dir: fs.Dir, |
| 7278 | buffer: std.ArrayList(u8), | 7324 | buffer: std.ArrayList(u8), |
| 7279 | strip: bool, | | |
| 7280 | | 7325 | |
| 7281 | fn deinit(templates: *Templates) void { | 7326 | fn deinit(templates: *Templates) void { |
| 7282 | templates.zig_lib_directory.handle.close(); | 7327 | templates.zig_lib_directory.handle.close(); |
| ... | @@ -7305,23 +7350,9 @@ const Templates = struct { | ... | @@ -7305,23 +7350,9 @@ const Templates = struct { |
| 7305 | }; | 7350 | }; |
| 7306 | templates.buffer.clearRetainingCapacity(); | 7351 | templates.buffer.clearRetainingCapacity(); |
| 7307 | try templates.buffer.ensureUnusedCapacity(contents.len); | 7352 | try templates.buffer.ensureUnusedCapacity(contents.len); |
| 7308 | var new_line = templates.strip; | | |
| 7309 | var i: usize = 0; | 7353 | var i: usize = 0; |
| 7310 | while (i < contents.len) { | 7354 | while (i < contents.len) { |
| 7311 | if (new_line) { | 7355 | if (contents[i] == '_' or contents[i] == '.') { |
| 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] == '.') { | | |
| 7325 | // Both '_' and '.' are allowed because depending on the context | 7356 | // Both '_' and '.' are allowed because depending on the context |
| 7326 | // one prefix will be valid, while the other might not. | 7357 | // one prefix will be valid, while the other might not. |
| 7327 | if (std.mem.startsWith(u8, contents[i + 1 ..], "NAME")) { | 7358 | if (std.mem.startsWith(u8, contents[i + 1 ..], "NAME")) { |
| ... | @@ -7350,8 +7381,16 @@ const Templates = struct { | ... | @@ -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 | const cwd_path = introspect.getResolvedCwd(arena) catch |err| { | 7394 | const cwd_path = introspect.getResolvedCwd(arena) catch |err| { |
| 7356 | fatal("unable to get cwd: {s}", .{@errorName(err)}); | 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,7 +7414,6 @@ fn findTemplates(gpa: Allocator, arena: Allocator, strip: bool) Templates { |
| 7375 | .zig_lib_directory = zig_lib_directory, | 7414 | .zig_lib_directory = zig_lib_directory, |
| 7376 | .dir = template_dir, | 7415 | .dir = template_dir, |
| 7377 | .buffer = std.ArrayList(u8).init(gpa), | 7416 | .buffer = std.ArrayList(u8).init(gpa), |
| 7378 | .strip = strip, | | |
| 7379 | }; | 7417 | }; |
| 7380 | } | 7418 | } |
| 7381 | | 7419 | |