diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2011, Daniel Trstenjak
+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 the <organization> nor the
+      names of its 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 DANIEL TRSTENJAK 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.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+cabal-lenses
+============
+
+Lenses and traversals (compatible with the [lens library](<https://hackage.haskell.org/package/lens>)) for the [Cabal library](<https://hackage.haskell.org/package/Cabal>).
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/cabal-lenses.cabal b/cabal-lenses.cabal
new file mode 100644
--- /dev/null
+++ b/cabal-lenses.cabal
@@ -0,0 +1,44 @@
+name: cabal-lenses
+version: 0.1
+cabal-version: >=1.9.2
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+maintainer: daniel.trstenjak@gmail.com
+synopsis: Lenses and traversals for the Cabal library.
+description:
+    Lenses and traversals (compatible with the <https://hackage.haskell.org/package/lens lens>) library) for
+    the <https://hackage.haskell.org/package/Cabal Cabal> library.
+category: Utils
+author: Daniel Trstenjak
+data-dir: ""
+extra-source-files: 
+    README.md
+ 
+source-repository head
+    type: git
+    location: https://github.com/dan-t/cabal-lenses
+ 
+library
+    build-depends: 
+        base >=3 && <5,
+        lens >=4.0.1 && <4.1,
+        unordered-containers >=0.2.3.3 && <0.3,
+        Cabal >=1.18.0 && <1.21
+    exposed-modules: 
+        CabalLenses
+        CabalLenses.PackageDescription
+        CabalLenses.Package
+        CabalLenses.Version
+        CabalLenses.CondVars
+        CabalLenses.Section
+        CabalLenses.Traversals.BuildInfo
+        CabalLenses.Traversals.Dependency
+    other-modules:
+        CabalLenses.Traversals.Internal
+    exposed: True
+    buildable: True
+    cpp-options: -DCABAL
+    hs-source-dirs: lib
+    other-modules: Paths_cabal_lenses
+    ghc-options: -W
diff --git a/lib/CabalLenses.hs b/lib/CabalLenses.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses.hs
@@ -0,0 +1,18 @@
+
+module CabalLenses
+   ( module CabalLenses.CondVars
+   , module CabalLenses.PackageDescription
+   , module CabalLenses.Package
+   , module CabalLenses.Version
+   , module CabalLenses.Section
+   , module CabalLenses.Traversals.BuildInfo
+   , module CabalLenses.Traversals.Dependency
+   ) where
+
+import CabalLenses.CondVars
+import CabalLenses.PackageDescription
+import CabalLenses.Package
+import CabalLenses.Version
+import CabalLenses.Section
+import CabalLenses.Traversals.BuildInfo
+import CabalLenses.Traversals.Dependency
diff --git a/lib/CabalLenses/CondVars.hs b/lib/CabalLenses/CondVars.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/CondVars.hs
@@ -0,0 +1,92 @@
+{-# Language TemplateHaskell, PatternGuards #-}
+
+module CabalLenses.CondVars
+   ( CondVars(..)
+   , fromDefaults
+   , enableFlag
+   , disableFlag
+   , eval
+   ) where
+
+import qualified Distribution.PackageDescription as PD
+import Distribution.PackageDescription (Condition(..))
+import qualified Distribution.System as S
+import Distribution.System (OS(..), Arch(..))
+import Distribution.Compiler (CompilerFlavor(..), buildCompilerFlavor)
+import Distribution.Version (Version(..), withinRange)
+import qualified Data.HashMap.Strict as HM
+import Control.Lens
+
+type FlagName = String
+type FlagMap  = HM.HashMap FlagName Bool
+
+
+-- | The variables that are used to resolve the conditionals inside of the cabal file.
+--   Holds the enable state of the cabal flags, the used OS, ARCH, CompilerFlavor and
+--   compiler version.
+data CondVars = CondVars
+   { flags           :: FlagMap          -- ^ the enable state of the flags, initialized with the default flag values in the cabal file
+   , os              :: OS               -- ^ the used OS, by default the one cabal was build on
+   , arch            :: Arch             -- ^ the used ARCH, by default the one cabal was build on
+   , compilerFlavor  :: CompilerFlavor   -- ^ the used CompilerFlavor, by default the one cabal was build on
+   , compilerVersion :: Maybe Version    -- ^ the user specified compiler version
+   } deriving (Show)
+
+
+makeLensesFor [ ("flags", "flagsL")
+              ] ''CondVars
+
+
+-- | Create a 'CondVars' from the default flags of the cabal package description.
+--   The 'os', 'arch' and 'compilerFlavor' fields are initialized by the ones the cabal library was build on.
+fromDefaults :: PD.GenericPackageDescription -> CondVars
+fromDefaults pkgDescrp = CondVars { flags           = flags
+                                  , os              = S.buildOS
+                                  , arch            = S.buildArch
+                                  , compilerFlavor  = buildCompilerFlavor
+                                  , compilerVersion = Nothing
+                                  }
+   where
+      flags = HM.fromList $ map nameWithDflt (PD.genPackageFlags pkgDescrp)
+
+      nameWithDflt PD.MkFlag { PD.flagName = PD.FlagName name, PD.flagDefault = dflt } =
+         (name, dflt)
+
+
+-- | Enable the given flag in 'CondVars'.
+enableFlag :: FlagName -> CondVars -> CondVars
+enableFlag flag condVars =
+   condVars & flagsL %~ HM.insert flag True
+
+
+-- | Disable the given flag in 'CondVars'.
+disableFlag :: FlagName -> CondVars -> CondVars
+disableFlag flag condVars =
+   condVars & flagsL %~ HM.insert flag False
+
+
+-- | Evaluate the 'Condition' using the 'CondVars'.
+eval :: CondVars -> Condition PD.ConfVar -> Bool
+eval condVars = eval'
+   where
+      eval' (Var var)    = hasVar var
+      eval' (Lit val)    = val
+      eval' (CNot c)     = not $ eval' c
+      eval' (COr c1 c2)  = eval' c1 || eval' c2
+      eval' (CAnd c1 c2) = eval' c1 && eval' c2
+
+      hasVar (PD.OS osVar)     = osVar == os condVars
+      hasVar (PD.Arch archVar) = archVar == arch condVars
+      hasVar (PD.Impl cflavor vrange)
+         | Just version <- compilerVersion condVars
+         = cflavor == compilerFlavor condVars && version `withinRange` vrange
+
+         | otherwise
+         = cflavor == compilerFlavor condVars
+
+      hasVar (PD.Flag (PD.FlagName name))
+         | Just v <- HM.lookup name (flags condVars)
+         = v
+
+         | otherwise
+         = False
diff --git a/lib/CabalLenses/Package.hs b/lib/CabalLenses/Package.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/Package.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+-- |
+-- Lenses for several data types of the 'Distribution.Package' module.
+-- All lenses are named after their field names with a 'L' appended.
+
+module CabalLenses.Package where
+
+import Distribution.Package (PackageName(..) , PackageIdentifier(..) , Dependency(..))
+import Distribution.Version (VersionRange)
+import Control.Lens (makeLensesFor, Lens', lens)
+
+
+pkgNameString :: Lens' PackageName String
+pkgNameString = lens getString setString
+   where
+      getString (PackageName str) = str
+      setString _                 = PackageName
+
+
+makeLensesFor [ ("pkgName"   , "pkgNameL")
+              , ("pkgVersion", "pkgVersionL")
+              ] ''PackageIdentifier
+
+
+depPackageName :: Lens' Dependency PackageName
+depPackageName = lens getPkgName setPkgName
+   where
+      getPkgName (Dependency pkgName _)          = pkgName
+      setPkgName (Dependency _ range) newPkgName = Dependency newPkgName range
+
+
+depVersionRange :: Lens' Dependency VersionRange
+depVersionRange = lens getRange setRange
+   where
+      getRange (Dependency _ range)   = range
+      setRange (Dependency pkgName _) = Dependency pkgName
diff --git a/lib/CabalLenses/PackageDescription.hs b/lib/CabalLenses/PackageDescription.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/PackageDescription.hs
@@ -0,0 +1,103 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+-- |
+-- Lenses for several data types of the 'Distribution.PackageDescription' module.
+-- All lenses are named after their field names with a 'L' appended.
+
+module CabalLenses.PackageDescription where
+
+import Distribution.PackageDescription ( GenericPackageDescription(..)
+                                       , PackageDescription(..)
+                                       , Library(..)
+                                       , Executable(..)
+                                       , TestSuite(..)
+                                       , Benchmark(..)
+                                       , BuildInfo(..)
+                                       , CondTree(..)
+                                       )
+import Control.Lens (makeLensesFor)
+
+
+makeLensesFor [ ("packageDescription", "packageDescriptionL")
+              , ("genPackageFlags"   , "genPackageFlagsL")
+              , ("condLibrary"       , "condLibraryL")
+              , ("condExecutables"   , "condExecutablesL")
+              , ("condTestSuites"    , "condTestSuitesL")
+              , ("condBenchmarks"    , "condBenchmarksL")
+              ] ''GenericPackageDescription
+
+
+makeLensesFor [ ("package"       , "packageL")
+              , ("license"       , "licenseL")
+              , ("licenseFile"   , "licenseFileL")
+              , ("copyright"     , "copyrightL")
+              , ("maintainer"    , "maintainerL")
+              , ("author"        , "authorL")
+              , ("stability"     , "stabilityL")
+              , ("testedWith"    , "testedWithL")
+              , ("homepage"      , "homepageL")
+              , ("pkgUrl"        , "pkgUrlL")
+              , ("bugReports"    , "bugReports")
+              , ("sourceRepos"   , "sourceReposL")
+              , ("synopsis"      , "synopsisL")
+              , ("description"   , "descriptionL")
+              , ("category"      , "categoryL")
+              , ("customFieldsPD", "customFieldsPDL")
+              , ("buildDepends"  , "buildDependsL")
+              , ("specVersionRaw", "specVersionRawL")
+              , ("buildType"     , "buildTypeL")
+              , ("library"       , "libraryL")
+              , ("executables"   , "executablesL")
+              , ("testSuites"    , "testSuitesL")
+              , ("benchmarks"    , "benchmarksL")
+              , ("dataFiles"     , "dataFilesL")
+              , ("dataDir"       , "dataDirL")
+              , ("extraSrcFiles" , "extraSrcFilesL")
+              , ("extraTmpFiles" , "extraTmpFilesL")
+              ] ''PackageDescription
+
+
+makeLensesFor [ ("exposedModules", "exposedModulesL")
+              , ("libExposed"    , "libExposedL")
+              , ("libBuildInfo"  , "libBuildInfoL")
+              ] ''Library
+
+
+makeLensesFor [ ("exeName"   , "exeNameL")
+              , ("modulePath", "modulePathL")
+              , ("buildInfo" , "buildInfoL")
+              ] ''Executable
+
+
+makeLensesFor [ ("testName"     , "testNameL")
+              , ("testInterface", "testInterfaceL")
+              , ("testBuildInfo", "testBuildInfoL")
+              , ("testEnabled"  , "testEnabledL")
+              ] ''TestSuite
+
+
+makeLensesFor [ ("benchmarkName", "benchmarkNameL")
+              , ("benchmarkInterface", "benchmarkInterfaceL")
+              , ("benchmarkBuildInfo", "benchmarkBuildInfoL")
+              , ("benchmarkEnabled"  , "benchmarkEnabledL")
+              ] ''Benchmark
+
+
+makeLensesFor [ ("hsSourceDirs"      , "hsSourceDirsL")
+              , ("options"           , "optionsL")
+              , ("defaultLanguage"   , "defaultLanguageL")
+              , ("cppOptions"        , "cppOptionsL")
+              , ("cSources"          , "cSourcesL")
+              , ("ccOptions"         , "ccOptionsL")
+              , ("extraLibDirs"      , "extraLibDirsL")
+              , ("extraLibs"         , "extraLibsL")
+              , ("ldOptions"         , "ldOptionsL")
+              , ("includeDirs"       , "includeDirsL")
+              , ("includes"          , "includesL")
+              ] ''BuildInfo
+
+
+makeLensesFor [ ("condTreeData"       , "condTreeDataL")
+              , ("condTreeConstraints", "condTreeConstraintsL")
+              , ("condTreeComponents" , "condTreeComponentsL")
+              ] ''CondTree
diff --git a/lib/CabalLenses/Section.hs b/lib/CabalLenses/Section.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/Section.hs
@@ -0,0 +1,26 @@
+
+module CabalLenses.Section
+   ( Section(..)
+   , allSections
+   ) where
+
+import Distribution.PackageDescription (GenericPackageDescription(..))
+
+type Name = String
+
+-- | A section of the cabal file.
+data Section = Library
+             | Executable Name
+             | TestSuite Name
+             | Benchmark Name
+             deriving (Show, Eq)
+
+
+-- | All sections defined in 'GenericPackageDescription'.
+allSections :: GenericPackageDescription -> [Section]
+allSections pkgDescr =
+   concat [ maybe [] (const [Library]) (condLibrary pkgDescr)
+          , map (Executable . fst) (condExecutables pkgDescr)
+          , map (TestSuite . fst) (condTestSuites pkgDescr)
+          , map (Benchmark . fst) (condBenchmarks pkgDescr)
+          ]
diff --git a/lib/CabalLenses/Traversals/BuildInfo.hs b/lib/CabalLenses/Traversals/BuildInfo.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/Traversals/BuildInfo.hs
@@ -0,0 +1,32 @@
+{-# LANGUAGE Rank2Types #-}
+
+module CabalLenses.Traversals.BuildInfo
+   ( buildInfo
+   , buildInfoIf
+   ) where
+
+import CabalLenses.Section (Section(..))
+import CabalLenses.Traversals.Internal (traverseData, traverseDataIf)
+import CabalLenses.CondVars (CondVars)
+import CabalLenses.PackageDescription
+import Control.Lens
+import Distribution.PackageDescription (GenericPackageDescription, BuildInfo)
+
+
+-- | A traversal for all 'BuildInfo' of 'Section'.
+buildInfo :: Section -> Traversal' GenericPackageDescription BuildInfo
+buildInfo Library           = condLibraryL . _Just . traverseData . libBuildInfoL
+buildInfo (Executable name) = condExecutablesL . traverse . having name . _2 . traverseData . buildInfoL
+buildInfo (TestSuite name)  = condTestSuitesL . traverse . having name . _2 . traverseData . testBuildInfoL
+buildInfo (Benchmark name)  = condBenchmarksL . traverse . having name . _2 . traverseData . benchmarkBuildInfoL
+
+
+-- | A traversal for the 'BuildInfo' of 'Section' that match 'CondVars'.
+buildInfoIf :: CondVars -> Section -> Traversal' GenericPackageDescription BuildInfo
+buildInfoIf condVars Library           = condLibraryL . _Just . traverseDataIf condVars . libBuildInfoL
+buildInfoIf condVars (Executable name) = condExecutablesL . traverse . having name . _2 . traverseDataIf condVars . buildInfoL
+buildInfoIf condVars (TestSuite name)  = condTestSuitesL . traverse . having name . _2 . traverseDataIf condVars . testBuildInfoL
+buildInfoIf condVars (Benchmark name)  = condBenchmarksL . traverse . having name . _2 . traverseDataIf condVars . benchmarkBuildInfoL
+
+
+having name = filtered ((== name) . fst) 
diff --git a/lib/CabalLenses/Traversals/Dependency.hs b/lib/CabalLenses/Traversals/Dependency.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/Traversals/Dependency.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE Rank2Types #-}
+
+module CabalLenses.Traversals.Dependency
+   ( dependency
+   , dependencyIf
+   ) where
+
+import CabalLenses.Section (Section(..))
+import CabalLenses.Traversals.Internal (traverseDependency, traverseDependencyIf)
+import CabalLenses.CondVars (CondVars)
+import CabalLenses.PackageDescription
+import Control.Lens
+import Distribution.PackageDescription (GenericPackageDescription)
+import Distribution.Package (Dependency)
+
+
+-- | A traversal for all 'Dependency' of 'Section'.
+dependency :: Section -> Traversal' GenericPackageDescription Dependency
+dependency Library           = condLibraryL . _Just . traverseDependency
+dependency (Executable name) = condExecutablesL . traverse . having name . _2 . traverseDependency
+dependency (TestSuite name)  = condTestSuitesL . traverse . having name . _2 . traverseDependency
+dependency (Benchmark name)  = condBenchmarksL . traverse . having name . _2 . traverseDependency
+
+
+-- | A traversal for the 'Dependency' of 'Section' that match 'CondVars'.
+dependencyIf :: CondVars -> Section -> Traversal' GenericPackageDescription Dependency
+dependencyIf condVars Library           = condLibraryL . _Just . traverseDependencyIf condVars
+dependencyIf condVars (Executable name) = condExecutablesL . traverse . having name . _2 . traverseDependencyIf condVars
+dependencyIf condVars (TestSuite name)  = condTestSuitesL . traverse . having name . _2 . traverseDependencyIf condVars
+dependencyIf condVars (Benchmark name)  = condBenchmarksL . traverse . having name . _2 . traverseDependencyIf condVars
+
+
+having name = filtered ((== name) . fst) 
diff --git a/lib/CabalLenses/Traversals/Internal.hs b/lib/CabalLenses/Traversals/Internal.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/Traversals/Internal.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE TupleSections, Rank2Types #-}
+
+module CabalLenses.Traversals.Internal
+   ( traverseDataIf
+   , traverseData
+   , traverseDependencyIf
+   , traverseDependency
+   ) where
+
+import CabalLenses.CondVars (CondVars)
+import qualified CabalLenses.CondVars as CV
+import Distribution.PackageDescription (CondTree(..), ConfVar)
+import Distribution.Package (Dependency(..))
+import Data.Traversable (traverse)
+import Control.Applicative (Applicative, pure, (<$>), (<*>))
+import Control.Lens (Traversal')
+
+type CondTree' a = CondTree ConfVar [Dependency] a
+
+
+-- | A traversal for all 'condTreeData' of 'CondTree' that match 'CondVars'.
+traverseDataIf :: CondVars -> Traversal' (CondTree' dat) dat
+traverseDataIf condVars f (CondNode dat constr comps) =
+   CondNode <$> f dat
+            <*> pure constr
+            <*> (traverse . traverseCompIf condVars) f comps  
+   where
+      traverseCompIf condVars f (cond, ifComp, elseComp) =
+         (,,) <$> pure cond <*> ifComp' <*> elseComp'
+         where
+            ifComp' | condMatches = traverseDataIf condVars f ifComp
+                    | otherwise   = pure ifComp
+
+            elseComp' | condMatches = pure elseComp
+                      | otherwise   = (traverse . traverseDataIf condVars) f elseComp
+
+            condMatches = CV.eval condVars cond
+
+
+-- | A traversal for all 'condTreeData' (the if and else branches) of the 'CondTree'.
+traverseData :: Traversal' (CondTree' dat) dat
+traverseData f (CondNode dat constr comps) =
+   CondNode <$> f dat
+            <*> pure constr
+            <*> (traverse . traverseComp) f comps
+   where
+      traverseComp f (cond, ifComp, elseComp) =
+         (,,) <$> pure cond <*> traverseData f ifComp <*> (traverse . traverseData) f elseComp
+
+
+-- | A traversal for all 'condTreeConstraints' of 'CondTree' that match 'CondVars'.
+traverseDependencyIf :: CondVars -> Traversal' (CondTree' dat) Dependency
+traverseDependencyIf condVars f (CondNode dat constr comps) =
+   CondNode <$> pure dat
+            <*> traverse f constr
+            <*> (traverse . traverseCompIf condVars) f comps  
+   where
+      traverseCompIf condVars f (cond, ifComp, elseComp) =
+         (,,) <$> pure cond <*> ifComp' <*> elseComp'
+         where
+            ifComp' | condMatches = traverseDependencyIf condVars f ifComp
+                    | otherwise   = pure ifComp
+
+            elseComp' | condMatches = pure elseComp
+                      | otherwise   = (traverse . traverseDependencyIf condVars) f elseComp
+
+            condMatches = CV.eval condVars cond
+
+
+-- | A traversal for all 'condTreeConstraints' (the if and else branches) of the 'CondTree'.
+traverseDependency :: Traversal' (CondTree' dat) Dependency
+traverseDependency f (CondNode dat constr comps) =
+   CondNode <$> pure dat
+            <*> traverse f constr
+            <*> (traverse . traverseComp) f comps
+   where
+      traverseComp f (cond, ifComp, elseComp) =
+         (,,) <$> pure cond <*> traverseDependency f ifComp <*> (traverse . traverseDependency) f elseComp
diff --git a/lib/CabalLenses/Version.hs b/lib/CabalLenses/Version.hs
new file mode 100644
--- /dev/null
+++ b/lib/CabalLenses/Version.hs
@@ -0,0 +1,15 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+-- |
+-- Lenses for several data types of the 'Distribution.Version' module.
+-- All lenses are named after their field names with a 'L' appended.
+
+module CabalLenses.Version where
+
+import Distribution.Version (Version(..))
+import Control.Lens (makeLensesFor)
+
+
+makeLensesFor [ ("versionBranch", "versionBranchL")
+              , ("versionTags"  , "versionTagsL")
+              ] ''Version
