authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-27 18:28:53-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-04-27 18:28:53-04:00
logecdf75d04e0b0193934d019e08aa46c45b67bef4
tree7d28d08307587391572fda48d520c93aed3a9ca2
parent45f4a1124f80219d9237d6809ecb919a8896723a
parent1e04e852009b969741e2969f2aeedb72d73d326a
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5187 from ziglang/squeek502-windows-fmt-relative

zig fmt: Fix relative paths with . and .. on Windows as well as forward slashes

3 files changed, 31 insertions(+), 15 deletions(-)

lib/std/io/buffered_atomic_file.zig+7-3
...@@ -15,8 +15,12 @@ pub const BufferedAtomicFile = struct {...@@ -15,8 +15,12 @@ pub const BufferedAtomicFile = struct {
1515
16 /// TODO when https://github.com/ziglang/zig/issues/2761 is solved16 /// TODO when https://github.com/ziglang/zig/issues/2761 is solved
17 /// this API will not need an allocator17 /// this API will not need an allocator
18 /// TODO integrate this with Dir API18 pub fn create(
19 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {19 allocator: *mem.Allocator,
20 dir: fs.Dir,
21 dest_path: []const u8,
22 atomic_file_options: fs.Dir.AtomicFileOptions,
23 ) !*BufferedAtomicFile {
20 var self = try allocator.create(BufferedAtomicFile);24 var self = try allocator.create(BufferedAtomicFile);
21 self.* = BufferedAtomicFile{25 self.* = BufferedAtomicFile{
22 .atomic_file = undefined,26 .atomic_file = undefined,
...@@ -26,7 +30,7 @@ pub const BufferedAtomicFile = struct {...@@ -26,7 +30,7 @@ pub const BufferedAtomicFile = struct {
26 };30 };
27 errdefer allocator.destroy(self);31 errdefer allocator.destroy(self);
2832
29 self.atomic_file = try fs.cwd().atomicFile(dest_path, .{});33 self.atomic_file = try dir.atomicFile(dest_path, atomic_file_options);
30 errdefer self.atomic_file.deinit();34 errdefer self.atomic_file.deinit();
3135
32 self.file_stream = self.atomic_file.file.outStream();36 self.file_stream = self.atomic_file.file.outStream();
lib/std/os/windows.zig+12-7
...@@ -1260,15 +1260,9 @@ pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE:0]u16 {...@@ -1260,15 +1260,9 @@ pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE:0]u16 {
1260pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len:0]u16 {1260pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len:0]u16 {
1261 // TODO https://github.com/ziglang/zig/issues/27651261 // TODO https://github.com/ziglang/zig/issues/2765
1262 var result: [PATH_MAX_WIDE + suffix.len:0]u16 = undefined;1262 var result: [PATH_MAX_WIDE + suffix.len:0]u16 = undefined;
1263 // > File I/O functions in the Windows API convert "/" to "\" as part of
1264 // > converting the name to an NT-style name, except when using the "\\?\"
1265 // > prefix as detailed in the following sections.
1266 // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
1267 // Because we want the larger maximum path length for absolute paths, we
1268 // disallow forward slashes in zig std lib file functions on Windows.
1269 for (s) |byte| {1263 for (s) |byte| {
1270 switch (byte) {1264 switch (byte) {
1271 '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName,1265 '*', '?', '"', '<', '>', '|' => return error.BadPathName,
1272 else => {},1266 else => {},
1273 }1267 }
1274 }1268 }
...@@ -1279,6 +1273,17 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)...@@ -1279,6 +1273,17 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
1279 };1273 };
1280 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);1274 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);
1281 if (end_index + suffix.len > result.len) return error.NameTooLong;1275 if (end_index + suffix.len > result.len) return error.NameTooLong;
1276 // > File I/O functions in the Windows API convert "/" to "\" as part of
1277 // > converting the name to an NT-style name, except when using the "\\?\"
1278 // > prefix as detailed in the following sections.
1279 // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
1280 // Because we want the larger maximum path length for absolute paths, we
1281 // convert forward slashes to backward slashes here.
1282 for (result[0..end_index]) |*elem| {
1283 if (elem.* == '/') {
1284 elem.* = '\\';
1285 }
1286 }
1282 mem.copy(u16, result[end_index..], suffix);1287 mem.copy(u16, result[end_index..], suffix);
1283 result[end_index + suffix.len] = 0;1288 result[end_index + suffix.len] = 0;
1284 return result;1289 return result;
src-self-hosted/stage2.zig+12-5
...@@ -318,11 +318,18 @@ const FmtError = error{...@@ -318,11 +318,18 @@ const FmtError = error{
318} || fs.File.OpenError;318} || fs.File.OpenError;
319319
320fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {320fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
321 if (fmt.seen.exists(file_path)) return;321 // get the real path here to avoid Windows failing on relative file paths with . or .. in them
322 try fmt.seen.put(file_path);322 var real_path = fs.realpathAlloc(fmt.allocator, file_path) catch |err| {
323 try stderr.print("unable to open '{}': {}\n", .{ file_path, err });
324 fmt.any_error = true;
325 return;
326 };
327 defer fmt.allocator.free(real_path);
328
329 if (fmt.seen.exists(real_path)) return;
330 try fmt.seen.put(real_path);
323331
324 const max = std.math.maxInt(usize);332 const source_code = fs.cwd().readFileAlloc(fmt.allocator, real_path, self_hosted_main.max_src_size) catch |err| switch (err) {
325 const source_code = fs.cwd().readFileAlloc(fmt.allocator, file_path, max) catch |err| switch (err) {
326 error.IsDir, error.AccessDenied => {333 error.IsDir, error.AccessDenied => {
327 // TODO make event based (and dir.next())334 // TODO make event based (and dir.next())
328 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });335 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
...@@ -370,7 +377,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {...@@ -370,7 +377,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
370 fmt.any_error = true;377 fmt.any_error = true;
371 }378 }
372 } else {379 } else {
373 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);380 const baf = try io.BufferedAtomicFile.create(fmt.allocator, fs.cwd(), real_path, .{});
374 defer baf.destroy();381 defer baf.destroy();
375382
376 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);383 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);