Peter Steinbergerfix: add trash helper27dd72a10 months agoHistory
97 lines · 2.5 KB · TypeScript
RawDownload
import fs from 'node:fs';import os from 'node:os';import path from 'node:path'; export type MovePathsToTrashOptions = {  allowMissing?: boolean;}; export type MovePathsToTrashResult = {  moved: string[];  missing: string[];  errors: string[];}; const getTrashDir = (): string => {  const home = os.homedir();  if (process.platform === 'darwin') {    return path.join(home, '.Trash');  }  return path.join(home, '.local', 'share', 'Trash', 'files');}; const ensureDirSync = (dirPath: string): void => {  fs.mkdirSync(dirPath, { recursive: true });}; const uniqueDestPathSync = (trashDir: string, originalName: string): string => {  const base = path.basename(originalName);  const ext = path.extname(base);  const stem = ext ? base.slice(0, -ext.length) : base;   let candidate = path.join(trashDir, base);  if (!fs.existsSync(candidate)) {    return candidate;  }   const nonce = Date.now();  for (let attempt = 1; attempt < 10_000; attempt += 1) {    candidate = path.join(trashDir, `${stem}-${nonce}-${attempt}${ext}`);    if (!fs.existsSync(candidate)) {      return candidate;    }  }   throw new Error(`Unable to find free Trash destination for ${base}`);}; const moveSync = (sourcePath: string, destinationPath: string): void => {  try {    fs.renameSync(sourcePath, destinationPath);  } catch {    const stats = fs.lstatSync(sourcePath);    fs.cpSync(sourcePath, destinationPath, { recursive: stats.isDirectory(), errorOnExist: true });    fs.rmSync(sourcePath, { recursive: stats.isDirectory(), force: true });  }}; export function movePathsToTrash(  targets: string[],  cwd: string,  options: MovePathsToTrashOptions = {}): MovePathsToTrashResult {  const result: MovePathsToTrashResult = {    moved: [],    missing: [],    errors: [],  };   const trashDir = getTrashDir();  ensureDirSync(trashDir);   for (const target of targets) {    const trimmed = target.trim();    if (!trimmed) {      continue;    }     const absolutePath = path.isAbsolute(trimmed) ? trimmed : path.resolve(cwd, trimmed);    if (!fs.existsSync(absolutePath)) {      if (!options.allowMissing) {        result.missing.push(trimmed);      }      continue;    }     try {      const destinationPath = uniqueDestPathSync(trashDir, absolutePath);      moveSync(absolutePath, destinationPath);      result.moved.push(trimmed);    } catch (error) {      const message = error instanceof Error ? error.message : String(error);      result.errors.push(`rm: ${trimmed}: ${message}`);    }  }   return result;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t