|
| 1 | +(ns orchard.os |
| 2 | + "Operating system specific utilities. |
| 3 | + This is a port of BaseDirectories.java in soc/directories-jvm. |
| 4 | + https://github.com/soc/directories-jvm" |
| 5 | + {:author "Masashi Iizuka" |
| 6 | + :added "0.5.0"} |
| 7 | + (:require [clojure.java.io :as io] |
| 8 | + [clojure.string :as str]) |
| 9 | + (:import (java.io BufferedReader))) |
| 10 | + |
| 11 | +(def os-name |
| 12 | + (str/lower-case (System/getProperty "os.name"))) |
| 13 | + |
| 14 | +(def os-type |
| 15 | + (condp #(str/includes? %2 %1) os-name |
| 16 | + "linux" ::linux |
| 17 | + "mac" ::mac |
| 18 | + "windows" ::windows |
| 19 | + "bsd" ::bsd |
| 20 | + ::not-supported)) |
| 21 | + |
| 22 | +(def file-separator (System/getProperty "file.separator")) |
| 23 | + |
| 24 | +(defn- run-commands |
| 25 | + [expected-result-lines commands] |
| 26 | + (let [commands ^"[Ljava.lang.String;" (into-array String commands) |
| 27 | + builder (ProcessBuilder. commands) |
| 28 | + process (.start builder)] |
| 29 | + (with-open [reader ^BufferedReader (io/reader (.getInputStream process))] |
| 30 | + (try |
| 31 | + (doall (repeatedly expected-result-lines #(.readLine reader))) |
| 32 | + (finally |
| 33 | + (.destroy process)))))) |
| 34 | + |
| 35 | +(defn- get-win-dirs |
| 36 | + [guids] |
| 37 | + (let [commands (concat ["& {" |
| 38 | + "[Console]::OutputEncoding = [System.Text.Encoding]::UTF8" |
| 39 | + "Add-Type @\\\"" |
| 40 | + "using System;" |
| 41 | + "using System.Runtime.InteropServices;" |
| 42 | + "public class Dir {" |
| 43 | + " [DllImport(\\\"shell32.dll\\\")]" |
| 44 | + " private static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);" |
| 45 | + " public static string GetKnownFolderPath(string rfid) {" |
| 46 | + " IntPtr pszPath;" |
| 47 | + " if (SHGetKnownFolderPath(new Guid(rfid), 0, IntPtr.Zero, out pszPath) != 0) return \\\"\\\";" |
| 48 | + " string path = Marshal.PtrToStringUni(pszPath);" |
| 49 | + " Marshal.FreeCoTaskMem(pszPath);" |
| 50 | + " return path;" |
| 51 | + " }" |
| 52 | + "}" |
| 53 | + "\\\"@"] |
| 54 | + (map #(str "[Dir]::GetKnownFolderPath(\\\"" % "\\\")") guids) |
| 55 | + ["}"])] |
| 56 | + (run-commands (count guids) ["powershell.exe" "-Command" (str/join "\n" commands)]))) |
| 57 | + |
| 58 | +(defn cache-dir |
| 59 | + "Returns the path to the user's cache directory. |
| 60 | +
|
| 61 | + macOS : $HOME/Library/Caches |
| 62 | + Windows: FOLDERID_LocalAppData\\cache |
| 63 | + Others : $XDG_CACHE_HOME or $HOME/.cache" |
| 64 | + {:added "0.5.0"} |
| 65 | + [] |
| 66 | + (case os-type |
| 67 | + ::mac |
| 68 | + (str/join file-separator [(System/getProperty "user.home") |
| 69 | + "Library" |
| 70 | + "Caches"]) |
| 71 | + |
| 72 | + ::windows |
| 73 | + (-> ["F1B32785-6FBA-4FCF-9D55-7B8E7F157091"] |
| 74 | + get-win-dirs |
| 75 | + first) |
| 76 | + |
| 77 | + (let [cache-home (System/getenv "XDG_CACHE_HOME")] |
| 78 | + (if (str/blank? cache-home) |
| 79 | + (str (System/getProperty "user.home") file-separator ".cache") |
| 80 | + cache-home)))) |
0 commit comments