« get me outta code hell

mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
path: root/tempdir.js
diff options
context:
space:
mode:
Diffstat (limited to 'tempdir.js')
-rw-r--r--tempdir.js86
1 files changed, 86 insertions, 0 deletions
diff --git a/tempdir.js b/tempdir.js
new file mode 100644
index 0000000..9264ffd
--- /dev/null
+++ b/tempdir.js
@@ -0,0 +1,86 @@
+import {mkdirSync, readdirSync, statSync} from 'node:fs'
+import * as os from 'node:os'
+import * as path from 'node:path'
+
+import {nanoid} from 'nanoid'
+import {rimrafSync} from 'rimraf'
+
+// Invariably obliterate contents of the rootDirectory upon
+// mtui startup if their mtime is older than this duration
+// before the current date.
+const ancient = 7 * 24 * 60 * 60 * 1000
+
+const ourTemporaryDirectories = []
+
+const rootDirectory = path.join(os.homedir(), '.mtui', 'tmp')
+
+function obliterateTemporaryDirectory(tempdir) {
+  const rel = path.relative(rootDirectory, tempdir)
+  if (rel.startsWith('/') || rel.startsWith('.')) {
+    console.trace()
+    console.error(`Ostensible tempdir located here:`)
+    console.error(tempdir)
+    console.error(`Doesn't appear to be located in tempdir root:`)
+    console.error(rootDirectory)
+    console.error(`This is a programming error, and possibly dangerous.`)
+    console.error(`So, exiting now. This should be investigated.`)
+    process.exit(1)
+  }
+
+  rimrafSync(tempdir)
+}
+
+function cleanupAncient() {
+  const fsOp = (fn, ...args) => {
+    try {
+      return fn(...args)
+    } catch (error) {
+      console.error(error)
+      console.error(`There was an error preparing the temporary file directory.`)
+      console.error(`You may be able to resolve this by deleting or moving away`)
+      console.error(`this path:`)
+      console.error(rootDirectory)
+      process.exit(1)
+    }
+  }
+
+  fsOp(() =>
+    mkdirSync(rootDirectory, {recursive: true}))
+
+  const tempdirs =
+    (fsOp(readdirSync, rootDirectory)
+      .map(dir => path.join(rootDirectory, dir)))
+
+  let first = true
+  for (const tempdir of tempdirs) {
+    const stats = fsOp(statSync, tempdir)
+
+    if (Date.now() - stats.mtimeMs > ancient) {
+      if (first) {
+        console.log(`One or more tempdirs haven't been modified in a while, removing:`)
+        first = false
+      }
+      console.log(tempdir)
+      fsOp(obliterateTemporaryDirectory, tempdir)
+    }
+  }
+}
+
+// This has to be a sync function, since it'll run on
+// the process' 'exit' event.
+function cleanupOurs() {
+  for (const tempdir of ourTemporaryDirectories) {
+    obliterateTemporaryDirectory(tempdir)
+  }
+}
+
+cleanupAncient()
+process.on('exit', cleanupOurs)
+
+export default function temporaryDirectory() {
+  const name = nanoid()
+  const dir = path.join(rootDirectory, name)
+  ourTemporaryDirectories.push(dir)
+  mkdirSync(dir)
+  return dir
+}