Skip to content

Commit d0c0174

Browse files
committed
delete broken symlinks
1 parent 981c47f commit d0c0174

File tree

1 file changed

+47
-27
lines changed

1 file changed

+47
-27
lines changed

src/index.ts

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ function doDeleteFile(currentFile: string, options: Options = {}) {
164164
return doDelete;
165165
}
166166

167+
function hasStats(dir: string) {
168+
try {
169+
fs.lstatSync(dir);
170+
return true;
171+
} catch (err) {
172+
return false;
173+
}
174+
}
175+
167176
/**
168177
* FindRemoveSync(currentDir, options) takes any start directory and searches files from there for removal.
169178
* the selection of files for removal depends on the given options. when no options are given, or only the maxLevel
@@ -185,9 +194,22 @@ const findRemoveSync = function (
185194
) {
186195
let removed: Record<string, boolean> = {};
187196

188-
if (!isOverTheLimit(options) && fs.existsSync(currentDir)) {
197+
if (isOverTheLimit(options)) {
198+
// Return early in that case
199+
return removed;
200+
}
201+
202+
let deleteDirectory = false;
203+
204+
const dirExists = fs.existsSync(currentDir);
205+
const dirHasStats = hasStats(currentDir);
206+
207+
if (dirExists && !dirHasStats) {
208+
// Must be a broken symlink. Flag it for deletion. See:
209+
// https://github.com/binarykitchen/find-remove/issues/42
210+
deleteDirectory = true;
211+
} else if (dirExists) {
189212
const maxLevel = getMaxLevel(options);
190-
let deleteDirectory = false;
191213

192214
if (options.limit !== undefined) {
193215
options.totalRemoved =
@@ -237,42 +259,40 @@ const findRemoveSync = function (
237259
if (options.totalRemoved !== undefined) {
238260
options.totalRemoved += Object.keys(result).length;
239261
}
240-
} else {
241-
if (doDeleteFile(currentFile, options)) {
242-
let unlinked;
243-
244-
if (!testRun) {
245-
try {
246-
fs.unlinkSync(currentFile);
247-
unlinked = true;
248-
} catch (exc) {
249-
// ignore
250-
}
251-
} else {
262+
} else if (doDeleteFile(currentFile, options)) {
263+
let unlinked;
264+
265+
if (!testRun) {
266+
try {
267+
fs.unlinkSync(currentFile);
252268
unlinked = true;
269+
} catch (exc) {
270+
// ignore
253271
}
272+
} else {
273+
unlinked = true;
274+
}
254275

255-
if (unlinked) {
256-
removed[currentFile] = true;
276+
if (unlinked) {
277+
removed[currentFile] = true;
257278

258-
if (options.totalRemoved !== undefined) {
259-
options.totalRemoved++;
260-
}
279+
if (options.totalRemoved !== undefined) {
280+
options.totalRemoved++;
261281
}
262282
}
263283
}
264284
});
265285
}
286+
}
266287

267-
if (deleteDirectory) {
268-
if (!testRun) {
269-
rimrafSync(currentDir);
270-
}
288+
if (deleteDirectory) {
289+
if (!testRun) {
290+
rimrafSync(currentDir);
291+
}
271292

272-
if (options.totalRemoved === undefined) {
273-
// for limit of files - we do not want to count the directories
274-
removed[currentDir] = true;
275-
}
293+
if (options.totalRemoved === undefined) {
294+
// for limit of files - we do not want to count the directories
295+
removed[currentDir] = true;
276296
}
277297
}
278298

0 commit comments

Comments
 (0)