barley-0.3: src/Barley/Project.hs
-- Copyright 2010 Google Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
module Barley.Project
( ProjectDir(..)
, enter
, init
) where
import Control.Monad (unless, when)
import Paths_barley -- generated by cabal
import Prelude hiding (init)
import System.Directory
import System.Exit
import System.FilePath
-- | A specification of a project directory
data ProjectDir = CurrentDir | ProjectDir FilePath
projectPath :: ProjectDir -> FilePath
projectPath CurrentDir = "." -- FIXME: The use of "." is probably not right
projectPath (ProjectDir fp) = fp
-- | The presence of this file indicates a directory is a barley project.
-- In the future we might store information in it.
markerFile :: FilePath
markerFile = ".barley-project"
-- | Change into the project directory.
-- Fails if the directory can't be entered.
enter :: ProjectDir -> IO ()
enter projectDir = do
exists <- case projectDir of
CurrentDir -> return True
ProjectDir fp -> doesDirectoryExist fp
unless exists $
putStrLn ("Project directory doesn't exist: " ++ pdPath) >>
exitFailure
hasMarker <- doesFileExist (pdPath </> markerFile)
unless hasMarker $
putStrLn "Directory doesn't appear to be a Barely project." >>
putStrLn ("Missing .barley-project file in directory: " ++ pdPath) >>
exitFailure
case projectDir of
CurrentDir -> return ()
ProjectDir fp -> setCurrentDirectory fp
where
pdPath = projectPath projectDir
-- | Create a project directory structure.
init :: Bool -> ProjectDir -> IO ()
init warnIfNotEmpty projectDir = nothingHere >>= \b -> if b
then copyInitialProject projectDir
else when warnIfNotEmpty $
putStrLn "** This directory is not empty. Not initializing."
where
nothingHere = whatsHere >>= return . null . filter notDot
whatsHere = case projectDir of
CurrentDir -> getCurrentDirectory >>= getDirectoryContents
ProjectDir fp -> do
exists <- doesDirectoryExist fp
if exists
then getDirectoryContents fp
else return []
notDot ('.':_) = False
notDot _ = True
-- | Copy the initial project skeleton to the project directory.
copyInitialProject :: ProjectDir -> IO ()
copyInitialProject projectDir = do
fromDir <- getSeedDir
let toDir = projectPath projectDir
putStrLn "Creating default project files..."
copyTree fromDir toDir
writeFile (toDir </> markerFile) ""
putStrLn "...done."
-- | Locate seed dir in current dir, or data dir, or if neither, fail.
getSeedDir :: IO FilePath
getSeedDir = findFirstSeed [ getCurrentDirectory, getDataDir ]
where
findFirstSeed (g:gs) = do
s <- g >>= return . (</> "seed")
exists <- doesDirectoryExist s
if exists
then return s
else findFirstSeed gs
findFirstSeed [] = do
putStrLn "** No seed directory found."
putStrLn "** You should try reinstalling Barley."
exitFailure
-- | Copy a directory tree from one place to another. The destination, or
-- the subtrees needn't exist. If they do, existing files with the same names
-- as the source will be overwritten. Other files will be left alone.
copyTree :: FilePath -> FilePath -> IO ()
copyTree from to = pick
[(doesFileExist, doFile),
(doesDirectoryExist, doDir)]
where
pick ((test, act):rest) = do
bool <- test from
if bool
then putStrLn (" " ++ to) >> act
else pick rest
pick [] =
putStrLn $ "** Skipping funny thing in skeleton tree: " ++ from
doFile = copyFile from to
doDir = do
createDirectoryIfMissing False to
getDirectoryContents from >>= mapM_ dive . filter notSpecial
dive item = copyTree (from </> item) (to </> item)
notSpecial item = item /= "." && item /= ".."