Refactor dependency oracles
[ghc.git] / src / Package.hs
1 {-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
2 module Package (
3 Package (..), PackageName (..), PackageType (..),
4 -- * Queries
5 pkgNameString, pkgCabalFile,
6 -- * Helpers for constructing and using 'Package's
7 setPath, topLevel, library, utility, setType, isLibrary, isProgram
8 ) where
9
10 import Data.String
11 import GHC.Generics (Generic)
12
13 import Base
14
15 -- | The name of a Cabal package.
16 newtype PackageName = PackageName { fromPackageName :: String }
17 deriving (Binary, Eq, Generic, Hashable, IsString, NFData, Ord, Typeable)
18
19 -- TODO: Make PackageType more precise, #12.
20 -- TODO: Turn Program to Program FilePath thereby getting rid of programPath
21 -- | We regard packages as either being libraries or programs. This is bit of a
22 -- convenient lie as Cabal packages can be both, but it works for now.
23 data PackageType = Library | Program deriving Generic
24
25 data Package = Package
26 { pkgName :: PackageName -- ^ Examples: "ghc", "Cabal".
27 , pkgPath :: FilePath -- ^ pkgPath is the path to the source code relative
28 -- to the root, e.g. "compiler", "libraries/Cabal/Cabal".
29 , pkgType :: PackageType -- ^ A library or a program.
30 } deriving Generic
31
32 -- | Prettyprint 'Package' name.
33 pkgNameString :: Package -> String
34 pkgNameString = fromPackageName . pkgName
35
36 -- | Relative path to cabal file, e.g.: "libraries/Cabal/Cabal/Cabal.cabal"
37 pkgCabalFile :: Package -> FilePath
38 pkgCabalFile pkg = pkgPath pkg -/- pkgNameString pkg <.> "cabal"
39
40 -- | Smart constructor for a top-level package, e.g. 'compiler'.
41 topLevel :: PackageName -> Package
42 topLevel name = Package name (fromPackageName name) Library
43
44 -- | Smart constructor for a library package, e.g. 'array'.
45 library :: PackageName -> Package
46 library name = Package name ("libraries" -/- fromPackageName name) Library
47
48 -- | Smart constructor for a utility package, e.g. 'haddock'.
49 utility :: PackageName -> Package
50 utility name = Package name ("utils" -/- fromPackageName name) Program
51
52 -- | Amend package path. Useful when a package name doesn't match its path.
53 setPath :: Package -> FilePath -> Package
54 setPath pkg path = pkg { pkgPath = path }
55
56 -- | Amend package type.
57 setType :: Package -> PackageType -> Package
58 setType pkg ty = pkg { pkgType = ty }
59
60 -- | Check whether a package is a library.
61 isLibrary :: Package -> Bool
62 isLibrary (Package _ _ Library) = True
63 isLibrary _ = False
64
65 -- | Check whether a package is a program.
66 isProgram :: Package -> Bool
67 isProgram (Package _ _ Program) = True
68 isProgram _ = False
69
70 -- TODO: Get rid of non-derived Show instances.
71 instance Show Package where
72 show = pkgNameString
73
74 instance Eq Package where
75 (==) = (==) `on` pkgName
76
77 instance Ord Package where
78 compare = compare `on` pkgName
79
80 -- | Instances for storing in the Shake database.
81 instance Binary Package
82 instance Hashable Package where
83 hashWithSalt salt = hashWithSalt salt . show
84 instance NFData Package
85
86 instance Binary PackageType
87 instance Hashable PackageType
88 instance NFData PackageType