Skip to content

Commit 383a038

Browse files
authored
Support recursively deleting long file names on Windows (#256)
1 parent 2f625ce commit 383a038

File tree

2 files changed

+66
-38
lines changed

2 files changed

+66
-38
lines changed

pkgs/io_file/lib/src/vm_windows_file_system.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ final class WindowsFileSystem extends FileSystem {
510510
void removeDirectoryTree(String path) => using((arena) {
511511
_primeGetLastError();
512512

513+
path = _extendedPath(path, arena).toDartString();
513514
final findData = arena<win32.WIN32_FIND_DATA>();
514515
final searchPath = p.join(path, '*');
515516

pkgs/io_file/test/remove_directory_tree_test.dart

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -44,49 +44,40 @@ void main() {
4444
);
4545
});
4646

47-
test(
48-
'absolute path, long directory name',
49-
() {
50-
// On Windows:
51-
// When using an API to create a directory, the specified path cannot be
52-
// so long that you cannot append an 8.3 file name (that is, the
53-
// directory name cannot exceed MAX_PATH minus 12).
54-
final dirname =
55-
'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255);
56-
final path = p.join(tmp, dirname);
57-
io.Directory(path).createSync();
58-
io.File('$path/file').writeAsStringSync('Hello World!');
47+
test('absolute path, long directory name', () {
48+
// On Windows:
49+
// When using an API to create a directory, the specified path cannot be
50+
// so long that you cannot append an 8.3 file name (that is, the
51+
// directory name cannot exceed MAX_PATH minus 12).
52+
final dirname = 'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255);
53+
final path = p.join(tmp, dirname);
54+
io.Directory(path).createSync();
55+
io.File('$path/file').writeAsStringSync('Hello World!');
5956

60-
fileSystem.removeDirectoryTree(path);
57+
fileSystem.removeDirectoryTree(path);
6158

62-
expect(
63-
io.FileSystemEntity.typeSync(path),
64-
io.FileSystemEntityType.notFound,
65-
);
66-
},
67-
skip: io.Platform.isWindows ? 'TODO(bquinlan): make this pass' : false,
68-
);
59+
expect(
60+
io.FileSystemEntity.typeSync(path),
61+
io.FileSystemEntityType.notFound,
62+
);
63+
});
6964

70-
test(
71-
'relative path, long directory name',
72-
() {
73-
// On Windows:
74-
// When using an API to create a directory, the specified path cannot be
75-
// so long that you cannot append an 8.3 file name (that is, the
76-
// directory name cannot exceed MAX_PATH minus 12).
77-
final path = 'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255);
78-
io.Directory(path).createSync();
79-
io.File('$path/file').writeAsStringSync('Hello World!');
65+
test('relative path, long directory name', () {
66+
// On Windows:
67+
// When using an API to create a directory, the specified path cannot be
68+
// so long that you cannot append an 8.3 file name (that is, the
69+
// directory name cannot exceed MAX_PATH minus 12).
70+
final path = 'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255);
71+
io.Directory(path).createSync();
72+
io.File('$path/file').writeAsStringSync('Hello World!');
8073

81-
fileSystem.removeDirectoryTree(path);
74+
fileSystem.removeDirectoryTree(path);
8275

83-
expect(
84-
io.FileSystemEntity.typeSync(path),
85-
io.FileSystemEntityType.notFound,
86-
);
87-
},
88-
skip: io.Platform.isWindows ? 'TODO(bquinlan) make this pass' : false,
89-
);
76+
expect(
77+
io.FileSystemEntity.typeSync(path),
78+
io.FileSystemEntityType.notFound,
79+
);
80+
});
9081

9182
test('contains single file', () {
9283
final path = '$tmp/dir';
@@ -156,6 +147,42 @@ void main() {
156147
);
157148
});
158149

150+
test('complex tree of long paths', () {
151+
// On Windows:
152+
// When using an API to create a directory, the specified path cannot be
153+
// so long that you cannot append an 8.3 file name (that is, the
154+
// directory name cannot exceed MAX_PATH minus 12).
155+
void createTree(String path, int depth) {
156+
io.Directory(path).createSync();
157+
158+
final filePath = 'f' * 255;
159+
final fileLinkPath = 'l' * 255;
160+
final directoryPath =
161+
'd' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255);
162+
final directoryLinkPath =
163+
's' * (io.Platform.isWindows ? win32.MAX_PATH - 12 : 255);
164+
165+
io.File('$path/$filePath').writeAsStringSync('Hello World');
166+
io.Link('$path/$fileLinkPath').createSync('$path/file1');
167+
io.Link('$path/$directoryLinkPath').createSync(path);
168+
169+
if (depth > 0) {
170+
createTree('$path/$directoryPath', depth - 1);
171+
}
172+
}
173+
174+
final path = '$tmp/dir';
175+
// macOS has a maximum path length of 1024 characters.
176+
createTree(path, 2);
177+
178+
fileSystem.removeDirectoryTree(path);
179+
180+
expect(
181+
io.FileSystemEntity.typeSync(path),
182+
io.FileSystemEntityType.notFound,
183+
);
184+
});
185+
159186
test(
160187
'unremoveable file',
161188
() {

0 commit comments

Comments
 (0)