Files
penpot/exporter/src/app/util/shell.cljs
2022-06-29 14:53:57 +02:00

94 lines
2.5 KiB
Clojure

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.util.shell
"Shell & FS utilities."
(:require
["child_process" :as proc]
["fs" :as fs]
["os" :as os]
["path" :as path]
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.uuid :as uuid]
[cuerdas.core :as str]
[promesa.core :as p]))
(l/set-level! :trace)
(def tempfile-minage (* 1000 60 60 1)) ;; 1h
(def tmpdir
(let [path (path/join (os/tmpdir) "penpot")]
(when-not (fs/existsSync path)
(fs/mkdirSync path #js {:recursive true}))
path))
(defn- schedule-deletion!
[path]
(letfn [(remote-tempfile []
(when (fs/existsSync path)
(l/trace :hint "permanently remove tempfile" :path path)
(fs/rmSync path #js {:recursive true})))]
(l/trace :hint "schedule tempfile deletion"
:path path
:scheduled-at (.. (js/Date. (+ (js/Date.now) tempfile-minage)) toString))
(js/setTimeout remote-tempfile tempfile-minage)))
(defn tempfile
[& {:keys [prefix suffix]
:or {prefix "penpot."
suffix ".tmp"}}]
(loop [i 0]
(if (< i 1000)
(let [path (path/join tmpdir (str/concat prefix (uuid/next) "-" i suffix))]
(if (fs/existsSync path)
(recur (inc i))
(do
(schedule-deletion! path)
path)))
(ex/raise :type :internal
:code :unable-to-locate-temporal-file
:hint "unable to find a tempfile candidate"))))
(defn move!
[origin-path dest-path]
(.rename fs/promises origin-path dest-path))
(defn stat
[path]
(-> (.stat fs/promises path)
(p/then (fn [data]
{:created-at (inst-ms (.-ctime ^js data))
:size (.-size data)}))
(p/catch (constantly nil))))
(defn rmdir!
[path]
(.rm fs/promises path #js {:recursive true}))
(defn write-file!
[fpath content]
(.writeFile fs/promises fpath content))
(defn read-file
[fpath]
(.readFile fs/promises fpath))
(defn run-cmd!
[cmd]
(p/create
(fn [resolve reject]
(l/trace :fn :run-cmd :cmd cmd)
(proc/exec cmd #js {:encoding "buffer"}
(fn [error stdout _stderr]
;; (l/trace :fn :run-cmd :stdout stdout)
(if error
(reject error)
(resolve stdout)))))))