Adding uninstall command (#953)

* Adding uninstall command

* Updates docs and changelog related to the uninstall command
This commit is contained in:
Mihovil Ilakovac 2023-02-01 11:18:24 +01:00 committed by GitHub
parent 0002414fa1
commit 1017e20bf4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 178 additions and 36 deletions

View File

@ -50,6 +50,13 @@ const getTasks: GetTasks<Task[]> = (args, context) => {
}
```
### Uninstall command
If you want to uninstall Wasp from your system, you can now do so with:
```bash
wasp uninstall
```
It will remove all of the Wasp binaries and data from your system.
## v0.8.0
### BREAKING CHANGES

View File

@ -21,6 +21,7 @@ import Wasp.Cli.Command.Dockerfile (printDockerfile)
import Wasp.Cli.Command.Info (info)
import Wasp.Cli.Command.Start (start)
import qualified Wasp.Cli.Command.Telemetry as Telemetry
import Wasp.Cli.Command.Uninstall (uninstall)
import Wasp.Cli.Command.WaspLS (runWaspLS)
import Wasp.Cli.Terminal (title)
import Wasp.Util (indent)
@ -36,6 +37,7 @@ main = withUtf8 . (`E.catch` handleInternalErrors) $ do
["clean"] -> Command.Call.Clean
["compile"] -> Command.Call.Compile
("db" : dbArgs) -> Command.Call.Db dbArgs
["uninstall"] -> Command.Call.Uninstall
["version"] -> Command.Call.Version
["build"] -> Command.Call.Build
["telemetry"] -> Command.Call.Telemetry
@ -57,6 +59,7 @@ main = withUtf8 . (`E.catch` handleInternalErrors) $ do
Command.Call.Compile -> runCommand compile
Command.Call.Db dbArgs -> dbCli dbArgs
Command.Call.Version -> printVersion
Command.Call.Uninstall -> runCommand uninstall
Command.Call.Build -> runCommand build
Command.Call.Telemetry -> runCommand Telemetry.telemetry
Command.Call.Deps -> runCommand deps
@ -92,6 +95,7 @@ printUsage =
cmd " version Prints current version of CLI.",
cmd " waspls Run Wasp Language Server. Add --help to get more info.",
cmd " completion Prints help on bash completion.",
cmd " uninstall Removes Wasp from your system.",
title " IN PROJECT",
cmd " start Runs Wasp app in development mode, watching for file changes.",
cmd " db <db-cmd> [args] Executes a database command. Run 'wasp db' for more info.",

View File

@ -26,7 +26,7 @@ bashCompletion = do
["db", cmdPrefix] -> listMatchingCommands cmdPrefix dbSubCommands
_ -> liftIO . putStrLn $ ""
where
commands = ["new", "version", "waspls", "start", "db", "clean", "build", "telemetry", "deps", "info", "completion", "completion:generate"]
commands = ["new", "version", "waspls", "start", "db", "clean", "uninstall", "build", "telemetry", "deps", "info", "completion", "completion:generate"]
dbSubCommands = ["migrate-dev", "studio"]
listMatchingCommands :: String -> [String] -> Command ()
listMatchingCommands cmdPrefix cmdList = listCommands $ filter (cmdPrefix `isPrefixOf`) cmdList

View File

@ -4,6 +4,7 @@ data Call
= New String -- project name
| Start
| Clean
| Uninstall
| Compile
| Db [String] -- db args
| Build

View File

@ -1,28 +1,27 @@
module Wasp.Cli.Command.Telemetry.Common
( TelemetryCacheDir,
ensureTelemetryCacheDirExists,
getTelemetryCacheDirPath,
)
where
import StrongPath (Abs, Dir, Path', reldir)
import StrongPath (Abs, Dir, Path', reldir, (</>))
import qualified StrongPath as SP
import qualified System.Directory as SD
data UserCacheDir
getUserCacheDirPath :: IO (Path' Abs (Dir UserCacheDir))
getUserCacheDirPath = SD.getXdgDirectory SD.XdgCache "" >>= SP.parseAbsDir
import Wasp.Cli.FileSystem
( UserCacheDir,
getUserCacheDir,
getWaspCacheDir,
)
data TelemetryCacheDir
getTelemetryCacheDir :: Path' Abs (Dir UserCacheDir) -> Path' Abs (Dir TelemetryCacheDir)
getTelemetryCacheDir userCacheDirPath = getWaspCacheDir userCacheDirPath </> [reldir|telemetry|]
ensureTelemetryCacheDirExists :: IO (Path' Abs (Dir TelemetryCacheDir))
ensureTelemetryCacheDirExists = do
userCacheDirPath <- getUserCacheDirPath
userCacheDirPath <- getUserCacheDir
SD.createDirectoryIfMissing False $ SP.fromAbsDir userCacheDirPath
let telemetryCacheDirPath = getTelemetryCacheDirPath userCacheDirPath
SD.createDirectoryIfMissing True $ SP.fromAbsDir telemetryCacheDirPath
return telemetryCacheDirPath
getTelemetryCacheDirPath :: Path' Abs (Dir UserCacheDir) -> Path' Abs (Dir TelemetryCacheDir)
getTelemetryCacheDirPath userCacheDirPath = userCacheDirPath SP.</> [reldir|wasp/telemetry|]
let telemetryCacheDir = getTelemetryCacheDir userCacheDirPath
SD.createDirectoryIfMissing True $ SP.fromAbsDir telemetryCacheDir
return telemetryCacheDir

View File

@ -0,0 +1,54 @@
module Wasp.Cli.Command.Uninstall
( uninstall,
)
where
import Control.Monad (when)
import Control.Monad.IO.Class (liftIO)
import StrongPath (fromAbsDir, fromAbsFile, (</>))
import System.Exit (die)
import Wasp.Cli.Command (Command)
import Wasp.Cli.Command.Message (cliSendMessageC)
import Wasp.Cli.FileSystem
( getHomeDir,
getUserCacheDir,
getWaspCacheDir,
waspExecutableInHomeDir,
waspInstallationDirInHomeDir,
)
import qualified Wasp.Message as Msg
import Wasp.Util.IO (deleteDirectoryIfExists, deleteFileIfExists)
-- | Removes Wasp from the system.
uninstall :: Command ()
uninstall = do
cliSendMessageC $ Msg.Start "Uninstalling Wasp ..."
liftIO removeWaspFiles
cliSendMessageC $ Msg.Success "Uninstalled Wasp"
removeWaspFiles :: IO ()
removeWaspFiles = do
homeDir <- getHomeDir
userCacheDir <- getUserCacheDir
let waspInstallationDir = homeDir </> waspInstallationDirInHomeDir
waspExecutableFile = homeDir </> waspExecutableInHomeDir
waspCacheDir = getWaspCacheDir userCacheDir
putStr $
unlines
[ "We will remove the following directories:",
" " ++ fromAbsDir waspInstallationDir,
" " ++ fromAbsDir waspCacheDir,
"",
"We will also remove the following files:",
" " ++ fromAbsFile waspExecutableFile,
"",
"Are you sure you want to continue? [y/N]"
]
answer <- getLine
when (answer /= "y") $ die "Aborted."
deleteDirectoryIfExists waspInstallationDir
deleteFileIfExists waspExecutableFile
deleteDirectoryIfExists waspCacheDir

View File

@ -0,0 +1,40 @@
module Wasp.Cli.FileSystem
( getUserCacheDir,
getWaspCacheDir,
getHomeDir,
waspInstallationDirInHomeDir,
waspExecutableInHomeDir,
UserCacheDir,
WaspCacheDir,
)
where
import Data.Maybe (fromJust)
import StrongPath (Abs, Dir, Dir', File', Path', Rel, reldir, relfile, (</>))
import qualified StrongPath as SP
import System.Directory
import qualified System.Directory as SD
data UserHomeDir
data UserCacheDir
data WaspCacheDir
getHomeDir :: IO (Path' Abs (Dir UserHomeDir))
getHomeDir = fromJust . SP.parseAbsDir <$> getHomeDirectory
getWaspCacheDir :: Path' Abs (Dir UserCacheDir) -> Path' Abs (Dir WaspCacheDir)
getWaspCacheDir userCacheDirPath = userCacheDirPath </> [reldir|wasp|]
getUserCacheDir :: IO (Path' Abs (Dir UserCacheDir))
getUserCacheDir = SD.getXdgDirectory SD.XdgCache "" >>= SP.parseAbsDir
-- NOTE: these paths are based on the installer script and if you change them there
-- you need to change them here as well (and vice versa).
-- Task to improve this: https://github.com/wasp-lang/wasp/issues/980
waspInstallationDirInHomeDir :: Path' (Rel UserHomeDir) Dir'
waspInstallationDirInHomeDir = [reldir|.local/share/wasp-lang|]
waspExecutableInHomeDir :: Path' (Rel UserHomeDir) File'
waspExecutableInHomeDir = [relfile|.local/bin/wasp|]

View File

@ -3,12 +3,15 @@
module Wasp.Util.IO
( listDirectoryDeep,
listDirectory,
deleteDirectoryIfExists,
deleteFileIfExists,
)
where
import Control.Monad (filterM)
import Control.Monad (filterM, when)
import StrongPath (Abs, Dir, Dir', File, Path', Rel, basename, parseRelDir, parseRelFile, toFilePath, (</>))
import qualified System.Directory
import qualified StrongPath as SP
import qualified System.Directory as SD
import qualified System.FilePath as FilePath
import System.IO.Error (isDoesNotExistError)
import UnliftIO.Exception (catch, throwIO)
@ -42,7 +45,7 @@ listDirectoryDeep absDirPath = do
-- | Lists files and directories at top lvl of the directory.
listDirectory :: forall d f. Path' Abs (Dir d) -> IO ([Path' (Rel d) (File f)], [Path' (Rel d) Dir'])
listDirectory absDirPath = do
fpRelItemPaths <- System.Directory.listDirectory fpAbsDirPath
fpRelItemPaths <- SD.listDirectory fpAbsDirPath
relFilePaths <- filterFiles fpAbsDirPath fpRelItemPaths
relDirPaths <- filterDirs fpAbsDirPath fpRelItemPaths
return (relFilePaths, relDirPaths)
@ -52,10 +55,22 @@ listDirectory absDirPath = do
filterFiles :: FilePath -> [FilePath] -> IO [Path' (Rel d) (File f)]
filterFiles absDir relItems =
filterM (System.Directory.doesFileExist . (absDir FilePath.</>)) relItems
filterM (SD.doesFileExist . (absDir FilePath.</>)) relItems
>>= mapM parseRelFile
filterDirs :: FilePath -> [FilePath] -> IO [Path' (Rel d) Dir']
filterDirs absDir relItems =
filterM (System.Directory.doesDirectoryExist . (absDir FilePath.</>)) relItems
filterM (SD.doesDirectoryExist . (absDir FilePath.</>)) relItems
>>= mapM parseRelDir
deleteDirectoryIfExists :: Path' r (Dir d) -> IO ()
deleteDirectoryIfExists dirPath = do
let dirPathStr = SP.toFilePath dirPath
exists <- SD.doesDirectoryExist dirPathStr
when exists $ SD.removeDirectoryRecursive dirPathStr
deleteFileIfExists :: Path' r (File f) -> IO ()
deleteFileIfExists filePath = do
let filePathStr = SP.toFilePath filePath
exists <- SD.doesFileExist filePathStr
when exists $ SD.removeFile filePathStr

View File

@ -332,10 +332,12 @@ library cli-lib
other-modules: Paths_waspc
exposed-modules:
Wasp.Cli.Command
Wasp.Cli.FileSystem
Wasp.Cli.Command.BashCompletion
Wasp.Cli.Command.Build
Wasp.Cli.Command.Call
Wasp.Cli.Command.Clean
Wasp.Cli.Command.Uninstall
Wasp.Cli.Command.Common
Wasp.Cli.Command.Compile
Wasp.Cli.Command.CreateNewProject

View File

@ -18,6 +18,7 @@ COMMANDS
version Prints current version of CLI.
waspls Run Wasp Language Server. Add --help to get more info.
completion Prints help on bash completion.
uninstall Removes Wasp from your system.
IN PROJECT
start Runs Wasp app in development mode, watching for file changes.
db <db-cmd> [args] Executes a database command. Run 'wasp db' for more info.
@ -52,6 +53,25 @@ Newsletter: https://wasp-lang.dev/#signup
0.2.0.1
```
- `wasp uninstall` removes Wasp from your system.
```
$ wasp uninstall
🐝 --- Uninstalling Wasp ... ------------------------------------------------------
We will remove the following directories:
{home}/.local/share/wasp-lang/
{home}/.cache/wasp/
We will also remove the following files:
{home}/.local/bin/wasp
Are you sure you want to continue? [y/N]
y
✅ --- Uninstalled Wasp -----------------------------------------------------------
```
### Bash Completion