    {-# LANGUAGE DeriveDataTypeable #-}

    -- | Properties to manipulate propellor's @/usr/local/propellor@ on spun hosts

    module Propellor.Property.Localdir where

    import Propellor.Base
    import Propellor.Git.Config
    import Propellor.Types.Info
    import Propellor.Types.Container
    import Propellor.Property.Mount (partialBindMountsOf, umountLazy)
    import qualified Propellor.Property.Git as Git

    -- | Sets the url to use as the origin of propellor's git repository.
    --
    -- By default, the url is taken from the deploy or origin remote of
    -- the repository that propellor --spin is run in. Setting this property
    -- overrides that default behavior with a different url.
    --
    -- When hosts are being updated without using -- --spin, eg when using
    -- the `Propellor.Property.Cron.runPropellor` cron job, this property can
    -- be set to redirect them to a new git repository url.
    hasOriginUrl :: String -> Property (HasInfo + DebianLike)
    hasOriginUrl u =
            setInfoProperty p (toInfo (InfoVal (OriginUrl u)))
                    `requires` Git.installed
      where
            p :: Property UnixLike
            p = property ("propellor repo url " ++ u) $ do
                    curru <- liftIO getRepoUrl
                    if curru == Just u
                            then return NoChange
                            else makeChange $ setRepoUrl u

    newtype OriginUrl = OriginUrl String
            deriving (Show, Typeable)

    -- | Removes the @/usr/local/propellor@ directory used to spin the host, after
    -- ensuring other properties.  Without this property, that directory is left
    -- behind after the spin.
    --
    -- Does not perform other clean up, such as removing Haskell libraries that were
    -- installed in order to build propellor, or removing cronjobs such as created
    -- by 'Propellor.Property.Cron.runPropellor'.
    removed :: Property UnixLike
    removed = check (doesDirectoryExist localdir) $
            property "propellor's /usr/local dir to be removed" $ do
                    endAction "removing /usr/local/propellor" atend
                    return NoChange
      where
            atend _ = do
                    ifM (hasContainerCapability FilesystemContained)
                            -- In a chroot, all we have to do is unmount localdir,
                            -- and then delete it
                            ( liftIO $ umountLazy localdir
                            -- Outside of a chroot, if we don't unmount any bind
                            -- mounts of localdir before deleting it, another run of
                            -- propellor will have problems reestablishing those
                            -- bind mounts in order to spin chroots
                            , liftIO $ partialBindMountsOf localdir
                                    >>= mapM_ umountLazy
                            )
                    liftIO $ removeDirectoryRecursive localdir
                    return NoChange