packages feed

clean-home (empty) → 0.0.1

raw patch · 14 files changed

+518/−0 lines, 14 filesdep +HSHdep +IfElsedep +basesetup-changed

Dependencies added: HSH, IfElse, base, cmdargs, containers, directory

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012, Ivan Perez - Keera Studios++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Ivan Perez nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ clean-home.cabal view
@@ -0,0 +1,79 @@+-- clean-home.cabal auto-generated by cabal init. For additional+-- options, see+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.+-- The name of the package.+Name:                clean-home++-- The package version. See the Haskell package versioning policy+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for+-- standards guiding when and how versions should be incremented.+Version:             0.0.1++-- A short (one-line) description of the package.+Synopsis:            Keep your home dir clean by finding old conf files+Description:         clean-home searches for config files in your $HOME+                     that no installed package/program will need.++-- URL for the project homepage or repository.+Homepage:            https://github.com/ivanperez-keera/clean-home++-- The license under which the package is released.+License:             BSD3++-- The file containing the license text.+License-file:        LICENSE++-- The package author(s).+Author:              Ivan Perez++-- An email address to which users can send suggestions, bug reports,+-- and patches.+Maintainer:          ivan.perez@keera.es++-- A copyright notice.+-- Copyright:           ++Category:            System++Build-type:          Simple++Data-files: data/PkgList+          , data/PrgList++-- Extra files to be distributed with the package, such as examples or+-- a README.+-- Extra-source-files:  ++-- Constraint on the version of Cabal needed to build this package.+Cabal-version:       >=1.6+++Executable clean-home+  Main-is: Main.hs+  hs-source-dirs: src/+  ghc-options: -Wall+  +  -- Packages needed in order to build this package.+  Build-depends: base       >= 4 && <= 5+               , cmdargs    >= 0.9+               , HSH        >= 2.0+               , directory+               , containers >= 0.4+               , IfElse+  +  -- Modules not exported by this package.+  Other-modules: SearchCommand.Apt+               , SearchCommand.Which+               , SearchCommand.UserSet+               , SearchCommands+               , Args+               , Env+               , Control.Exception.Extra+               , System.Err+  +  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+  -- Build-tools:         +  +source-repository head+  type:     git+  location: http://github.com/ivanperez-keera/clean-home
+ data/PkgList view
@@ -0,0 +1,46 @@+[ (".cabal",           [ "cabal", "cabal-install" ])+, (".emacs",           [ "emacs", "emacs21", "emacs22", "emacs23" ]) +, (".emacs.d",         [ "emacs", "emacs21", "emacs22", "emacs23"])+, (".mozilla",         [ "firefox", "iceweasel"       ])+, (".lftp",            [ "lftp"                       ])+, (".mission-control", [ "mission-control"            ])+, (".viminfo",         [ "vim", "vim-gnome"           ])+, (".vim",             [ "vim", "vim-gnome"           ])+, (".vimrc",           [ "vim", "vim-gnome"           ])+, (".wine",            [ "wine", "wine1.2", "wine1.3" ])+, (".eclipse",         [ "eclipse"                    ])+, (".kde",             [ "kde"                        ])+, (".libreoffice",     [ "libreoffice"                ])+, (".openoffice.org",  [ "openoffice"                 ])+, (".VirtualBox",      [ "virtualbox-ose"             ])+, (".ssh",             [ "openssh-client"             ])+, (".xmind",           [ "xmind"                      ])+, (".gSTM",            [ "gstm"                       ])+, (".bashrc",          [ "bash"                       ])+, (".bash_logout",     [ "bash"                       ])+, (".bash_profile",    [ "bash"                       ])+, (".bash_history",    [ "bash"                       ])+, (".gimp-2.6",        [ "gimp"                       ])+, (".hgrc",            [ "mercurial"                  ])+, (".gconfd",          [ "gconf2"                     ])+, (".subversion",      [ "subversion"                 ])+, (".lyx",             [ "lyx"                        ])+, (".thunderbird",     [ "thunderbird"                ])+, (".xine",            [ "xine-ui"                    ])+, (".lesshst",         [ "less"                       ])+, (".gitconfig",       [ "git"                        ])+, (".Skype",           [ "skype"                      ])+, (".gem",             [ "rubygems"                   ])+, (".mplayer",         [ "mplayer"                    ])+, (".aptitude",        [ "aptitude"                   ])+, (".sqlite_history",  [ "sqlite3"                    ])+, (".shotwell",        [ "shotwell"                   ])+, (".ghc",             [ "ghc"                        ])+, (".gvfs",            [ "gvfs"                       ])+, (".mysql_history",   [ "mysql-client"               ])+, (".audacity-data",   [ "audacity"                   ])+, (".xournal",         [ "xournal"                    ])+, (".qtstalker",       [ "qtstalker"                  ])+, (".icedteaplugin",   [ "icedtea-plugin"             ])+, (".gnupg",           [ "gnupg"                      ])+]
+ data/PrgList view
@@ -0,0 +1,47 @@+[ (".cabal",           [ "cabal", "cabal-install" ])+, (".emacs",           [ "emacs", "emacs21", "emacs22", "emacs23" ]) +, (".emacs.d",         [ "emacs", "emacs21", "emacs22", "emacs23"])+, (".lftp",            [ "lftp"                       ])+, (".mission-control", [ "mission-control"            ])+, (".mozilla",         [ "firefox", "iceweasel"       ])+, (".viminfo",         [ "vim", "gvim"                ])+, (".diamondcard-sms", [ "keera-diamondcard-sms-trayicon"])+, (".vim",             [ "vim", "gvim"                ])+, (".vimrc",           [ "vim", "gvim"                ])+, (".wine",            [ "wine"                       ])+, (".eclipse",         [ "eclipse"                    ])+, (".kde",             [ "kde"                        ])+, (".libreoffice",     [ "libreoffice"                ])+, (".openoffice.org",  [ "openoffice"                 ])+, (".VirtualBox",      [ "virtualbox-ose"             ])+, (".ssh",             [ "openssh-client"             ])+, (".xmind",           [ "xmind"                      ])+, (".gSTM",            [ "gstm"                       ])+, (".bashrc",          [ "bash"                       ])+, (".bash_logout",     [ "bash"                       ])+, (".bash_profile",    [ "bash"                       ])+, (".bash_history",    [ "bash"                       ])+, (".gimp-2.6",        [ "gimp"                       ])+, (".hgrc",            [ "mercurial"                  ])+, (".gconfd",          [ "gconf2"                     ])+, (".subversion",      [ "subversion"                 ])+, (".lyx",             [ "lyx"                        ])+, (".thunderbird",     [ "thunderbird"                ])+, (".xine",            [ "xine"                       ])+, (".lesshst",         [ "less"                       ])+, (".gitconfig",       [ "git"                        ])+, (".Skype",           [ "skype"                      ])+, (".gem",             [ "rubygems"                   ])+, (".mplayer",         [ "mplayer"                    ])+, (".aptitude",        [ "aptitude"                   ])+, (".sqlite_history",  [ "sqlite3"                    ])+, (".shotwell",        [ "shotwell"                   ])+, (".ghc",             [ "ghc"                        ])+, (".gvfs",            [ "gvfs"                       ])+, (".mysql_history",   [ "mysql-client"               ])+, (".audacity-data",   [ "audacity"                   ])+, (".xournal",         [ "xournal"                    ])+, (".qtstalker",       [ "qtstalker"                  ])+, (".icedteaplugin",   [ "icedtea-plugin"             ])+, (".gnupg",           [ "gnupg"                      ])+]
+ src/Args.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE DeriveDataTypeable #-}+module Args where++import Data.Data+import System.Console.CmdArgs++-- This is the CLI app definition : what we get from the user+data Args = Args {+  showNotOrphan   :: Bool+  , byPackage     :: Bool+  , byProgram     :: Bool+  , pkgSearchProg :: String+  , pkgSearchArgs :: [String]+  , pkgSearchExitCode :: Bool+  +  -- To be added+  --   home          :: String   -- Use this dir instead of the current+  --                             -- user's home dir+  -- , verbose       :: Bool     -- Show everything you do+  -- , ignore        :: [String] -- Ignore these filepaths+  -- , remove        :: Bool     -- Give users the option to remove orphan fps+  }+ deriving (Show, Data, Typeable)++-- This is the cmdArgs-based CLI interface definition+chArgs :: Args+chArgs = Args+ {  showNotOrphan = False+ &= explicit+ &= name "show-not-orphan"+ &= help "Whether dirs with an owning program show be shown" + + , byPackage = enum [ True  &= explicit &= name "by-package"+                            &= help "Search by package name (enabled by default)"+                    , False &= explicit &= name "not-by-package"+                            &= help "Do not search by package name"+                    ]+ -- &= explicit+ -- &= name "by-package"+ -- &= help "Search the responsible program by package name"++ , byProgram = enum [ True  &= explicit &= name "by-program"+                            &= help "Search by program name (enabled by default)"+                    , False &= explicit &= name "not-by-program"+                            &= help "Do not search by program name"+                    ]++ , pkgSearchProg = def+ &= explicit+ &= name "with-pkg-search"+ &= help "Program used to search for packages"+ &= typ "PROGRAM"++ , pkgSearchArgs = def+ &= explicit+ &= name "with-pkg-search-opt"+ &= help "Arguments passed to pkg-search program"+ &= typ "ARG"++ , pkgSearchExitCode = False+ &= explicit+ &= name "with-pkg-search-exit-code"+ &= help "Use program exit code to determine package presence"+ + }+ &= summary "clean-home 0.0.1"+ &= details [ "(c) 2012 Ivan Perez - Keera Studios"+            , "Find more about clean-home at http://keera.es"+            , "and http://github.com/ivanperez-keera/clean-home"+            ]
+ src/Control/Exception/Extra.hs view
@@ -0,0 +1,13 @@+module Control.Exception.Extra where++import qualified Control.Exception as E++-- | Returns a given computation ignoring an exception+anyway :: a -> E.SomeException -> a+anyway f _ = f++-- | Tries to execute all the IO computations+-- until one succeeds+trySeq :: [IO ()] -> IO ()+trySeq []     = return ()+trySeq (x:xs) = E.handle (anyway (trySeq xs)) x
+ src/Env.hs view
@@ -0,0 +1,59 @@+module Env where++import Control.Monad+import Control.Exception as E+import Control.Exception.Extra++import Args+import System.Err+import Paths_clean_home++data Env = Env+ { appArgs :: Args+ , pkgList :: PkgList+ , prgList :: PrgList+ }++type PrgList = [ (String, [ String ]) ]+type PkgList = [ (String, [ String ]) ]++type ConfigSearchCmd = Env -> FilePath -> String -> IO (Either String Bool)++-- | Reads and returns the program list contained in+-- the file PrgList.+readPrgList :: Args -> IO (Maybe PrgList)+readPrgList appArgs+ | byProgram appArgs = readListFP "data/PrgList" "program list"+ | otherwise         = return $ Just []++-- | Reads and returns the package list contained in+-- the file PrgList.+readPkgList :: Args -> IO (Maybe PkgList)+readPkgList appArgs+ | byPackage appArgs = readListFP "data/PkgList" "package list"+ | otherwise         = return $ Just []++readListFP :: Read a => FilePath -> String -> IO (Maybe [a])+readListFP fn n = do+  fp <- getDataFileName fn+  list <- E.handle (anyway (return [])) $+            liftM reads $ readFile fp+  case list of+   []        -> do putErrLn $ "Cannot read or parse " ++ n+                   return Nothing+   ((x,_):_) -> return (Just x)++-- FIXME: MaybeT?+buildEnv :: Args -> IO (Maybe Env)+buildEnv appArgs +  | not (pkg || prg)+  = do putErrLn "You must enable --by-package or --by-program"+       return Nothing+  | otherwise +  = do pkgList <- readPkgList appArgs+       prgList <- readPrgList appArgs+       case (pkgList, prgList) of+         (Just pkgs, Just prgs) -> return $ Just $ Env appArgs pkgs prgs+         _                      -> return Nothing+  where pkg = byPackage appArgs+        prg = byProgram appArgs
+ src/Main.hs view
@@ -0,0 +1,65 @@+-- | This program checks every file/dir in $HOME against+-- a list of know programs/packages to determine whether+-- we have any program installed that may need it.++import           Control.Monad.IfElse+import           Data.List+import qualified Data.Map               as M+import           System.Directory+import           System.Console.CmdArgs++-- Local imports+import Args+import Env+import SearchCommands+import System.Err++main :: IO ()+main = do+  -- Process args and build an env+  env <- buildEnv =<< cmdArgs chArgs+  awhen env $ \env' ->+    -- Get config files and check them+    mapM_ (checkFile env') =<< getHomeConfFiles env'++-- | Gets the list of filepaths that may be config paths+getHomeConfFiles :: Env -> IO [FilePath]+getHomeConfFiles _env = do+  homeDir <- getHomeDirectory  +  names   <- getDirectoryContents homeDir+  return $ filter isConfigPath $ sort names+  where isConfigPath :: String -> Bool+        isConfigPath x = x `notElem` [".", ".."] && "." `isPrefixOf` x++-- Checks a file using all the know programs and packages+-- that may be responsible for it+checkFile :: Env -> FilePath -> IO ()+checkFile env fp = checkFile' env fp allChks+   where allChks  = prgChks' ++ pkgChks'+         pkgChks' = if byPackage (appArgs env) then pkgChks else []+         prgChks' = if byProgram (appArgs env) then prgChks else []+         pkgChks  = map (checkPackage env fp) pkgs+         prgChks  = map (checkProgram env fp) prgs+         pkgs     = packageSearch env fp+         prgs     = programSearch env fp++-- | Prints a message indicating that the file is orphan (when it is)+-- and shows error messages when appropriate+checkFile' :: Env -> FilePath -> [IO (Either String Bool)] -> IO ()+checkFile' _env fp []     = putErrLn $ "Warning: Orphan dir: " ++ fp+checkFile' env  fp (x:xs) = do+  res <- x+  case res of+   (Left s)      -> putErrLn s+   (Right False) -> checkFile' env fp xs+   (Right True)  -> return ()++-- | Search config cp and return associated packages+packageSearch :: Env -> String -> [ String ]+packageSearch env k = M.findWithDefault [] k (M.fromList pkgs)+  where pkgs = pkgList env++-- | Search config cp and return associated programs+programSearch :: Env -> String -> [ String ]+programSearch env k = M.findWithDefault [] k (M.fromList prgs)+  where prgs = prgList env
+ src/SearchCommand/Apt.hs view
@@ -0,0 +1,18 @@+module SearchCommand.Apt where++import Data.List++-- Local imports+import Env+import SearchCommand.UserSet++aptSearch :: ConfigSearchCmd+aptSearch env fp pkg = userSetSearchCustom+  (Left "apt-get exited with error code")+  (\results -> not (null results) && any ((pkg ++ " -") `isPrefixOf`) results)+  cmd env fp pkg+  where cmd = ("apt-cache", [ "search"+                            , "--installed"+                            , "--names-only"+                            , "^" ++ pkg ++ "$"]+              )
+ src/SearchCommand/UserSet.hs view
@@ -0,0 +1,54 @@+module SearchCommand.UserSet+   ( userSetSearch+   , userSetSearchExitCode+   , userSetSearchOutput+   , userSetSearchCustom+   , userSetSearchCombined+   )+  where++-- External imports+import Control.Monad+import Control.Exception as E+import Control.Exception.Extra+import HSH++-- Local imports+import Args+import Env+import System.Err++userSetSearch :: ConfigSearchCmd+userSetSearch env fp pkg+  | pkgSearchExitCode (appArgs env) = userSetSearchExitCode cmd env fp pkg+  | otherwise                       = userSetSearchOutput   cmd env fp pkg+  where cmd = (pkgSearchProg (appArgs env),+               pkgSearchArgs (appArgs env) ++ [ pkg ]+              )++type CMD = (String, [String])++userSetSearchExitCode :: CMD -> ConfigSearchCmd+userSetSearchExitCode = userSetSearchCustom (Right False) (const True)++userSetSearchOutput :: CMD -> ConfigSearchCmd+userSetSearchOutput cmd env fp pkg =+  userSetSearchCustom (Left (pkg ++ " exited with error code"))+                      (not.null)+                      cmd env fp pkg++userSetSearchCombined :: CMD -> ConfigSearchCmd+userSetSearchCombined = userSetSearchCustom (Right False) (not.null)+     +userSetSearchCustom :: Either String Bool+                    -> ([String] -> Bool)+                    -> CMD+                    -> ConfigSearchCmd+userSetSearchCustom exceptRet test cmd env fp pkg =+   E.handle (anyway (return exceptRet)) $ do+    results <- run cmd :: IO [String]+    let notOrphan = test results+    when (notOrphan && showNotOrphan (appArgs env)) $+      putErrLn $ pkg ++ " might be responsible for " ++ fp+    return $ Right notOrphan+
+ src/SearchCommand/Which.hs view
@@ -0,0 +1,9 @@+module SearchCommand.Which where++-- Local imports+import Env+import SearchCommand.UserSet++whichSearch :: ConfigSearchCmd+whichSearch env fp prg = userSetSearchCombined cmd env fp prg+  where cmd = ("which", [ prg ])
+ src/SearchCommands.hs view
@@ -0,0 +1,17 @@+module SearchCommands where++-- Local imports+import Args+import Env+import SearchCommand.Apt+import SearchCommand.Which+import SearchCommand.UserSet++-- FIXME: The problem is here+checkPackage :: ConfigSearchCmd+checkPackage env fp pkg+  | null (pkgSearchProg (appArgs env)) = aptSearch env fp pkg+  | otherwise                          = userSetSearch env fp pkg++checkProgram :: ConfigSearchCmd+checkProgram = whichSearch
+ src/System/Err.hs view
@@ -0,0 +1,9 @@+module System.Err where++import System.IO++putErr :: String -> IO()+putErr = hPutStr stderr++putErrLn :: String -> IO()+putErrLn = hPutStrLn stderr