From 877b55e21d5f9736038e6701903e322634f56ee8 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 18 Jun 2021 15:01:32 +0530 Subject: [PATCH 01/39] Adds basic "nuke" command structure so that it reflects in ghcup cli --- app/ghcup/Main.hs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 2da1b12..e7258b1 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -103,6 +103,7 @@ data Command | Upgrade UpgradeOpts Bool | ToolRequirements | ChangeLog ChangeLogOptions + | Nuke #if defined(BRICK) | Interactive #endif @@ -219,7 +220,7 @@ invertableSwitch' -> Mod FlagFields Bool -- ^ option modifier for --no-foo -> Parser (Maybe Bool) invertableSwitch' longopt shortopt defv enmod dismod = optional - ( flag' True (enmod <> long longopt <> if defv then mempty else short shortopt) + ( flag' True ( enmod <> long longopt <> if defv then mempty else short shortopt) <|> flag' False (dismod <> long nolongopt <> if defv then short shortopt else mempty) ) where @@ -368,6 +369,14 @@ com = ) <> internal ) + <|> subparser + (command + "nuke" + (info (pure Nuke <**> helper) + (progDesc "Completely remove ghcup from your system")) + <> commandGroup "Nuclear Commands:" + ) + where installToolFooter :: String installToolFooter = [s|Discussion: @@ -393,7 +402,6 @@ com = By default returns the URI of the ChangeLog of the latest GHC release. Pass '-o' to automatically open via xdg-open.|] - installCabalFooter :: String installCabalFooter = [s|Discussion: Installs the specified cabal-install version (or a recommended default one) @@ -1654,6 +1662,10 @@ Make sure to clean up #{tmpdir} afterwards.|]) VLeft e -> do runLogger $ $(logError) $ T.pack $ prettyShow e pure $ ExitFailure 12 + Nuke -> do + putStrLn "Nuking in 3...2....1" + putStrLn "BOOM!" + pure ExitSuccess ChangeLog ChangeLogOptions{..} -> do let tool = fromMaybe GHC clTool @@ -1696,6 +1708,8 @@ Make sure to clean up #{tmpdir} afterwards.|]) case res of ExitSuccess -> pure () ef@(ExitFailure _) -> exitWith ef + + pure () fromVersion :: (MonadLogger m, MonadFail m, MonadReader AppState m, MonadThrow m, MonadIO m, MonadCatch m) From 0f6381e67bc9e77f242c4ddb6d599e155defd8e4 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 18 Jun 2021 15:09:01 +0530 Subject: [PATCH 02/39] Move Nuke Command a little down in the file --- app/ghcup/Main.hs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index e7258b1..8b8e008 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1662,10 +1662,6 @@ Make sure to clean up #{tmpdir} afterwards.|]) VLeft e -> do runLogger $ $(logError) $ T.pack $ prettyShow e pure $ ExitFailure 12 - Nuke -> do - putStrLn "Nuking in 3...2....1" - putStrLn "BOOM!" - pure ExitSuccess ChangeLog ChangeLogOptions{..} -> do let tool = fromMaybe GHC clTool @@ -1705,6 +1701,11 @@ Make sure to clean up #{tmpdir} afterwards.|]) >> pure (ExitFailure 13) else putStrLn uri' >> pure ExitSuccess + Nuke -> do + putStrLn "Nuking in 3...2....1" + putStrLn "BOOM!" + pure ExitSuccess + case res of ExitSuccess -> pure () ef@(ExitFailure _) -> exitWith ef From ec29332657ae00aadaeb51ad982e490a830c161e Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 14:29:26 +0530 Subject: [PATCH 03/39] Adds basic implementation of rmTool function --- app/ghcup/Main.hs | 5 ++++- lib/GHCup.hs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 8b8e008..163962b 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1702,7 +1702,10 @@ Make sure to clean up #{tmpdir} afterwards.|]) else putStrLn uri' >> pure ExitSuccess Nuke -> do - putStrLn "Nuking in 3...2....1" + putStrLn "Initiating Nuclear Sequence... " + lInstalled <- runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) + forM_ lInstalled $ runLogger . flip runReaderT appstate . rmTool + putStrLn "Nuking in 3...2...1" putStrLn "BOOM!" pure ExitSuccess diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 372a422..2a03f9c 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1282,6 +1282,40 @@ rmStackVer ver = do Nothing -> liftIO $ rmLink (binDir "stack" <> exeExt) +rmTool :: ( MonadReader AppState m + , MonadLogger m + , MonadFail m + , MonadMask m + , MonadUnliftIO m) + => ListResult + -> m () + +rmTool tool = do + let ListResult {lVer, lTool, lCross} = tool + -- appstate <- ask + + case lTool of + GHC -> do + let ghcTargetVersion = GHCTargetVersion lCross lVer + _ <- runE @'[NotInstalled] $ rmGHCVer ghcTargetVersion + pure () + + HLS -> do + _ <- runE @'[NotInstalled] $ rmHLSVer lVer + pure () + + Cabal -> do + _ <- runE @'[NotInstalled] $ rmCabalVer lVer + pure () + + Stack -> do + _ <- runE @'[NotInstalled] $ rmStackVer lVer + pure () + + GHCup -> do + -- leaving this unimplemented for now. + pure () + ------------------ --[ Debug info ]-- From 0b959c56fb23583c8c588e5b174127ffc7808707 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 18:44:30 +0530 Subject: [PATCH 04/39] change rmTool type to ` Excepts '[NotInstalled ] m () ` --- lib/GHCup.hs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 2a03f9c..1a88d0a 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1288,7 +1288,7 @@ rmTool :: ( MonadReader AppState m , MonadMask m , MonadUnliftIO m) => ListResult - -> m () + -> Excepts '[NotInstalled ] m () rmTool tool = do let ListResult {lVer, lTool, lCross} = tool @@ -1297,20 +1297,16 @@ rmTool tool = do case lTool of GHC -> do let ghcTargetVersion = GHCTargetVersion lCross lVer - _ <- runE @'[NotInstalled] $ rmGHCVer ghcTargetVersion - pure () + rmGHCVer ghcTargetVersion HLS -> do - _ <- runE @'[NotInstalled] $ rmHLSVer lVer - pure () + rmHLSVer lVer Cabal -> do - _ <- runE @'[NotInstalled] $ rmCabalVer lVer - pure () + rmCabalVer lVer Stack -> do - _ <- runE @'[NotInstalled] $ rmStackVer lVer - pure () + rmStackVer lVer GHCup -> do -- leaving this unimplemented for now. From d09adf9159134ecbb61f114bd69a798222c460ac Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 18:51:03 +0530 Subject: [PATCH 05/39] Updates Main.hs to work with new rmTool. --- app/ghcup/Main.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 163962b..fe83377 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1702,11 +1702,8 @@ Make sure to clean up #{tmpdir} afterwards.|]) else putStrLn uri' >> pure ExitSuccess Nuke -> do - putStrLn "Initiating Nuclear Sequence... " lInstalled <- runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) - forM_ lInstalled $ runLogger . flip runReaderT appstate . rmTool - putStrLn "Nuking in 3...2...1" - putStrLn "BOOM!" + forM_ lInstalled $ runRm . rmTool pure ExitSuccess case res of From 0cb22945fe596bdafff5b9a0fb6b9028aaa16f88 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 18:52:24 +0530 Subject: [PATCH 06/39] Adds some logger messages. --- app/ghcup/Main.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index fe83377..fd0efbf 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1702,8 +1702,12 @@ Make sure to clean up #{tmpdir} afterwards.|]) else putStrLn uri' >> pure ExitSuccess Nuke -> do + runLogger $ $logInfo "Initiating Nuclear Sequence 🚀🚀🚀" + runLogger $ $logInfo "Nuking in 3...2...1" + lInstalled <- runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) forM_ lInstalled $ runRm . rmTool + pure ExitSuccess case res of From 82a704ab442df6b1d70ac4be272c8d8ba6c24c6d Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 18:53:18 +0530 Subject: [PATCH 07/39] Adds 10s Thread-Delay and relevant Logger messages to Main.hs --- app/ghcup/Main.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index fd0efbf..4275e46 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1702,6 +1702,11 @@ Make sure to clean up #{tmpdir} afterwards.|]) else putStrLn uri' >> pure ExitSuccess Nuke -> do + runLogger $ $logWarn "WARNING: This will remove GHCup and all installed components from your system." + runLogger $ $logWarn "Wating 10 seconds before commencing, if you want to cancel it, now would be the time." + + threadDelay 10000000 -- wait 10s + runLogger $ $logInfo "Initiating Nuclear Sequence 🚀🚀🚀" runLogger $ $logInfo "Nuking in 3...2...1" From 4ef36226165fd7a44bd88952140b168b61120237 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 20:09:26 +0530 Subject: [PATCH 08/39] Adds argument de-structuring to 'rmTool' function & remove the one in its body --- lib/GHCup.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 1a88d0a..16b2063 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1290,8 +1290,7 @@ rmTool :: ( MonadReader AppState m => ListResult -> Excepts '[NotInstalled ] m () -rmTool tool = do - let ListResult {lVer, lTool, lCross} = tool +rmTool ListResult {lVer, lTool, lCross} = do -- appstate <- ask case lTool of From 8a1dbe9dbbd33b28882ce56588ec623ae247a233 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 23:14:25 +0530 Subject: [PATCH 09/39] basic implementation of rmGhcupDirs function that removes relevant dirs in NUKE command --- lib/GHCup.hs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 16b2063..857267b 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1311,6 +1311,66 @@ rmTool ListResult {lVer, lTool, lCross} = do -- leaving this unimplemented for now. pure () +rmGhcupDirs :: ( MonadReader AppState m + , MonadIO m + , MonadLogger m) + => m () +rmGhcupDirs = do + dirs@Dirs + { baseDir + , binDir + , logsDir + , cacheDir + , confDir } <- asks dirs + + let envDir = baseDir "env" + + -- remove env Dir + rmEnvDir envDir + + -- remove entire cache Dir + rmCacheDir cacheDir + + -- remove entire logs Dir + rmLogsDir logsDir + + -- remove the $ghcupConfigDir/config.yaml file + rmConfFile confDir + + liftIO $ print dirs + + where + + rmEnvDir envDir = do + isEnvDirPresent <- liftIO $ doesDirectoryExist envDir + + if isEnvDirPresent + then do + $logInfo "Removing Ghcup Environment Dir" + liftIO $ removeDirectory envDir + else + $logInfo "EnvDir Not Found, Skipping" + + rmCacheDir cacheDir = do + $logInfo "removing ghcup cache Dir" + liftIO $ removeDirectory cacheDir + + + rmLogsDir logsDir = do + $logInfo "removing ghcup logs Dir" + liftIO $ removeDirectory logsDir + + rmConfFile confDir = do + let confPath = confDir "config.yaml" + + exists <- liftIO $ doesFileExist confPath + + if exists + then do + $logInfo "removing config.yaml" + liftIO $ removeFile confPath + else + $logInfo "no config file found, skipping." ------------------ --[ Debug info ]-- From 07fb04bb74d8dae711dafae67128ffbd50e636cb Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 22 Jun 2021 23:15:13 +0530 Subject: [PATCH 10/39] Adds the new rmGhcupDirs function in Main.hs under Nuke command --- app/ghcup/Main.hs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 4275e46..12b866b 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1713,6 +1713,8 @@ Make sure to clean up #{tmpdir} afterwards.|]) lInstalled <- runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) forM_ lInstalled $ runRm . rmTool + runLogger $ runReaderT rmGhcupDirs appstate + pure ExitSuccess case res of From 2e3dceecf868a66cb66d2ce1604f9ee785254625 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 23 Jun 2021 10:08:06 +0530 Subject: [PATCH 11/39] abstracts out getting ghcup conf file path --- lib/GHCup/Utils/Dirs.hs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/GHCup/Utils/Dirs.hs b/lib/GHCup/Utils/Dirs.hs index ba90660..0057f1e 100644 --- a/lib/GHCup/Utils/Dirs.hs +++ b/lib/GHCup/Utils/Dirs.hs @@ -26,6 +26,7 @@ module GHCup.Utils.Dirs , parseGHCupGHCDir , relativeSymlink , withGHCupTmpDir + , getConfigFilePath ) where @@ -201,13 +202,16 @@ getDirs = do --[ GHCup files ]-- ------------------- +getConfigFilePath :: (MonadIO m) => m FilePath +getConfigFilePath = do + confDir <- liftIO ghcupConfigDir + pure $ confDir "config.yaml" ghcupConfigFile :: (MonadIO m) => Excepts '[JSONError] m UserSettings ghcupConfigFile = do - confDir <- liftIO ghcupConfigDir - let file = confDir "config.yaml" - contents <- liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ Just <$> BS.readFile file + filepath <- getConfigFilePath + contents <- liftIO $ handleIO' NoSuchThing (\_ -> pure Nothing) $ Just <$> BS.readFile filepath case contents of Nothing -> pure defaultUserSettings Just contents' -> lE' JSONDecodeError . first show . Y.decodeEither' $ contents' From 118a2744fe0efab6e415600f5a37d47476ff6a6c Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 23 Jun 2021 10:10:28 +0530 Subject: [PATCH 12/39] adds new getGhcupConfFilePath fn to GHCup.hs, also refactors to use for error handling in missing file cases --- lib/GHCup.hs | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 857267b..13d722f 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1313,7 +1313,8 @@ rmTool ListResult {lVer, lTool, lCross} = do rmGhcupDirs :: ( MonadReader AppState m , MonadIO m - , MonadLogger m) + , MonadLogger m + , MonadCatch m ) => m () rmGhcupDirs = do dirs@Dirs @@ -1323,10 +1324,15 @@ rmGhcupDirs = do , cacheDir , confDir } <- asks dirs - let envDir = baseDir "env" + let envFilePath = baseDir "env" - -- remove env Dir - rmEnvDir envDir + confFilePath <- getConfigFilePath + + -- remove env File + rmEnvFile envFilePath + +-- remove the configFile file + rmConfFile confFilePath -- remove entire cache Dir rmCacheDir cacheDir @@ -1334,43 +1340,25 @@ rmGhcupDirs = do -- remove entire logs Dir rmLogsDir logsDir - -- remove the $ghcupConfigDir/config.yaml file - rmConfFile confDir - liftIO $ print dirs where - rmEnvDir envDir = do - isEnvDirPresent <- liftIO $ doesDirectoryExist envDir - - if isEnvDirPresent - then do - $logInfo "Removing Ghcup Environment Dir" - liftIO $ removeDirectory envDir - else - $logInfo "EnvDir Not Found, Skipping" + rmEnvFile enFilePath = do + $logInfo "Removing Ghcup Environment File" + hideError doesNotExistErrorType $ liftIO $ removeFile enFilePath rmCacheDir cacheDir = do $logInfo "removing ghcup cache Dir" liftIO $ removeDirectory cacheDir - rmLogsDir logsDir = do $logInfo "removing ghcup logs Dir" liftIO $ removeDirectory logsDir - rmConfFile confDir = do - let confPath = confDir "config.yaml" - - exists <- liftIO $ doesFileExist confPath - - if exists - then do - $logInfo "removing config.yaml" - liftIO $ removeFile confPath - else - $logInfo "no config file found, skipping." + rmConfFile confFilePath = do + $logInfo "removing Ghcup Config File" + hideError doesNotExistErrorType $ liftIO $ removeFile confFilePath ------------------ --[ Debug info ]-- From 3b3dde8413d5cc609924b24e6608636f5f13e6ee Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 23 Jun 2021 10:36:17 +0530 Subject: [PATCH 13/39] updates deleting dirs in rmGhcupDirs according to feedback on merge request --- lib/GHCup.hs | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 13d722f..08c648e 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1348,18 +1348,39 @@ rmGhcupDirs = do $logInfo "Removing Ghcup Environment File" hideError doesNotExistErrorType $ liftIO $ removeFile enFilePath - rmCacheDir cacheDir = do - $logInfo "removing ghcup cache Dir" - liftIO $ removeDirectory cacheDir - - rmLogsDir logsDir = do - $logInfo "removing ghcup logs Dir" - liftIO $ removeDirectory logsDir - rmConfFile confFilePath = do $logInfo "removing Ghcup Config File" hideError doesNotExistErrorType $ liftIO $ removeFile confFilePath + rmCacheDir cacheDir = do + $logInfo "removing ghcup cache Dir" + contents <- liftIO $ listDirectory cacheDir + forM_ contents removeIfFile + removeDirIfEmpty cacheDir + + rmLogsDir logsDir = do + $logInfo "removing ghcup logs Dir" + contents <- liftIO $ listDirectory logsDir + forM_ contents removeIfFile + removeDirIfEmpty logsDir + + removeIfFile filepath = do + isFile <- checkIfSymlink filepath + isSymlink <- checkIfRegularFile filepath + + if isFile && not isSymlink + then liftIO $ removeFile filepath + else pure () + + checkIfSymlink filepath = + liftIO $ pathIsSymbolicLink filepath + + checkIfRegularFile filepath = + liftIO $ doesFileExist filepath + + removeDirIfEmpty filepath = + liftIO $ removeDirectory filepath + ------------------ --[ Debug info ]-- ------------------ From 33eaa765d79cf4e41a8383e38cc6ad9a06740843 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Wed, 23 Jun 2021 23:23:54 +0530 Subject: [PATCH 14/39] adds better error handling when removing files and dirs in rmGhcupDirs function --- lib/GHCup.hs | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 08c648e..0143b6e 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1355,31 +1355,20 @@ rmGhcupDirs = do rmCacheDir cacheDir = do $logInfo "removing ghcup cache Dir" contents <- liftIO $ listDirectory cacheDir - forM_ contents removeIfFile + forM_ contents deleteFile removeDirIfEmpty cacheDir rmLogsDir logsDir = do $logInfo "removing ghcup logs Dir" contents <- liftIO $ listDirectory logsDir - forM_ contents removeIfFile + forM_ contents deleteFile removeDirIfEmpty logsDir - removeIfFile filepath = do - isFile <- checkIfSymlink filepath - isSymlink <- checkIfRegularFile filepath - - if isFile && not isSymlink - then liftIO $ removeFile filepath - else pure () - - checkIfSymlink filepath = - liftIO $ pathIsSymbolicLink filepath - - checkIfRegularFile filepath = - liftIO $ doesFileExist filepath + deleteFile filepath = do + hideError InappropriateType $ liftIO $ removeFile filepath removeDirIfEmpty filepath = - liftIO $ removeDirectory filepath + hideError UnsatisfiedConstraints $ liftIO $ removeDirectory filepath ------------------ --[ Debug info ]-- From 3fae516ce45610d77bf7deba88cdd935ec2dd3df Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Thu, 24 Jun 2021 10:08:12 +0530 Subject: [PATCH 15/39] Adds using 'rmFile' fn in rmGhcupDirs, it has better windows handling logic --- lib/GHCup.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 0143b6e..12f2c12 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1314,7 +1314,8 @@ rmTool ListResult {lVer, lTool, lCross} = do rmGhcupDirs :: ( MonadReader AppState m , MonadIO m , MonadLogger m - , MonadCatch m ) + , MonadCatch m + , MonadMask m ) => m () rmGhcupDirs = do dirs@Dirs @@ -1365,7 +1366,7 @@ rmGhcupDirs = do removeDirIfEmpty logsDir deleteFile filepath = do - hideError InappropriateType $ liftIO $ removeFile filepath + hideError InappropriateType $ rmFile filepath removeDirIfEmpty filepath = hideError UnsatisfiedConstraints $ liftIO $ removeDirectory filepath From 82a8c61cf691b6639a1be506382ecec77d2ce959 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Thu, 24 Jun 2021 10:54:38 +0530 Subject: [PATCH 16/39] adds bin dir removal code, checking for XDG --- lib/GHCup.hs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 12f2c12..c2be448 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1341,6 +1341,9 @@ rmGhcupDirs = do -- remove entire logs Dir rmLogsDir logsDir + -- remove bin directory conditionally + rmBinDir binDir + liftIO $ print dirs where @@ -1365,6 +1368,16 @@ rmGhcupDirs = do forM_ contents deleteFile removeDirIfEmpty logsDir + rmBinDir binDir = do +#if !defined(IS_WINDOWS) + isXDGStyle <- useXDG + if not isXDGStyle + then removeDirIfEmpty binDir + else pure () +#else + removeDirIfEmpty binDir +#endif + deleteFile filepath = do hideError InappropriateType $ rmFile filepath From 951506540700d7360db4acdaa7166b1c739cb9ba Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Thu, 24 Jun 2021 22:48:38 +0530 Subject: [PATCH 17/39] adds conditional export of useXDG in non-windows OS-es. fix in rmGhcupDirs code that used useXDG --- lib/GHCup.hs | 2 +- lib/GHCup/Utils/Dirs.hs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index c2be448..d6eadbc 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1370,7 +1370,7 @@ rmGhcupDirs = do rmBinDir binDir = do #if !defined(IS_WINDOWS) - isXDGStyle <- useXDG + isXDGStyle <- liftIO $ useXDG if not isXDGStyle then removeDirIfEmpty binDir else pure () diff --git a/lib/GHCup/Utils/Dirs.hs b/lib/GHCup/Utils/Dirs.hs index 0057f1e..ec680e7 100644 --- a/lib/GHCup/Utils/Dirs.hs +++ b/lib/GHCup/Utils/Dirs.hs @@ -27,6 +27,9 @@ module GHCup.Utils.Dirs , relativeSymlink , withGHCupTmpDir , getConfigFilePath +#if !defined(IS_WINDOWS) + , useXDG +#endif ) where From d26ddf7015c5d391e2d794782abe970589f24d05 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 25 Jun 2021 13:54:38 +0530 Subject: [PATCH 18/39] adds rudimentary ghcup bin removal code. TODO: handle windows. --- lib/GHCup.hs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index d6eadbc..d9f3e3a 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1282,6 +1282,17 @@ rmStackVer ver = do Nothing -> liftIO $ rmLink (binDir "stack" <> exeExt) +-- assuming the current scheme of having just 1 ghcup bin, no version info is required. +rmGhcup :: ( MonadReader AppState m + , MonadIO m + ) + => Excepts '[NotInstalled] m () + +rmGhcup = do + AppState {dirs = Dirs {binDir}} <- lift ask + let ghcupFile = "ghcup" <> exeExt + liftIO $ hideError doesNotExistErrorType $ rmFile (binDir ghcupFile) + rmTool :: ( MonadReader AppState m , MonadLogger m , MonadFail m @@ -1308,8 +1319,7 @@ rmTool ListResult {lVer, lTool, lCross} = do rmStackVer lVer GHCup -> do - -- leaving this unimplemented for now. - pure () + rmGhcup rmGhcupDirs :: ( MonadReader AppState m , MonadIO m From 9f5df9db1009fe8d21ff85c94bf3605aa63fba6f Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 25 Jun 2021 15:06:02 +0530 Subject: [PATCH 19/39] Adds conditional windows ghcup bin removal code. Todo: test it, add more exception handling if required. --- lib/GHCup.hs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index d9f3e3a..3aa0138 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1284,14 +1284,24 @@ rmStackVer ver = do -- assuming the current scheme of having just 1 ghcup bin, no version info is required. rmGhcup :: ( MonadReader AppState m - , MonadIO m + , MonadIO m, + MonadCatch m ) => Excepts '[NotInstalled] m () rmGhcup = do AppState {dirs = Dirs {binDir}} <- lift ask - let ghcupFile = "ghcup" <> exeExt - liftIO $ hideError doesNotExistErrorType $ rmFile (binDir ghcupFile) + let ghcupFilename = "ghcup" <> exeExt + let ghcupFilepath = binDir ghcupFilename +#if defined(IS_WINDOWS) + -- since it doesn't seem possible to delete a running exec in windows + -- we move it to temp dir, to be deleted at next reboot + tempDir <- liftIO $ getTemporaryDirectory + tempFilepath = tempDir ghcupFilename + hideError doesNotExistErrorType $ liftIO $ renameFile ghcupFilepath tempFilepath +#else + hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath +#endif rmTool :: ( MonadReader AppState m , MonadLogger m From a40d0cbb5c85cd580cdf5cf2ecc5edc9b5bfbe5e Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 25 Jun 2021 16:09:26 +0530 Subject: [PATCH 20/39] swap out system.Directory.rename for Win32.File.moveFileEx for windows --- lib/GHCup.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 3aa0138..d5d71e9 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1298,9 +1298,10 @@ rmGhcup = do -- we move it to temp dir, to be deleted at next reboot tempDir <- liftIO $ getTemporaryDirectory tempFilepath = tempDir ghcupFilename - hideError doesNotExistErrorType $ liftIO $ renameFile ghcupFilepath tempFilepath + liftIO $ hideError NoSuchThing $ Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 #else - hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath + -- delete it. + hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath #endif rmTool :: ( MonadReader AppState m From 931904f3881ea03cadd3b8baad2f7b500589d225 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Fri, 25 Jun 2021 17:00:39 +0530 Subject: [PATCH 21/39] fix minor typo in conditional windows code --- lib/GHCup.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index d5d71e9..219bf50 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1297,7 +1297,7 @@ rmGhcup = do -- since it doesn't seem possible to delete a running exec in windows -- we move it to temp dir, to be deleted at next reboot tempDir <- liftIO $ getTemporaryDirectory - tempFilepath = tempDir ghcupFilename + let tempFilepath = tempDir ghcupFilename liftIO $ hideError NoSuchThing $ Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 #else -- delete it. From 46fcdd356c8f2d107e739256478f8aa193ee35e3 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 19:32:53 +0530 Subject: [PATCH 22/39] Use rmFile instead of removeFile. --- lib/GHCup.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index d5d71e9..b35c692 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1371,11 +1371,11 @@ rmGhcupDirs = do rmEnvFile enFilePath = do $logInfo "Removing Ghcup Environment File" - hideError doesNotExistErrorType $ liftIO $ removeFile enFilePath + hideError doesNotExistErrorType $ liftIO $ deleteFile enFilePath rmConfFile confFilePath = do $logInfo "removing Ghcup Config File" - hideError doesNotExistErrorType $ liftIO $ removeFile confFilePath + hideError doesNotExistErrorType $ liftIO $ deleteFile confFilePath rmCacheDir cacheDir = do $logInfo "removing ghcup cache Dir" From 59519febbc18d8691666b17611ca2ed4bebde38e Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 19:52:32 +0530 Subject: [PATCH 23/39] handle symlink case when deleting directories in rmGhcupDirs --- lib/GHCup.hs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index b35c692..0648079 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1381,19 +1381,19 @@ rmGhcupDirs = do $logInfo "removing ghcup cache Dir" contents <- liftIO $ listDirectory cacheDir forM_ contents deleteFile - removeDirIfEmpty cacheDir + removeDirIfEmptyOrIsSymlink cacheDir rmLogsDir logsDir = do $logInfo "removing ghcup logs Dir" contents <- liftIO $ listDirectory logsDir forM_ contents deleteFile - removeDirIfEmpty logsDir + removeDirIfEmptyOrIsSymlink logsDir rmBinDir binDir = do #if !defined(IS_WINDOWS) isXDGStyle <- liftIO $ useXDG if not isXDGStyle - then removeDirIfEmpty binDir + then removeDirIfEmptyOrIsSymlink binDir else pure () #else removeDirIfEmpty binDir @@ -1402,8 +1402,17 @@ rmGhcupDirs = do deleteFile filepath = do hideError InappropriateType $ rmFile filepath - removeDirIfEmpty filepath = - hideError UnsatisfiedConstraints $ liftIO $ removeDirectory filepath + removeDirIfEmptyOrIsSymlink filepath = + hideError UnsatisfiedConstraints $ + handleIO' InappropriateType + (handleIfSym filepath) + (liftIO $ removeDirectory filepath) + where + handleIfSym fp e = do + isSym <- liftIO $ pathIsSymbolicLink fp + if isSym + then liftIO $ deleteFile fp + else liftIO $ ioError e ------------------ --[ Debug info ]-- From 2277013c76e31def6f9f2cff9302fa690a178012 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 20:05:21 +0530 Subject: [PATCH 24/39] hide unsupportedOperation error in windows ghcup bin removal in case of different drives. --- lib/GHCup.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index def8725..04c5feb 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1298,7 +1298,9 @@ rmGhcup = do -- we move it to temp dir, to be deleted at next reboot tempDir <- liftIO $ getTemporaryDirectory let tempFilepath = tempDir ghcupFilename - liftIO $ hideError NoSuchThing $ Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 + hideError UnsupportedOperation $ + liftIO $ hideError NoSuchThing $ + Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 #else -- delete it. hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath From 6379a26afb658f6cc90270c2bba67be9d0bed030 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 21:53:14 +0530 Subject: [PATCH 25/39] factor out `getDirectoryContentsRecursive` function in GHCup.Utils.Prelude --- lib/GHCup/Utils/Prelude.hs | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/GHCup/Utils/Prelude.hs b/lib/GHCup/Utils/Prelude.hs index 9dd45f0..b31f700 100644 --- a/lib/GHCup/Utils/Prelude.hs +++ b/lib/GHCup/Utils/Prelude.hs @@ -340,31 +340,31 @@ copyDirectoryRecursive srcDir destDir = do -- parent directories. The list is generated lazily so is not well defined if -- the source directory structure changes before the list is used. -- - getDirectoryContentsRecursive :: FilePath -> IO [FilePath] - getDirectoryContentsRecursive topdir = recurseDirectories [""] +getDirectoryContentsRecursive :: FilePath -> IO [FilePath] +getDirectoryContentsRecursive topdir = recurseDirectories [""] + where + recurseDirectories :: [FilePath] -> IO [FilePath] + recurseDirectories [] = return [] + recurseDirectories (dir:dirs) = unsafeInterleaveIO $ do + (files, dirs') <- collect [] [] =<< getDirectoryContents (topdir dir) + files' <- recurseDirectories (dirs' ++ dirs) + return (files ++ files') + where - recurseDirectories :: [FilePath] -> IO [FilePath] - recurseDirectories [] = return [] - recurseDirectories (dir:dirs) = unsafeInterleaveIO $ do - (files, dirs') <- collect [] [] =<< getDirectoryContents (topdir dir) - files' <- recurseDirectories (dirs' ++ dirs) - return (files ++ files') + collect files dirs' [] = return (reverse files + ,reverse dirs') + collect files dirs' (entry:entries) | ignore entry + = collect files dirs' entries + collect files dirs' (entry:entries) = do + let dirEntry = dir entry + isDirectory <- doesDirectoryExist (topdir dirEntry) + if isDirectory + then collect files (dirEntry:dirs') entries + else collect (dirEntry:files) dirs' entries - where - collect files dirs' [] = return (reverse files - ,reverse dirs') - collect files dirs' (entry:entries) | ignore entry - = collect files dirs' entries - collect files dirs' (entry:entries) = do - let dirEntry = dir entry - isDirectory <- doesDirectoryExist (topdir dirEntry) - if isDirectory - then collect files (dirEntry:dirs') entries - else collect (dirEntry:files) dirs' entries - - ignore ['.'] = True - ignore ['.', '.'] = True - ignore _ = False + ignore ['.'] = True + ignore ['.', '.'] = True + ignore _ = False -- https://github.com/haskell/directory/issues/110 -- https://github.com/haskell/directory/issues/96 From 830fb70492d78b0f58571de861a65e529c36c9d0 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 21:54:42 +0530 Subject: [PATCH 26/39] adds returning left-over files back to Main.hs from rmGhcupDirs --- lib/GHCup.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 04c5feb..f493960 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1367,7 +1367,7 @@ rmGhcupDirs = do -- remove bin directory conditionally rmBinDir binDir - liftIO $ print dirs + reportRemainingFiles baseDir where @@ -1401,6 +1401,10 @@ rmGhcupDirs = do removeDirIfEmpty binDir #endif + reportRemainingFiles ghcupDir = do + remainingFiles <- liftIO $ getDirectoryContentsRecursive ghcupDir + pure remainingFiles + deleteFile filepath = do hideError InappropriateType $ rmFile filepath From 395aeb415d5bf98292c5cfb12205995e22add154 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 21:56:07 +0530 Subject: [PATCH 27/39] change return type of rmGhcupDirs to m [Filepath] from m () --- lib/GHCup.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index f493960..41b3478 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1339,7 +1339,7 @@ rmGhcupDirs :: ( MonadReader AppState m , MonadLogger m , MonadCatch m , MonadMask m ) - => m () + => m [FilePath] rmGhcupDirs = do dirs@Dirs { baseDir From f7986cb4da0793b27ae6caeab6ed6039d79f68f3 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 21:56:52 +0530 Subject: [PATCH 28/39] integrate new rmGhcupDirs fn into Main.hs --- app/ghcup/Main.hs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 12b866b..07af343 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1713,7 +1713,13 @@ Make sure to clean up #{tmpdir} afterwards.|]) lInstalled <- runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) forM_ lInstalled $ runRm . rmTool - runLogger $ runReaderT rmGhcupDirs appstate + leftOverFiles <- runLogger $ runReaderT rmGhcupDirs appstate + + case length leftOverFiles of + 0 -> runLogger $ $logInfo "Nuclear Annihilation complete!" + _ -> do + runLogger $ $logWarn "These Directories have survived Nuclear Annihilation, you'd may remove them manually." + forM_ leftOverFiles (runLogger . $logWarn . T.pack) pure ExitSuccess From 708cd5ead9e1dc8c07277a7a4ca70a65485e3af7 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 21:59:15 +0530 Subject: [PATCH 29/39] Fix a minor typo in some conditional windows code. --- lib/GHCup.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 41b3478..a667b3c 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1398,7 +1398,7 @@ rmGhcupDirs = do then removeDirIfEmptyOrIsSymlink binDir else pure () #else - removeDirIfEmpty binDir + removeDirIfEmptyOrIsSymlink binDir #endif reportRemainingFiles ghcupDir = do From bb7229d22456a67438a9cc8fb4370ff0d4269185 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 22:09:32 +0530 Subject: [PATCH 30/39] Adds descriptive comments in rmGhcupDir explaing silent deletions and leftover reporting. --- lib/GHCup.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index a667b3c..80f7a64 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1367,6 +1367,7 @@ rmGhcupDirs = do -- remove bin directory conditionally rmBinDir binDir + -- report files in baseDir that are left-over after the standard location deletions above reportRemainingFiles baseDir where @@ -1405,6 +1406,9 @@ rmGhcupDirs = do remainingFiles <- liftIO $ getDirectoryContentsRecursive ghcupDir pure remainingFiles + -- we expect only files inside cache/log dir + -- we report remaining files/dirs later, + -- hence the force/quiet mode in these delete functions below. deleteFile filepath = do hideError InappropriateType $ rmFile filepath From d166cc84a1e93c5f5c18d80bb2e72176ae36651a Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 23:26:31 +0530 Subject: [PATCH 31/39] change type of rmGhcup fn from "Excepts '[NotInstalled] m ()" to m () --- lib/GHCup.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 80f7a64..964a6ab 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1284,13 +1284,13 @@ rmStackVer ver = do -- assuming the current scheme of having just 1 ghcup bin, no version info is required. rmGhcup :: ( MonadReader AppState m - , MonadIO m, - MonadCatch m + , MonadIO m + , MonadCatch m ) - => Excepts '[NotInstalled] m () + => m () rmGhcup = do - AppState {dirs = Dirs {binDir}} <- lift ask + AppState {dirs = Dirs {binDir}} <- ask let ghcupFilename = "ghcup" <> exeExt let ghcupFilepath = binDir ghcupFilename #if defined(IS_WINDOWS) @@ -1332,7 +1332,7 @@ rmTool ListResult {lVer, lTool, lCross} = do rmStackVer lVer GHCup -> do - rmGhcup + lift rmGhcup rmGhcupDirs :: ( MonadReader AppState m , MonadIO m From aee7fa52c39cc41a89464054b3322d29175891d0 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sat, 26 Jun 2021 23:58:38 +0530 Subject: [PATCH 32/39] warn user if current running ghcup exec is in non-standard location --- lib/GHCup.hs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 964a6ab..548f016 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1286,6 +1286,7 @@ rmStackVer ver = do rmGhcup :: ( MonadReader AppState m , MonadIO m , MonadCatch m + , MonadLogger m ) => m () @@ -1293,18 +1294,30 @@ rmGhcup = do AppState {dirs = Dirs {binDir}} <- ask let ghcupFilename = "ghcup" <> exeExt let ghcupFilepath = binDir ghcupFilename + currentRunningExecPath <- liftIO $ getExecutablePath + if currentRunningExecPath == ghcupFilepath + then do #if defined(IS_WINDOWS) -- since it doesn't seem possible to delete a running exec in windows -- we move it to temp dir, to be deleted at next reboot - tempDir <- liftIO $ getTemporaryDirectory - let tempFilepath = tempDir ghcupFilename - hideError UnsupportedOperation $ - liftIO $ hideError NoSuchThing $ - Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 + tempDir <- liftIO $ getTemporaryDirectory + let tempFilepath = tempDir ghcupFilename + hideError UnsupportedOperation $ + liftIO $ hideError NoSuchThing $ + Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 #else - -- delete it. - hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath + -- delete it. + hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath #endif + else + $logWarn $ + nonStandardInstallLocationMsg currentRunningExecPath + + where + nonStandardInstallLocationMsg path = T.pack $ + "current ghcup is invoked from a non-standard location: \n" + <> path <> + "\n you may have to uninstall it manually." rmTool :: ( MonadReader AppState m , MonadLogger m From 8e4550657ec70c08bc92887ad243a21adcc896fa Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Sun, 27 Jun 2021 00:25:55 +0530 Subject: [PATCH 33/39] couple of windows indentation fixes in source files --- lib/GHCup.hs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 548f016..dcad07e 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1296,25 +1296,26 @@ rmGhcup = do let ghcupFilepath = binDir ghcupFilename currentRunningExecPath <- liftIO $ getExecutablePath if currentRunningExecPath == ghcupFilepath - then do + then + do #if defined(IS_WINDOWS) - -- since it doesn't seem possible to delete a running exec in windows - -- we move it to temp dir, to be deleted at next reboot - tempDir <- liftIO $ getTemporaryDirectory - let tempFilepath = tempDir ghcupFilename - hideError UnsupportedOperation $ - liftIO $ hideError NoSuchThing $ - Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 + -- since it doesn't seem possible to delete a running exec in windows + -- we move it to temp dir, to be deleted at next reboot + tempDir <- liftIO $ getTemporaryDirectory + let tempFilepath = tempDir ghcupFilename + hideError UnsupportedOperation $ + liftIO $ hideError NoSuchThing $ + Win32.moveFileEx ghcupFilepath (Just tempFilepath) 1 #else - -- delete it. - hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath + -- delete it. + hideError doesNotExistErrorType $ liftIO $ rmFile ghcupFilepath #endif - else + else $logWarn $ nonStandardInstallLocationMsg currentRunningExecPath - where - nonStandardInstallLocationMsg path = T.pack $ + where + nonStandardInstallLocationMsg path = T.pack $ "current ghcup is invoked from a non-standard location: \n" <> path <> "\n you may have to uninstall it manually." From 1dfe5cfecf1fb9871c9e1de22046215a2b4af785 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 28 Jun 2021 13:56:20 +0530 Subject: [PATCH 34/39] updates path equating (which may fail) in "rmGhcup" function. --- lib/GHCup.hs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index dcad07e..cc1a77e 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1294,8 +1294,23 @@ rmGhcup = do AppState {dirs = Dirs {binDir}} <- ask let ghcupFilename = "ghcup" <> exeExt let ghcupFilepath = binDir ghcupFilename + currentRunningExecPath <- liftIO $ getExecutablePath - if currentRunningExecPath == ghcupFilepath + + -- if paths do no exist, warn user, and continue to compare them, as is, + -- which should eventually fail and result in a non-standard install warning + + p1 <- handleIO' doesNotExistErrorType + (handlePathNotPresent currentRunningExecPath) + (liftIO $ canonicalizePath currentRunningExecPath) + + p2 <- handleIO' doesNotExistErrorType + (handlePathNotPresent ghcupFilename) + (liftIO $ canonicalizePath ghcupFilename) + + let areEqualPaths = equalFilePath p1 p2 + + if areEqualPaths then do #if defined(IS_WINDOWS) @@ -1315,6 +1330,10 @@ rmGhcup = do nonStandardInstallLocationMsg currentRunningExecPath where + handlePathNotPresent fp _err = do + $logWarn $ "Error: The path does not exist, " <> T.pack fp + pure fp + nonStandardInstallLocationMsg path = T.pack $ "current ghcup is invoked from a non-standard location: \n" <> path <> From 69a461d9c3af87e4aa6d9caae766799c2710d001 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 28 Jun 2021 19:32:09 +0530 Subject: [PATCH 35/39] Fix a couple of typos in Main.hs --- app/ghcup/Main.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 07af343..1e357be 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1703,7 +1703,7 @@ Make sure to clean up #{tmpdir} afterwards.|]) Nuke -> do runLogger $ $logWarn "WARNING: This will remove GHCup and all installed components from your system." - runLogger $ $logWarn "Wating 10 seconds before commencing, if you want to cancel it, now would be the time." + runLogger $ $logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time." threadDelay 10000000 -- wait 10s @@ -1718,7 +1718,7 @@ Make sure to clean up #{tmpdir} afterwards.|]) case length leftOverFiles of 0 -> runLogger $ $logInfo "Nuclear Annihilation complete!" _ -> do - runLogger $ $logWarn "These Directories have survived Nuclear Annihilation, you'd may remove them manually." + runLogger $ $logWarn "These Directories/Files have survived Nuclear Annihilation, you may remove them manually." forM_ leftOverFiles (runLogger . $logWarn . T.pack) pure ExitSuccess From a3b11f21bb598509080a0eba8b9fdbef6ac19ed8 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Mon, 28 Jun 2021 19:35:48 +0530 Subject: [PATCH 36/39] change logWarn to logDebug in "rmghcup / handlePathNotPresent" function --- lib/GHCup.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index cc1a77e..a867a17 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1331,7 +1331,7 @@ rmGhcup = do where handlePathNotPresent fp _err = do - $logWarn $ "Error: The path does not exist, " <> T.pack fp + $logDebug $ "Error: The path does not exist, " <> T.pack fp pure fp nonStandardInstallLocationMsg path = T.pack $ From f09f4bd1b78e9bb80eec7b8d460464fc116ed9da Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 29 Jun 2021 08:47:44 +0530 Subject: [PATCH 37/39] Update the running of "Nuke" command in Main.hs --- app/ghcup/Main.hs | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/app/ghcup/Main.hs b/app/ghcup/Main.hs index 1e357be..2188c61 100644 --- a/app/ghcup/Main.hs +++ b/app/ghcup/Main.hs @@ -1701,27 +1701,39 @@ Make sure to clean up #{tmpdir} afterwards.|]) >> pure (ExitFailure 13) else putStrLn uri' >> pure ExitSuccess - Nuke -> do - runLogger $ $logWarn "WARNING: This will remove GHCup and all installed components from your system." - runLogger $ $logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time." + Nuke -> + runRm (do + lift $ runLogger $ $logWarn "WARNING: This will remove GHCup and all installed components from your system." + lift $ runLogger $ $logWarn "Waiting 10 seconds before commencing, if you want to cancel it, now would be the time." + liftIO $ threadDelay 10000000 -- wait 10s - threadDelay 10000000 -- wait 10s + lift $ runLogger $ $logInfo "Initiating Nuclear Sequence 🚀🚀🚀" + lift $ runLogger $ $logInfo "Nuking in 3...2...1" - runLogger $ $logInfo "Initiating Nuclear Sequence 🚀🚀🚀" - runLogger $ $logInfo "Nuking in 3...2...1" - lInstalled <- runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) - forM_ lInstalled $ runRm . rmTool + lInstalled <- lift $ runLogger . flip runReaderT appstate $ listVersions Nothing (Just ListInstalled) - leftOverFiles <- runLogger $ runReaderT rmGhcupDirs appstate + forM_ lInstalled (liftE . rmTool) - case length leftOverFiles of - 0 -> runLogger $ $logInfo "Nuclear Annihilation complete!" - _ -> do - runLogger $ $logWarn "These Directories/Files have survived Nuclear Annihilation, you may remove them manually." - forM_ leftOverFiles (runLogger . $logWarn . T.pack) + leftOverFiles <- lift $ runLogger $ runReaderT rmGhcupDirs appstate + pure leftOverFiles + + ) >>= \case + VRight leftOverFiles -> do + + case length leftOverFiles of + 0 -> do + runLogger $ $logInfo "Nuclear Annihilation complete!" + pure ExitSuccess + _ -> do + runLogger $ $logWarn "These Directories/Files have survived Nuclear Annihilation, you may remove them manually." + forM_ leftOverFiles (runLogger . $logDebug . T.pack) + pure ExitSuccess + + VLeft e -> do + runLogger $ $(logError) $ T.pack $ prettyShow e + pure $ ExitFailure 15 - pure ExitSuccess case res of ExitSuccess -> pure () From bed06d13347d1ee87f3c1d82d33a6502f0f98303 Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 29 Jun 2021 08:56:57 +0530 Subject: [PATCH 38/39] make reported leftover file paths absolute --- lib/GHCup.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index a867a17..0a380fc 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1437,11 +1437,15 @@ rmGhcupDirs = do reportRemainingFiles ghcupDir = do remainingFiles <- liftIO $ getDirectoryContentsRecursive ghcupDir - pure remainingFiles + remainingFilesAbsolute <- makePathsAbsolute remainingFiles + pure remainingFilesAbsolute + + makePathsAbsolute paths = liftIO $ traverse makeAbsolute paths -- we expect only files inside cache/log dir -- we report remaining files/dirs later, -- hence the force/quiet mode in these delete functions below. + deleteFile filepath = do hideError InappropriateType $ rmFile filepath From 61019ecd49d7b3f89f83fcb872967af4598c5cda Mon Sep 17 00:00:00 2001 From: Arjun Kathuria Date: Tue, 29 Jun 2021 14:31:13 +0530 Subject: [PATCH 39/39] Adds reporting remaining leftover files sorted by Depth. --- lib/GHCup.hs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/GHCup.hs b/lib/GHCup.hs index 0a380fc..1c1ce27 100644 --- a/lib/GHCup.hs +++ b/lib/GHCup.hs @@ -1437,10 +1437,22 @@ rmGhcupDirs = do reportRemainingFiles ghcupDir = do remainingFiles <- liftIO $ getDirectoryContentsRecursive ghcupDir - remainingFilesAbsolute <- makePathsAbsolute remainingFiles + let normalizedFilePaths = fmap normalise remainingFiles + let sortedByDepthRemainingFiles = reverse $ sortBy compareFn normalizedFilePaths + remainingFilesAbsolute <- makePathsAbsolute sortedByDepthRemainingFiles + pure remainingFilesAbsolute - makePathsAbsolute paths = liftIO $ traverse makeAbsolute paths + where + calcDepth :: FilePath -> Int + calcDepth = length . filter isPathSeparator + + compareFn :: FilePath -> FilePath -> Ordering + compareFn fp1 fp2 = compare (calcDepth fp1) (calcDepth fp2) + + makePathsAbsolute :: (MonadIO m) => [FilePath] -> m [FilePath] + makePathsAbsolute paths = liftIO $ + traverse (makeAbsolute . normalise) paths -- we expect only files inside cache/log dir -- we report remaining files/dirs later,