Commit b9d86c6bc8

jagt <jagt@live.com>
2022-04-12 06:01:47
fix `link.renameTmpIntoCache` on windows when dest dir exists.
Previously it would fail as `renameW` do not ever fail with `PathAlreadyExists`. As a workaround we check for dest dir existence before rename on Windows.
1 parent c4aac28
Changed files (1)
src/link.zig
@@ -717,19 +717,38 @@ pub const File = struct {
         // directly, and remove this function from link.zig.
         _ = base;
         while (true) {
-            std.fs.rename(
-                cache_directory.handle,
-                tmp_dir_sub_path,
-                cache_directory.handle,
-                o_sub_path,
-            ) catch |err| switch (err) {
-                error.PathAlreadyExists => {
+            if (builtin.os.tag == .windows) {
+                // workaround windows `renameW` can't fail with `PathAlreadyExists`
+                // See https://github.com/ziglang/zig/issues/8362
+                if (cache_directory.handle.access(o_sub_path, .{})) |_| {
                     try cache_directory.handle.deleteTree(o_sub_path);
                     continue;
-                },
-                else => |e| return e,
-            };
-            break;
+                } else |err| switch (err) {
+                    error.FileNotFound => {},
+                    else => |e| return e,
+                }
+                try std.fs.rename(
+                    cache_directory.handle,
+                    tmp_dir_sub_path,
+                    cache_directory.handle,
+                    o_sub_path,
+                );
+                break;
+            } else {
+                std.fs.rename(
+                    cache_directory.handle,
+                    tmp_dir_sub_path,
+                    cache_directory.handle,
+                    o_sub_path,
+                ) catch |err| switch (err) {
+                    error.PathAlreadyExists => {
+                        try cache_directory.handle.deleteTree(o_sub_path);
+                        continue;
+                    },
+                    else => |e| return e,
+                };
+                break;
+            }
         }
     }