1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE RecordWildCards #-}
4module Main ( main ) where
6import Cabal2Nix.Flags ( configureCabalFlags )
7import Cabal2Nix.Generate ( cabal2nix' )
8import Cabal2Nix.HackageGit ( readHackage, Hackage )
9import Cabal2Nix.Package
10import Cabal2Nix.Version
11import Control.Arrow ( second )
13import Control.Monad.Par.Combinator
14import Control.Monad.Par.IO
15import Control.Monad.Trans ( liftIO )
18import Data.Map.Strict ( Map )
19import qualified Data.Map.Strict as Map
22import Data.Set ( Set )
23import qualified Data.Set as Set
24import Distribution.Compiler
25import Distribution.Nixpkgs.Fetch
26import Distribution.Nixpkgs.Haskell
27import Distribution.Nixpkgs.Meta
28import Distribution.Nixpkgs.PackageMap
29import Distribution.Nixpkgs.Util.PrettyPrinting hiding ( attr, (<>) )
30import Distribution.Package
31import Distribution.PackageDescription hiding ( options, buildDepends, extraLibs, buildTools )
32import Distribution.PackageDescription.Configuration
33import Distribution.System
34import Distribution.Text
35import Distribution.Version
37import Language.Nix.Identifier
38import Language.Nix.Path
39import Options.Applicative
42type Nixpkgs = PackageMap -- Map String (Set [String])
43type PackageSet = Map String Version
44type PackageMultiSet = Map String (Set Version)
46type Constraint = Dependency
48resolveConstraint :: Constraint -> Hackage -> Version
49resolveConstraint c = fromMaybe (error ("constraint " ++ display c ++ " cannot be resolved in Hackage")) .
52resolveConstraint' :: Constraint -> Hackage -> Maybe Version
53resolveConstraint' (Dependency (PackageName name) vrange) hackage | Set.null vs = Nothing
54 | otherwise = Just (Set.findMax vs)
55 where vs = Set.filter (`withinRange` vrange) (Map.keysSet (hackage Map.! name))
57satisfiesConstraint :: PackageIdentifier -> Constraint -> Bool
58satisfiesConstraint (PackageIdentifier pn v) (Dependency cn vr) = (pn /= cn) || (v `withinRange` vr)
60satisfiesConstraints :: PackageIdentifier -> [Constraint] -> Bool
61satisfiesConstraints p = all (satisfiesConstraint p)
63data Configuration = Configuration
65 -- |Target architecture. Used by 'finalizePackageDescription' to
66 -- choose appropriate flags and dependencies.
69 -- |Target compiler. Used by 'finalizePackageDescription' to choose
70 -- appropriate flags and dependencies.
71 , compilerInfo :: CompilerInfo
73 -- |Core packages found on Hackageg
74 , corePackages :: [PackageIdentifier]
76 -- |Core packages not found on Hackage.
77 , hardCorePackages :: [PackageIdentifier]
79 -- |These packages replace the latest respective version during
80 -- dependency resolution.
81 , defaultPackageOverrides :: [Constraint]
83 -- |These packages are added to the generated set, but the play no
84 -- role during dependency resolution.
85 , extraPackages :: [Constraint]
87 -- |These packages have not succeeded a build yet, so we give them an
88 -- empty meta.hydraPlatforms attribute to avoid cluttering our Hydra
89 -- output with lots of broken builds.
90 , brokenPackages :: Set PackageName
95 { hackageRepository :: FilePath
96 , nixpkgsRepository :: FilePath
100options :: Parser Options
102 <$> strOption (long "hackage" <> help "path to Hackage git repository" <> value "hackage" <> showDefault <> metavar "PATH")
103 <*> strOption (long "nixpkgs" <> help "path to Nixpkgs repository" <> value "<nixpkgs>" <> showDefault <> metavar "PATH")
105pinfo :: ParserInfo Options
108 <*> infoOption ("hackage2nix " ++ version) (long "version" <> help "Show version number")
112 <> header "hackage2nix converts a Hackage database into a haskell-packages.nix file."
117 Options {..} <- execParser pinfo
119 hackage <- readHackage hackageRepository
120 nixpkgs <- readNixpkgPackageMap nixpkgsRepository (Just (create path ["pkgs"]))
121 preferredVersions <- readPreferredVersions (hackageRepository </> "preferred-versions")
122 let fixup = Map.delete "acme-everything" -- TODO: https://github.com/NixOS/cabal2nix/issues/164
123 . Map.delete "som" -- TODO: https://github.com/NixOS/cabal2nix/issues/164
124 . Map.delete "type" -- TODO: https://github.com/NixOS/cabal2nix/issues/163
125 . Map.delete "dictionary-sharing" -- TODO: https://github.com/NixOS/cabal2nix/issues/175
126 . Map.filter (/= Map.empty)
127 . Map.mapWithKey (enforcePreferredVersions preferredVersions)
128 runParIO $ generatePackageSet defaultConfiguration (fixup hackage) nixpkgs
130enforcePreferredVersions :: [Constraint] -> String -> Map Version GenericPackageDescription
131 -> Map Version GenericPackageDescription
132enforcePreferredVersions cs pkg = Map.filterWithKey (\v _ -> PackageIdentifier (PackageName pkg) v `satisfiesConstraints` cs)
134generatePackageSet :: Configuration -> Hackage -> Nixpkgs -> ParIO ()
135generatePackageSet config hackage nixpkgs = do
137 corePackageSet :: PackageSet
138 corePackageSet = Map.fromList [ (name, v) | PackageIdentifier (PackageName name) v <- corePackages config ++ hardCorePackages config ]
140 latestVersionSet :: PackageSet
141 latestVersionSet = Map.map (Set.findMax . Map.keysSet) hackage
143 defaultPackageOverridesSet :: PackageSet
144 defaultPackageOverridesSet = Map.fromList [ (name, resolveConstraint c hackage) | c@(Dependency (PackageName name) _) <- defaultPackageOverrides config ]
146 generatedDefaultPackageSet :: PackageSet
147 generatedDefaultPackageSet = (defaultPackageOverridesSet `Map.union` latestVersionSet) `Map.difference` corePackageSet
149 latestCorePackageSet :: PackageSet
150 latestCorePackageSet = latestVersionSet `Map.intersection` corePackageSet
152 latestOverridePackageSet :: PackageSet
153 latestOverridePackageSet = latestVersionSet `Map.intersection` defaultPackageOverridesSet
155 extraPackageSet :: PackageMultiSet
156 extraPackageSet = Map.unionsWith Set.union
157 [ Map.singleton name (Set.singleton (resolveConstraint c hackage)) | c@(Dependency (PackageName name) _) <- extraPackages config ]
159 db :: PackageMultiSet
160 db = Map.unionsWith Set.union [ Map.map Set.singleton generatedDefaultPackageSet
161 , Map.map Set.singleton latestCorePackageSet
162 , Map.map Set.singleton latestOverridePackageSet
166 knownIdentifierSet :: Set Identifier
167 knownIdentifierSet = Set.map (create ident) (Set.union (Map.keysSet hackage) (Map.keysSet corePackageSet))
169 resolver :: Dependency -> Bool
170 resolver (Dependency (PackageName name) vrange)
171 | Just v <- Map.lookup name corePackageSet = v `withinRange` vrange
172 | Just v <- Map.lookup name generatedDefaultPackageSet = v `withinRange` vrange
175 liftIO $ do putStrLn "/* hackage-packages.nix is an auto-generated file -- DO NOT EDIT! */"
177 putStrLn "{ pkgs, stdenv, callPackage }:"
181 pkgs <- flip parMapM (Map.toAscList db) $ \(name, vs) -> do
182 defs <- forM (Set.toAscList vs) $ \pkgversion -> do
183 let -- TODO: Include list of broken dependencies in the generated output.
184 descr = hackage Map.! name Map.! pkgversion
185 (missingDeps, _, drv') = cabal2nix resolver descr
187 haskellDependencies :: Set Identifier
188 haskellDependencies = Set.unions [ drv'^.x.haskell | x <- [libraryDepends,executableDepends,testDepends] ]
190 systemDependencies :: Set Identifier
191 systemDependencies = Set.unions [ drv'^.x.y | x <- [libraryDepends,executableDepends,testDepends], y <- [system,pkgconfig] ]
193 haskellOrSystemDependencies :: Set Identifier
194 haskellOrSystemDependencies = Set.unions [ drv'^.x.tool | x <- [libraryDepends,executableDepends,testDepends] ]
196 missing :: Set Identifier
197 missing = Set.filter (`Set.notMember` knownIdentifierSet) haskellDependencies
199 buildInputs :: Map Identifier (Maybe Path)
200 buildInputs = Map.unions
201 [ Map.fromList [ (n, Nothing) | n <- Set.toList missing ]
202 , Map.fromList [ (n, resolveNixpkgsIdentifier nixpkgs n) | n <- Set.toAscList systemDependencies ]
203 , Map.fromList [ (n, resolveHackageThenNixpkgsIdentifier nixpkgs hackage n) | n <- Set.toAscList haskellOrSystemDependencies ]
206 systemOverrides :: Doc
207 systemOverrides = fsep (map (uncurry formatOverride) (Map.toAscList buildInputs))
209 formatOverride :: Identifier -> Maybe Path -> Doc
210 formatOverride n Nothing = space <> pPrint n <> text " = null;" -- missing dependency
211 formatOverride n (Just p) = case view path p of
212 [] -> error ("internal error: " ++ show n ++ "resolved to empty path!")
213 ["self"] -> mempty -- callPackage finds this package automatically
214 _ -> (text " inherit" <+> parens (pPrint p) <+> pPrint n) <> semi
217 overrides = systemOverrides
219 attr | Just v <- Map.lookup name generatedDefaultPackageSet, v == pkgversion = name
220 | otherwise = name ++ '_' : [ if c == '.' then '_' else c | c <- display pkgversion ]
223 sha256 | Just x <- lookup "X-Package-SHA256" (customFieldsPD (packageDescription descr)) = x
224 | otherwise = error $ display (packageId descr) ++ " has no hash"
226 srcSpec <- liftIO $ sourceFromHackage (Certain sha256) (name ++ "-" ++ display pkgversion)
228 let drv = drv' & src .~ srcSpec
229 & jailbreak .~ (not (null missingDeps) && (name /= "jailbreak-cabal")) -- Dependency constraints aren't fulfilled
230 & metaSection . broken .~ not (Set.null missing) -- Missing Haskell dependencies!
231 & metaSection.hydraPlatforms .~ (if PackageName name `Set.member` brokenPackages config
232 then Set.singleton "stdenv.lib.platforms.none"
233 else drv'^.metaSection.hydraPlatforms)
235 return $ nest 2 $ hang (string attr <+> equals <+> text "callPackage") 2 (parens (pPrint drv)) <+> (braces overrides <> semi)
236 return (intercalate "\n\n" (map render defs))
238 liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
239 liftIO $ putStrLn "}"
241resolveHackageThenNixpkgsIdentifier :: Nixpkgs -> Hackage -> Identifier -> Maybe Path
242resolveHackageThenNixpkgsIdentifier nixpkgs hackage name
243 | Just _ <- Map.lookup (view ident name) hackage = Just (create path ["self"])
244 | p@(Just _) <- resolveNixpkgsIdentifier nixpkgs name = p
245 | otherwise = Nothing
247resolveNixpkgsIdentifier :: Nixpkgs -> Identifier -> Maybe Path
248resolveNixpkgsIdentifier nixpkgs name
249 | name `elem` ["clang","lldb","llvm"] = Just (create path ["self","llvmPackages"])
250 | Just paths <- Map.lookup name nixpkgs = getShortestPath (Set.toList (paths `Set.intersection` goodScopes))
251 | otherwise = Nothing
253goodScopes :: Set Path
254goodScopes = Set.fromList ((map (create path . ("pkgs":))) [[], ["xlibs"], ["gnome"], ["gnome3"], ["kde4"]])
256getShortestPath :: [Path] -> Maybe Path
257getShortestPath [] = Nothing
258getShortestPath ps = Just (minimumBy (on compare (view (path . to length))) ps)
260cabal2nix :: (Dependency -> Bool) -> GenericPackageDescription -> ([Dependency], FlagAssignment, Derivation)
261cabal2nix resolver cabal = (missingDeps, flags, drv)
263 drv = cabal2nix' descr
265 Right (descr, flags) = finalize (if null missingDeps then resolver else const True) cabal
267 missingDeps :: [Dependency]
268 missingDeps = either id (const []) (finalize resolver cabal')
270 finalize :: (Dependency -> Bool) -> GenericPackageDescription -> Either [Dependency] (PackageDescription, FlagAssignment)
271 finalize resolver' = finalizePackageDescription
272 (configureCabalFlags (package (packageDescription cabal)))
274 (platform defaultConfiguration)
275 (compilerInfo defaultConfiguration)
276 [] -- no additional constraints
278 -- A variant of the cabal file that has all test suites enabled to ensure
279 -- that their dependencies are recognized by finalizePackageDescription.
280 cabal' :: GenericPackageDescription
281 cabal' = cabal { condTestSuites = flaggedTests }
283 flaggedTests :: [(String, CondTree ConfVar [Dependency] TestSuite)]
284 flaggedTests = map (second (mapTreeData enableTest)) (condTestSuites cabal)
286 enableTest :: TestSuite -> TestSuite
287 enableTest t = t { testEnabled = True }
289readPreferredVersions :: FilePath -> IO [Constraint]
290readPreferredVersions p = mapMaybe parsePreferredVersionsLine . lines <$> readFile p
292parsePreferredVersionsLine :: String -> Maybe Constraint
293parsePreferredVersionsLine ('-':'-':_) = Nothing
294parsePreferredVersionsLine l = case simpleParse l of
296 Nothing -> error ("invalid preferred-versions line: " ++ show l)
298defaultConfiguration :: Configuration
299defaultConfiguration = Configuration
300 { platform = Platform X86_64 Linux
301 , compilerInfo = unknownCompilerInfo (CompilerId GHC (Version [7,10,2] [])) NoAbiTag
303 , defaultPackageOverrides = map (\s -> fromMaybe (error (show s ++ " is not a valid override selector")) (simpleParse s))
307 , corePackages = map (\s -> fromMaybe (error (show s ++ " is not a valid core package")) (simpleParse s))
312 , "bytestring-0.10.6.0"
313 , "containers-0.5.6.2"
315 , "directory-1.2.2.0"
318 , "haskeline-0.7.2.1"
321 , "integer-gmp-1.0.0.0"
324 , "template-haskell-2.10.0.0"
327 , "transformers-0.4.2.0"
332 , hardCorePackages = map (\s -> fromMaybe (error (show s ++ " is not a valid core package")) (simpleParse s))
333 [ "bin-package-db-0.0.0.0"
338 , extraPackages = map (\s -> fromMaybe (error (show s ++ " is not a valid extra package selector")) (simpleParse s))
339 [ "aeson < 0.8" -- newer versions don't work with GHC 6.12.3
340 , "Cabal == 1.18.*" -- required for cabal-install et al on old GHC versions
341 , "Cabal == 1.20.*" -- required for cabal-install et al on old GHC versions
342 , "cabal-install == 1.18.*" -- required for ghc-mod on 7.8.x
343 , "conduit < 1.2.4.2" -- newer versions trigger non-deterministic ID bugs in GHC versions prior to 7.10.x
344 , "containers < 0.5" -- required to build alex with GHC 6.12.3
345 , "control-monad-free < 0.6" -- newer versions don't compile with anything but GHC 7.8.x
346 , "deepseq == 1.3.0.1" -- required to build Cabal with GHC 6.12.3
347 , "descriptive < 0.1" -- required for structured-haskell-mode-1.0.8
348 , "gloss < 1.9.3" -- new versions don't compile with GHC 7.8.x
349 , "haddock-api < 2.16" -- required on GHC 7.8.x
350 , "haskell-src-exts < 1.16" -- required for structured-haskell-mode-1.0.8
351 , "mtl < 2.2" -- newer versions require transformers > 0.4.x, which we cannot provide in GHC 7.8.x
352 , "mtl-prelude < 2" -- required for to build postgrest on mtl 2.1.x platforms
353 , "parallel == 3.2.0.3" -- newer versions don't work with GHC 6.12.3
354 , "primitive == 0.5.1.*" -- required to build alex with GHC 6.12.3
355 , "QuickCheck < 2" -- required by test-framework-quickcheck and its users
356 , "seqid < 0.2" -- newer versions depend on transformers 0.4.x which we cannot provide in GHC 7.8.x
357 , "seqid-streams < 0.2" -- newer versions depend on transformers 0.4.x which we cannot provide in GHC 7.8.x
358 , "split < 0.2" -- newer versions don't work with GHC 6.12.3
359 , "tar < 0.4.2.0" -- later versions don't work with GHC < 7.6.x
360 , "vector < 0.10.10" -- newer versions don't work with GHC 6.12.3
361 , "zlib < 0.6" -- newer versions break cabal-install
364 , brokenPackages = Set.fromList $ map PackageName
368 , "abstract-par-accelerate"
371 , "accelerate-arithmetic"
373 , "accelerate-fourier"
375 , "accelerate-utility"
378 , "AC-EasyRaster-GTK"
383 , "acme-numbersystem"
384 , "acme-schoenfinkel"
393 , "Adaptive-Blaisorblade"
394 , "adaptive-containers"
399 , "adobe-swatch-exchange"
401 , "adp-multi-monadiccp"
407 , "AERN-Real-Interval"
420 , "aivika-experiment-diagrams"
421 , "aivika-transformers"
440 , "android-lint-summary"
441 , "AndroidViewHierarchyImporter"
453 , "apiary-purescript"
490 , "atlassian-connect-core"
491 , "atlassian-connect-descriptor"
496 , "attoparsec-iteratee"
498 , "attoparsec-text-enumerator"
514 , "aws-cloudfront-signer"
516 , "aws-elastic-transcoder"
517 , "aws-kinesis-reshard"
520 , "aws-sdk-text-converter"
521 , "aws-sdk-xml-unordered"
524 , "azure-service-api"
531 , "bamboo-plugin-highlight"
532 , "bamboo-plugin-photo"
533 , "bamboo-theme-blueprint"
534 , "bamboo-theme-mini-html5"
547 , "bed-and-breakfast"
555 , "bidirectionalization-combined"
561 , "billeksah-services"
564 , "binary-indexed-tree"
565 , "binary-protocol-zmq"
570 , "bindings-apr-util"
585 , "bindings-libstemmer"
587 , "bindings-linux-videodev2"
588 , "bindings-mpdecimal"
600 , "BiobaseTrainingData"
626 , "blaze-html-contrib"
627 , "blaze-html-hexpat"
629 , "blaze-textual-native"
632 , "BlogLiterately-diagrams"
638 , "boolean-normal-forms"
666 , "bytestring-rematch"
671 , "cabal-constraints"
676 , "cabal-install-bundle"
677 , "cabal-install-ghc72"
678 , "cabal-install-ghc74"
695 , "call-haskell-from-anything"
705 , "casadi-bindings-control"
706 , "casadi-bindings-core"
707 , "casadi-bindings-internal"
708 , "casadi-bindings-ipopt-interface"
709 , "casadi-bindings-snopt-interface"
719 , "categorical-algebra"
727 , "CC-delcont-ref-tf"
729 , "cctools-workqueue"
731 , "ceilometer-common"
732 , "cereal-enumerator"
743 , "chalkboard-viewer"
767 , "citeproc-hs-pandoc-filter"
777 , "clash-prelude-quickcheck"
778 , "clash-systemverilog"
785 , "clckwrks-plugin-bugs"
786 , "clckwrks-plugin-ircbot"
787 , "clckwrks-plugin-media"
788 , "clckwrks-plugin-page"
789 , "clckwrks-theme-bootstrap"
790 , "clckwrks-theme-clckwrks"
791 , "clckwrks-theme-geo-bootstrap"
800 , "cloudfront-signer"
815 , "cnc-spec-compiler"
818 , "Codec-Image-DevIL"
824 , "coinbase-exchange"
830 , "collections-base-instances"
834 , "combinat-diagrams"
835 , "combinatorial-problems"
836 , "combinator-interactive"
841 , "commsec-keyexchange"
852 , "computational-algebra"
864 , "conduit-audio-lame"
865 , "conduit-audio-samplerate"
867 , "conduit-network-stream"
868 , "conduit-resumablesink"
873 , "const-math-ghc-plugin"
874 , "constrained-categories"
875 , "constructive-algebra"
884 , "control-monad-attempt"
885 , "control-monad-exception-mtl"
886 , "control-monad-failure"
887 , "control-monad-failure-mtl"
888 , "Control-Monad-MultiPass"
889 , "Control-Monad-ST2"
890 , "contstuff-monads-tf"
891 , "contstuff-transformers"
892 , "convertible-ascii"
899 , "copilot-libraries"
908 , "coroutine-iteratee"
911 , "couchdb-enumerator"
935 , "crf-chain1-constrained"
936 , "crf-chain2-generic"
941 , "crypto-cipher-benchmarks"
946 , "csound-expression"
947 , "csound-expression-opcodes"
948 , "csound-expression-typed"
978 , "darcs-buildpackage"
1020 , "ddc-source-tetra"
1023 , "dead-simple-json"
1035 , "definitive-filesystem"
1036 , "definitive-graphics"
1037 , "definitive-parser"
1038 , "definitive-reactive"
1039 , "definitive-sound"
1050 , "derivation-trees"
1061 , "diagrams-builder"
1063 , "diagrams-haddock"
1069 , "dice-entropy-conduit"
1074 , "DifferentialEvolution"
1075 , "digestive-functors-hsp"
1081 , "direct-binary-files"
1082 , "directed-cubical"
1091 , "distributed-process-async"
1092 , "distributed-process-azure"
1093 , "distributed-process-client-server"
1094 , "distributed-process-execution"
1095 , "distributed-process-extras"
1096 , "distributed-process-platform"
1097 , "distributed-process-registry"
1098 , "distributed-process-supervisor"
1099 , "distributed-process-task"
1100 , "distributed-process-tests"
1101 , "distributed-process-zookeeper"
1103 , "distribution-plot"
1106 , "DnaProteinAlignment"
1115 , "doctest-discover"
1116 , "doctest-discover-configurator"
1119 , "download-media-content"
1163 , "DysFRP-Craftwerk"
1181 , "effective-aspects"
1182 , "effective-aspects-mzv"
1187 , "eibd-client-simple"
1204 , "embeddock-example"
1217 , "equational-reasoning"
1231 , "Eternal10Seconds"
1233 , "ethereum-client-haskell"
1234 , "ethereum-merkle-patricia-db"
1241 , "every-bit-counts"
1246 , "expat-enumerator"
1248 , "explicit-sharing"
1250 , "exposed-containers"
1254 , "extended-categories"
1273 , "feldspar-compiler"
1274 , "feldspar-language"
1277 , "FermatsLastMargin"
1280 , "ffmpeg-tutorials"
1288 , "filesystem-conduit"
1289 , "filesystem-enumerator"
1290 , "Finance-Quote-Yahoo"
1291 , "Finance-Treasury"
1295 , "FirstOrderTheory"
1299 , "fixed-point-vector"
1300 , "fixed-point-vector-space"
1302 , "fixed-storable-array"
1303 , "fix-parser-simple"
1305 , "fix-symbols-gitit"
1307 , "flexiwrap-smallcheck"
1316 , "flowlocks-framework"
1320 , "foldl-incremental"
1326 , "font-opengl-basic4x6"
1349 , "free-operational"
1353 , "free-theorems-counterexamples"
1354 , "free-theorems-seq"
1355 , "free-theorems-seq-webui"
1356 , "free-theorems-webui"
1367 , "functional-arrow"
1368 , "function-combine"
1379 , "gc-monitoring-wai"
1389 , "GeneralTicTacToe"
1392 , "genericserialize"
1393 , "generic-storable"
1404 , "GeomPredicates-SSE"
1409 , "ghc-events-analyze"
1410 , "ghc-events-parallel"
1438 , "gladexml-accessor"
1457 , "google-html5-slide"
1458 , "google-mail-filters"
1467 , "GPipe-TextureLoad"
1472 , "grapefruit-examples"
1474 , "grapefruit-records"
1476 , "grapefruit-ui-gtk"
1480 , "GraphHammer-examples"
1482 , "graphics-formats-collada"
1485 , "graph-rewriting-cl"
1486 , "graph-rewriting-gl"
1487 , "graph-rewriting-lambdascope"
1488 , "graph-rewriting-layout"
1489 , "graph-rewriting-ski"
1490 , "graph-rewriting-strategies"
1491 , "graph-rewriting-trs"
1492 , "graph-rewriting-ww"
1511 , "gtk2hs-cast-glade"
1512 , "gtk2hs-cast-gnomevfs"
1514 , "gtk2hs-cast-gtkglext"
1517 , "gtk3-mac-integration"
1521 , "gtk-mac-integration"
1523 , "gtk-serialized-event"
1525 , "guess-combinator"
1531 , "hack2-handler-happstack-server"
1532 , "hack2-handler-mongrel2-http"
1533 , "hack2-handler-warp"
1534 , "hack2-interface-wai"
1542 , "hack-contrib-press"
1544 , "hack-frontend-happstack"
1545 , "hack-handler-epoll"
1546 , "hack-handler-evhttp"
1547 , "hack-handler-fastcgi"
1548 , "hack-handler-happstack"
1549 , "hack-handler-hyena"
1550 , "hack-handler-kibro"
1551 , "hack-handler-simpleserver"
1553 , "hack-middleware-cleanpath"
1554 , "hack-middleware-clientsession"
1555 , "hack-middleware-jsonp"
1565 , "hakyll-blaze-templates"
1567 , "hakyll-contrib-links"
1588 , "happs-hsp-template"
1593 , "happstack-contrib"
1596 , "happstack-facebook"
1598 , "happstack-foundation"
1600 , "happstack-helpers"
1603 , "happstack-monad-peel"
1604 , "happstack-plugins"
1611 , "happybara-webkit"
1612 , "happybara-webkit-server"
1627 , "hashable-generics"
1641 , "haskell-brainfuck"
1643 , "haskell-course-preludes"
1644 , "haskelldb-connect-hdbc"
1645 , "haskelldb-connect-hdbc-catchio-mtl"
1646 , "haskelldb-connect-hdbc-catchio-tf"
1647 , "haskelldb-connect-hdbc-catchio-transformers"
1648 , "haskelldb-connect-hdbc-lifted"
1649 , "haskelldb-dynamic"
1651 , "haskelldb-hdbc-mysql"
1652 , "haskelldb-hdbc-odbc"
1653 , "haskelldb-hdbc-postgresql"
1654 , "haskelldb-hdbc-sqlite3"
1656 , "haskelldb-hsql-mysql"
1657 , "haskelldb-hsql-odbc"
1658 , "haskelldb-hsql-postgresql"
1659 , "haskelldb-hsql-sqlite3"
1662 , "haskell-formatter"
1664 , "haskell-in-space"
1665 , "haskell-neo4j-client"
1668 , "haskell-openflow"
1669 , "haskell-pdf-presenter"
1670 , "haskell-platform-test"
1675 , "haskell-src-meta-mwotton"
1677 , "haskell-type-exts"
1688 , "haskoin-protocol"
1693 , "haskoon-httpspec"
1696 , "haskore-realtime"
1697 , "haskore-supercollider"
1698 , "haskore-synthesizer"
1734 , "hdaemonize-buildfix"
1769 , "her-lexer-parsec"
1774 , "herringbone-embed"
1782 , "hexpat-pickle-generic"
1795 , "HGamer3D-CAudio-Binding"
1796 , "HGamer3D-CEGUI-Binding"
1797 , "HGamer3D-Enet-Binding"
1798 , "HGamer3D-Graphics3D"
1800 , "HGamer3D-InputSystem"
1801 , "HGamer3D-Network"
1802 , "HGamer3D-Ogre-Binding"
1803 , "HGamer3D-OIS-Binding"
1804 , "HGamer3D-SDL2-Binding"
1805 , "HGamer3D-SFML-Binding"
1806 , "HGamer3D-WinEvent"
1821 , "hierarchical-clustering-diagrams"
1829 , "hinduce-classifier"
1830 , "hinduce-classifier-decisiontree"
1831 , "hinduce-examples"
1848 , "HLearn-datastructures"
1861 , "hmatrix-gsl-stats"
1862 , "hmatrix-quadprogpp"
1892 , "Holumbus-Distribution"
1893 , "Holumbus-MapReduce"
1894 , "Holumbus-Searchengine"
1895 , "Holumbus-Storage"
1966 , "hs-carbon-examples"
1970 , "hscurses-fish-ex"
2004 , "hsndfile-storablevector"
2006 , "hs-nombre-generator"
2015 , "hspec-experimental"
2025 , "hsqml-demo-morris"
2026 , "hsqml-demo-samples"
2036 , "HStringTemplateHelpers"
2038 , "hs-twitterarchiver"
2058 , "http-client-request-modifiers"
2059 , "http-conduit-browser"
2060 , "http-conduit-downloader"
2064 , "https-everywhere-rules"
2078 , "hunt-searchengine"
2081 , "husk-scheme-libs"
2097 , "hydrogen-cli-args"
2099 , "hydrogen-parsing"
2100 , "hydrogen-prelude"
2101 , "hydrogen-prelude-parsec"
2114 , "ide-backend-server"
2121 , "ige-mac-integration"
2128 , "ihaskell-display"
2130 , "ihaskell-juicypixels"
2134 , "ihaskell-rlangqq"
2142 , "ImperativeHaskell"
2148 , "incremental-computing"
2149 , "incremental-sat-solver"
2156 , "InfixApplicative"
2163 , "interleavableGen"
2166 , "interpolatedstring-qq"
2167 , "interpolatedstring-qq-mwotton"
2177 , "iptables-helpers"
2186 , "iteratee-compress"
2195 , "ivory-quickcheck"
2209 , "java-bridge-extras"
2230 , "JSON-Combinator-Examples"
2239 , "JuicyPixels-repa"
2240 , "JunkDB-driver-gdbm"
2245 , "kansas-lava-cores"
2246 , "kansas-lava-papilio"
2247 , "kansas-lava-shake"
2249 , "keera-hails-mvc-model-lightmodel"
2250 , "keera-hails-reactive-fs"
2259 , "kickass-torrents-dump-parser"
2266 , "koellner-phonetic"
2270 , "kure-your-boilerplate"
2274 , "labyrinth-server"
2280 , "LambdaCalculator"
2283 , "lambdacube-bullet"
2284 , "lambdacube-engine"
2285 , "lambdacube-examples"
2286 , "lambdacube-samples"
2291 , "LambdaPrettyQuote"
2299 , "language-c-comments"
2300 , "language-c-inline"
2303 , "language-java-classfile"
2307 , "language-python-colour"
2309 , "language-spelling"
2314 , "latest-npm-version"
2318 , "layout-bootstrap"
2328 , "learn-physics-examples"
2331 , "leveldb-haskell-fork"
2348 , "libsystemd-daemon"
2354 , "lighttpd-conf-qq"
2359 , "linear-algebra-cblas"
2362 , "linearscan-hoopl"
2375 , "listlike-instances"
2376 , "list-t-html-parser"
2383 , "llvm-general-quote"
2390 , "LogicGrowsOnTrees"
2391 , "LogicGrowsOnTrees-MPI"
2392 , "LogicGrowsOnTrees-network"
2393 , "LogicGrowsOnTrees-processes"
2427 , "manatee-anything"
2432 , "manatee-filemanager"
2433 , "manatee-imageviewer"
2435 , "manatee-pdfviewer"
2436 , "manatee-processmanager"
2438 , "manatee-template"
2439 , "manatee-terminal"
2448 , "markov-processes"
2450 , "marmalade-upload"
2464 , "MaybeT-monads-tf"
2465 , "MaybeT-transformers"
2479 , "meta-par-accelerate"
2487 , "microformats2-parser"
2516 , "modular-prelude-classy"
2517 , "module-management"
2522 , "monad-atom-simple"
2524 , "MonadCatchIO-mtl-foreign"
2525 , "MonadCatchIO-transformers-foreign"
2528 , "monadiccp-gecode"
2529 , "monad-interleave"
2534 , "monad-mersenne-random"
2538 , "monad-stlike-stm"
2546 , "mongrel2-handler"
2574 , "multiplate-simplified"
2575 , "multirec-alt-deriver"
2580 , "musicbrainz-email"
2595 , "mysnapsession-example"
2596 , "mysql-simple-quasi"
2597 , "mysql-simple-typed"
2600 , "nagios-plugin-ekg"
2626 , "network-anonymous-i2p"
2628 , "network-bytestring"
2629 , "network-connection"
2631 , "network-minihttp"
2634 , "network-simple-tls"
2635 , "network-topic-models"
2636 , "network-transport-amqp"
2637 , "network-websocket"
2662 , "not-gloss-examples"
2689 , "ois-input-manager"
2703 , "openexchangerates"
2710 , "openpgp-crypto-api"
2712 , "openssh-github-keys"
2723 , "order-maintenance"
2740 , "parameterized-data"
2742 , "parco-attoparsec"
2743 , "parconc-examples"
2776 , "persistent-hssqlppp"
2778 , "persistent-protobuf"
2784 , "pg-harness-server"
2801 , "pipes-cereal-plus"
2803 , "pipes-network-tls"
2804 , "pipes-p2p-examples"
2814 , "plugins-multistage"
2820 , "pointless-haskell"
2821 , "pointless-lenses"
2822 , "pointless-rewrite"
2826 , "polytypeable-utils"
2827 , "pontarius-mediaserver"
2841 , "postgresql-schema"
2842 , "postgresql-simple-typed"
2843 , "postgresql-typed"
2855 , "prelude-generalize"
2857 , "preprocess-haskell"
2863 , "PriorityChansConverger"
2865 , "ProbabilityMonads"
2870 , "process-listlike"
2871 , "process-progress"
2873 , "procrastinating-structure"
2874 , "procrastinating-variable"
2877 , "profunctor-extras"
2882 , "proj4-hs-bindings"
2885 , "prolog-graph-lib"
2890 , "protocol-buffers-descriptor-fork"
2891 , "protocol-buffers-fork"
2892 , "prove-everywhere-server"
2895 , "publicsuffixlistcreate"
2912 , "push-notify-general"
2915 , "puzzle-draw-cmdline"
2925 , "querystring-pickle"
2930 , "quickcheck-regex"
2931 , "quickcheck-relaxng"
2932 , "quickcheck-rematch"
2941 , "radium-formula-parser"
2943 , "rail-compiler-editor"
2949 , "random-access-list"
2953 , "random-hypergeometric"
2960 , "raven-haskell-scotty"
2968 , "reactive-banana-sdl"
2969 , "reactive-banana-threepenny"
2970 , "reactive-fieldtrip"
2974 , "really-simple-xml-parser"
2978 , "record-preprocessor"
2986 , "reflection-extras"
2997 , "regional-pointers"
2999 , "regions-monadsfd"
3000 , "regions-monadstf"
3022 , "representable-functors"
3023 , "representable-profunctors"
3024 , "representable-tries"
3030 , "restricted-workers"
3032 , "resumable-exceptions"
3033 , "rethinkdb-client-driver"
3044 , "ripple-federation"
3056 , "roguestar-engine"
3059 , "RollingDirectory"
3068 , "roundtrip-string"
3090 , "safer-file-handles"
3091 , "safer-file-handles-bytestring"
3092 , "safer-file-handles-text"
3100 , "salvia-websocket"
3101 , "samtools-iteratee"
3104 , "satchmo-backends"
3105 , "satchmo-examples"
3111 , "scan-vector-machine"
3116 , "scholdoc-citeproc"
3150 , "semigroups-actions"
3158 , "seqloc-datafiles"
3162 , "servant-postgresql"
3165 , "ses-html-snaplet"
3184 , "shakespeare-i18n"
3189 , "Shellac-compatline"
3190 , "Shellac-editline"
3191 , "Shellac-haskeline"
3192 , "Shellac-readline"
3204 , "simple-bluetooth"
3214 , "simple-log-syslog"
3217 , "simple-postgresql-orm"
3221 , "simple-templates"
3252 , "snaplet-actionlog"
3254 , "snaplet-environments"
3259 , "snaplet-mongodb-minimalistic"
3260 , "snaplet-mysql-simple"
3267 , "snaplet-typed-sessions"
3268 , "snaplet-wordpress"
3273 , "sndfile-enumerators"
3274 , "sneathlane-haste"
3284 , "sonic-visualiser"
3288 , "source-code-server"
3299 , "special-functors"
3301 , "speculation-transformers"
3315 , "sqlite-simple-typed"
3317 , "sql-simple-mysql"
3319 , "sql-simple-postgresql"
3320 , "sql-simple-sqlite"
3326 , "stackage-curator"
3331 , "statistics-dirichlet"
3332 , "statistics-fusion"
3337 , "stm-chunked-queues"
3341 , "storable-static-array"
3343 , "storablevector-carray"
3344 , "storablevector-streamfusion"
3345 , "Strafunski-Sdf2Haskell"
3349 , "strict-concurrency"
3352 , "structured-mongoDB"
3358 , "sunroof-compiler"
3359 , "sunroof-examples"
3361 , "supercollider-midi"
3380 , "syntax-attoparsec"
3382 , "syntax-example-json"
3387 , "syntax-trees-fork-bairyn"
3389 , "synthesizer-alsa"
3390 , "synthesizer-core"
3391 , "synthesizer-dimensional"
3392 , "synthesizer-midi"
3394 , "system-canonicalpath"
3396 , "system-random-effect"
3408 , "tamarin-prover-term"
3409 , "tamarin-prover-theory"
3410 , "tamarin-prover-utils"
3423 , "template-default"
3424 , "template-haskell-util"
3431 , "termbox-bindings"
3435 , "test-framework-doctest"
3436 , "test-framework-quickcheck"
3448 , "text-register-machine"
3450 , "text-xml-generic"
3455 , "theoremquest-client"
3481 , "timestamp-subprocess-lines"
3493 , "tokyocabinet-haskell"
3499 , "to-string-instances"
3503 , "transactional-events"
3504 , "transformers-convert"
3505 , "transformers-runnable"
3508 , "treemap-html-tools"
3518 , "tsession-happstack"
3526 , "twentefp-rosetree"
3538 , "twitter-enumerator"
3540 , "twitter-types-lens"
3549 , "type-equality-check"
3556 , "typelevel-tensor"
3561 , "type-ord-spine-cereal"
3569 , "typography-geometry"
3580 , "unbounded-delays-units"
3581 , "unboxed-containers"
3582 , "unicode-normalization"
3592 , "unix-process-conduit"
3594 , "unordered-containers-rematch"
3604 , "uri-enumerator-file"
3608 , "urldisp-happstack"
3618 , "uvector-algorithms"
3629 , "vaultaire-common"
3633 , "vector-bytestring"
3637 , "vector-functorlazy"
3638 , "vector-instances-collections"
3640 , "vector-read-instances"
3641 , "vector-space-opengl"
3653 , "visual-graphrewrite"
3668 , "wai-handler-devel"
3669 , "wai-handler-snap"
3670 , "wai-handler-webkit"
3673 , "wai-logger-prefork"
3674 , "wai-middleware-cache"
3675 , "wai-middleware-cache-redis"
3676 , "wai-middleware-catch"
3677 , "wai-middleware-consul"
3678 , "wai-middleware-etag"
3679 , "wai-middleware-headers"
3680 , "wai-middleware-hmac-client"
3681 , "wai-middleware-preprocessor"
3682 , "wai-middleware-route"
3683 , "wai-middleware-static-caching"
3686 , "wai-session-tokyocabinet"
3687 , "wai-static-cache"
3700 , "WebBits-multiplate"
3701 , "web-browser-in-haskell"
3703 , "webcrank-dispatch"
3708 , "webkit-javascriptcore"
3711 , "web-routes-quasi"
3712 , "web-routes-transformers"
3727 , "Win32-dhcp-server"
3730 , "Win32-junction-point"
3734 , "Win32-services-wrapper"
3757 , "wumpus-microprint"
3776 , "xhaskell-library"
3788 , "xml-enumerator-combinators"
3797 , "xmms2-client-glib"
3798 , "xmonad-bluetilebranch"
3799 , "xmonad-contrib-bluetilebranch"
3815 , "yahoo-web-search"
3831 , "yesod-angular-ui"
3832 , "yesod-auth-account-fork"
3833 , "yesod-auth-kerberos"
3836 , "yesod-auth-smbclient"
3839 , "yesod-continuations"
3840 , "yesod-datatables"
3842 , "yesod-eventsource"
3848 , "yesod-pagination"
3852 , "yesod-purescript"
3854 , "yesod-routes-flow"
3855 , "yesod-routes-typescript"
3858 , "yesod-session-redis"
3872 , "Yogurt-Standalone"
3895 , "zoom-cache-sndfile"
3900 , "yesod-media-simple"
3902 , "ghc-imported-from"
3907 , "aws-configuration-tools"
3908 , "aws-dynamodb-streams"
3910 , "aws-kinesis-client"
3912 , "aws-performance-tests"
3915 , "haskell-token-utils"
3919 , "pdf-toolbox-content"
3920 , "pdf-toolbox-core"
3921 , "pdf-toolbox-document"
3922 , "pdf-toolbox-viewer"
3929 , "full-text-search"
3935 , "atomic-primops-vector"
3948 , "AlignmentAlgorithms"
3955 , "concurrent-machines"
3956 , "darcs-fastconvert"
3965 , "wai-middleware-metrics"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list