diff --git a/src/main.zig b/src/main.zig index ffe5a9c8ea..d939eebc68 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4752,13 +4752,16 @@ pub fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void // Mark any excluded files/directories as already seen, // so that they are skipped later during actual processing for (excluded_files.items) |file_path| { - var dir = fs.cwd().openDir(file_path, .{}) catch |err| switch (err) { + const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { error.FileNotFound => continue, + // On Windows, statFile does not work for directories + error.IsDir => dir: { + var dir = try fs.cwd().openDir(file_path, .{}); + defer dir.close(); + break :dir try dir.stat(); + }, else => |e| return e, }; - defer dir.close(); - - const stat = try dir.stat(); try fmt.seen.put(stat.inode, {}); } diff --git a/test/tests.zig b/test/tests.zig index 5912ceb907..b73b5f0519 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -790,6 +790,10 @@ pub fn addCliTests(b: *std.Build) *Step { defer dir.close(); dir.writeFile("fmt1.zig", unformatted_code) catch @panic("unhandled"); dir.writeFile("fmt2.zig", unformatted_code) catch @panic("unhandled"); + dir.makeDir("subdir") catch @panic("unhandled"); + var subdir = dir.openDir("subdir", .{}) catch @panic("unhandled"); + defer subdir.close(); + subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled"); // Test zig fmt affecting only the appropriate files. const run1 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "fmt1.zig" }); @@ -799,46 +803,62 @@ pub fn addCliTests(b: *std.Build) *Step { // stdout should be file path + \n run1.expectStdOutEqual("fmt1.zig\n"); - // running it on the dir, only the new file should be changed - const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); - run2.setName("run zig fmt the directory"); + // Test excluding files and directories from a run + const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); + run2.setName("run zig fmt on directory with exclusions"); run2.cwd = tmp_path; run2.has_side_effects = true; - run2.expectStdOutEqual("." ++ s ++ "fmt2.zig\n"); + run2.expectStdOutEqual(""); run2.step.dependOn(&run1.step); - // both files have been formatted, nothing should change now - const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); - run3.setName("run zig fmt with nothing to do"); + // Test excluding non-existent file + const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); + run3.setName("run zig fmt on directory with non-existent exclusion"); run3.cwd = tmp_path; run3.has_side_effects = true; - run3.expectStdOutEqual(""); + run3.expectStdOutEqual("." ++ s ++ "subdir" ++ s ++ "fmt3.zig\n"); run3.step.dependOn(&run2.step); - const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00"; - const fmt4_path = std.fs.path.join(b.allocator, &.{ tmp_path, "fmt4.zig" }) catch @panic("OOM"); - const write4 = b.addWriteFiles(); - write4.addBytesToSource(unformatted_code_utf16, fmt4_path); - write4.step.dependOn(&run3.step); - - // Test `zig fmt` handling UTF-16 decoding. + // running it on the dir, only the new file should be changed const run4 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); - run4.setName("run zig fmt convert UTF-16 to UTF-8"); + run4.setName("run zig fmt the directory"); run4.cwd = tmp_path; run4.has_side_effects = true; - run4.expectStdOutEqual("." ++ s ++ "fmt4.zig\n"); - run4.step.dependOn(&write4.step); + run4.expectStdOutEqual("." ++ s ++ "fmt2.zig\n"); + run4.step.dependOn(&run3.step); + + // both files have been formatted, nothing should change now + const run5 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); + run5.setName("run zig fmt with nothing to do"); + run5.cwd = tmp_path; + run5.has_side_effects = true; + run5.expectStdOutEqual(""); + run5.step.dependOn(&run4.step); + + const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00"; + const fmt6_path = std.fs.path.join(b.allocator, &.{ tmp_path, "fmt6.zig" }) catch @panic("OOM"); + const write6 = b.addWriteFiles(); + write6.addBytesToSource(unformatted_code_utf16, fmt6_path); + write6.step.dependOn(&run5.step); + + // Test `zig fmt` handling UTF-16 decoding. + const run6 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); + run6.setName("run zig fmt convert UTF-16 to UTF-8"); + run6.cwd = tmp_path; + run6.has_side_effects = true; + run6.expectStdOutEqual("." ++ s ++ "fmt6.zig\n"); + run6.step.dependOn(&write6.step); // TODO change this to an exact match - const check4 = b.addCheckFile(.{ .path = fmt4_path }, .{ + const check6 = b.addCheckFile(.{ .path = fmt6_path }, .{ .expected_matches = &.{ "// no reason", }, }); - check4.step.dependOn(&run4.step); + check6.step.dependOn(&run6.step); const cleanup = b.addRemoveDirTree(tmp_path); - cleanup.step.dependOn(&check4.step); + cleanup.step.dependOn(&check6.step); step.dependOn(&cleanup.step); }