module Propellor.Property.Rsync where import Propellor.Base import qualified Propellor.Property.Apt as Apt import qualified Propellor.Property.Pacman as Pacman type Src = FilePath type Dest = FilePath class RsyncParam p where toRsync :: p -> String -- | A pattern that matches all files under a directory, but does not -- match the directory itself. filesUnder :: FilePath -> Pattern filesUnder d = Pattern (d ++ "/*") -- | Ensures that the Dest directory exists and has identical contents as -- the Src directory. syncDir :: Src -> Dest -> Property (DebianLike + ArchLinux) syncDir = syncDirFiltered [] data Filter = Include Pattern | Exclude Pattern | Protect Pattern instance RsyncParam Filter where toRsync (Include (Pattern p)) = "--include=" ++ p toRsync (Exclude (Pattern p)) = "--exclude=" ++ p toRsync (Protect (Pattern p)) = "--filter=P " ++ p -- | A pattern to match against files that rsync is going to transfer. -- -- See "INCLUDE/EXCLUDE PATTERN RULES" in the rsync(1) man page. -- -- For example, Pattern "/foo/*" matches all files under the "foo" -- directory, relative to the 'Src' that rsync is acting on. newtype Pattern = Pattern String -- | Like syncDir, but avoids copying anything that the filter list -- excludes. Anything that's filtered out will be deleted from Dest. -- -- Rsync checks each name to be transferred against its list of Filter -- rules, and the first matching one is acted on. If no matching rule -- is found, the file is processed. syncDirFiltered :: [Filter] -> Src -> Dest -> Property (DebianLike + ArchLinux) syncDirFiltered filters src dest = rsync $ [ "-a" -- Add trailing '/' to get rsync to sync the Dest directory, -- rather than a subdir inside it, which it will do without a -- trailing '/'. , addTrailingPathSeparator src , addTrailingPathSeparator dest , "--delete" , "--delete-excluded" , "--info=progress2" ] ++ map toRsync filters rsync :: [String] -> Property (DebianLike + ArchLinux) rsync ps = cmdProperty "rsync" ps `assume` MadeChange `requires` installed installed :: Property (DebianLike + ArchLinux) installed = Apt.installed ["rsync"] `pickOS` Pacman.installed ["rsync"]