distribution-nixpkgs 1.5.0 → 1.6.0
raw patch · 8 files changed
+147/−53 lines, 8 filesnew-uploaderPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Distribution.Nixpkgs.PackageMap: readNixpkgPackageMap :: [String] -> IO PackageMap
+ Distribution.Nixpkgs.PackageMap: readNixpkgPackageMap :: String -> Maybe String -> IO PackageMap
Files
- CHANGELOG.md +13/−0
- README.md +4/−0
- derivation-attr-paths.nix +42/−0
- distribution-nixpkgs.cabal +9/−6
- src/Distribution/Nixpkgs/License.hs +20/−19
- src/Distribution/Nixpkgs/Meta.hs +1/−4
- src/Distribution/Nixpkgs/PackageMap.hs +57/−23
- src/Language/Nix/PrettyPrinting.hs +1/−1
+ CHANGELOG.md view
@@ -0,0 +1,13 @@+# Revision history for distribution-nixpkgs++## 1.6.0++* `Distribution.Nixpkgs.PackageMap`+ * `readNixpkgPackageMap`: instead of a list of arguments to pass to+ `nix-env`, take path to nixpkgs and an optional nix expression+ to pass to it as arguments.+ * `readNixpkgPackageMap`: populate `PackageMap` with *all* attribute+ paths that point to derivations instead of just one per derivation.+ This fixes `resolve` not finding certain identifiers if there were+ two attributes pointing to the same derivation in nixpkgs. See also+ [#9](https://github.com/NixOS/distribution-nixpkgs/issues/9).
+ README.md view
@@ -0,0 +1,4 @@+# distribution-nixpkgs++[](http://hackage.haskell.org/package/distribution-nixpkgs)+[](http://stackage.org/lts/package/distribution-nixpkgs)
+ derivation-attr-paths.nix view
@@ -0,0 +1,42 @@+{ nixpkgsPath ? <nixpkgs>+, nixpkgsArgs ? {}+}@args:++let+ pkgs = import nixpkgsPath nixpkgsArgs;++ inherit (pkgs) lib;++ /* Condition for us to recurse:+ Either we are at the top-level or+ recurseForDerivations is true.++ Type :: list any -> any -> bool+ */+ recurseInto = path: x: path == [] ||+ (lib.isAttrs x && (x.recurseForDerivations or false));++ /* Takes the nixpkgs set and returns all attribute paths+ to reachable derivations within it as a list of lists of+ strings.++ Type :: attrs -> list (list string)+ */+ derivationPaths =+ let+ go = path: x:+ let+ inherit (builtins.tryEval x)+ value+ success+ ;+ in+ if !success then []+ else if lib.isDerivation value then [+ path+ ] else if recurseInto path x then lib.concatLists (+ lib.mapAttrsToList (n: go (path ++ [ n ])) x+ ) else [];+ in go [];+in+ derivationPaths pkgs
distribution-nixpkgs.cabal view
@@ -1,20 +1,23 @@ name: distribution-nixpkgs-version: 1.5.0+version: 1.6.0 synopsis: Types and functions to manipulate the Nixpkgs distribution description: Types and functions to represent, query, and manipulate the Nixpkgs distribution. license: BSD3 license-file: LICENSE maintainer: Peter Simons <simons@cryp.to>-tested-with: GHC == 8.0.2 || == 8.2.2 || == 8.4.4 || == 8.6.5 || == 8.8.4 || == 8.10.4+tested-with: GHC == 8.6.5 || == 8.8.4 || == 8.10.4 || == 9.0.1 category: Distribution, Nix-homepage: https://github.com/peti/distribution-nixpkgs-bug-reports: https://github.com/peti/distribution-nixpkgs/issues+homepage: https://github.com/NixOS/distribution-nixpkgs+bug-reports: https://github.com/NixOS/distribution-nixpkgs/issues build-type: Simple cabal-version: >= 1.10+data-files: derivation-attr-paths.nix+extra-source-files: CHANGELOG.md+ README.md source-repository head type: git- location: https://github.com/peti/distribution-nixpkgs+ location: https://github.com/NixOS/distribution-nixpkgs library exposed-modules: Distribution.Nixpkgs.Hashes@@ -22,6 +25,7 @@ Distribution.Nixpkgs.Meta Distribution.Nixpkgs.PackageMap Language.Nix.PrettyPrinting+ other-modules: Paths_distribution_nixpkgs hs-source-dirs: src build-depends: base > 4.2 && < 5 , Cabal >= 2.4@@ -35,7 +39,6 @@ , process , split default-language: Haskell2010- default-extensions: MonadFailDesugaring other-extensions: CPP TemplateHaskell RecordWildCards
src/Distribution/Nixpkgs/License.hs view
@@ -2,8 +2,8 @@ {- | Known licenses in Nix expressions are represented using the- attributes defined in @pkgs\/lib\/licenses.nix@, and unknown licenses- are represented as a literal string.+ attributes defined in nixpkgs' @lib\/licenses.nix@, and+ unknown licenses are represented as a literal string. -} module Distribution.Nixpkgs.License ( License(..) ) where@@ -14,27 +14,28 @@ import Language.Nix.PrettyPrinting -- | The representation for licenses used in Nix derivations. Known--- licenses are Nix expressions -- such as @lib.licenses.bsd3@--- --, so their exact \"name\" is not generally known, because the path--- to @lib@ depends on the context defined in the expression. In--- Cabal expressions, for example, the BSD3 license would have to be+-- licenses are Nix expressions — such as @lib.licenses.bsd3@ —,+-- so their exact name is not generally known, because the path+-- to @lib@ depends on the context defined in the expression.+--+-- In Cabal expressions, for example, the BSD3 license would have to be -- referred to as @self.lib.licenses.bsd3@. Other expressions,--- however, use different paths to the @licenses@ record. Because of tat+-- however, use different paths to the @licenses@ record. Because of that -- situation, the library cannot provide an abstract data type that--- encompasses all known licenses. Instead, the @License@ type just--- distinguishes references to known and unknown licenses. The--- difference between the two is in the way they are pretty-printed:+-- encompasses all known licenses. ----- > > putStrLn (display (Known "lib.license.gpl2"))--- > lib.license.gpl2--- >--- > > putStrLn (display (Unknown (Just "GPL")))--- > "GPL"--- >--- > > putStrLn (display (Unknown Nothing))--- > "unknown"+-- Instead, the @License@ type just distinguishes references to known+-- and unknown licenses. The difference between the two is in the way+-- they are pretty-printed: ----- Note that the "Text" instance definition provides pretty-printing,+-- >>> putStrLn (prettyShow (Known "lib.license.gpl2"))+-- lib.license.gpl2+-- >>> putStrLn (prettyShow (Unknown (Just "GPL")))+-- "GPL"+-- >>> putStrLn (prettyShow (Unknown Nothing))+-- "unknown"+--+-- Note that the 'Pretty' instance definition provides pretty-printing, -- but no parsing as of now! data License = Known String
src/Distribution/Nixpkgs/Meta.hs view
@@ -76,10 +76,7 @@ renderPlatforms :: String -> Set Platform -> Doc renderPlatforms field ps | Set.null ps = sep [ text field <+> equals <+> text "lib.platforms.none" <> semi ]- | otherwise = sep [ text field <+> equals <+> lbrack- , nest 2 $ fsep $ map text (toAscList (Set.map fromCabalPlatform ps))- , rbrack <> semi- ]+ | otherwise = setattr field mempty $ Set.map fromCabalPlatform ps nullMeta :: Meta nullMeta = Meta
src/Distribution/Nixpkgs/PackageMap.hs view
@@ -1,3 +1,4 @@+-- | Build a lookup table from package identifiers to full attribute paths in nixpkgs. module Distribution.Nixpkgs.PackageMap ( PackageMap, readNixpkgPackageMap , resolve@@ -7,45 +8,78 @@ import qualified Data.Aeson as JSON import qualified Data.ByteString.Lazy as LBS import Data.Function-import Data.List as List-import Data.List.Split+import Data.List (minimumBy) import Data.Map.Strict ( Map ) import qualified Data.Map.Strict as Map import Data.Maybe import Data.Set ( Set ) import qualified Data.Set as Set import Language.Nix+import Paths_distribution_nixpkgs (getDataFileName) import System.Process type PackageMap = Map Identifier (Set Path) -readNixpkgPackageMap :: [String] -> IO PackageMap-readNixpkgPackageMap = fmap identifierSet2PackageMap . readNixpkgSet+-- | Evaluate nixpkgs at a given (nix) path and build a 'Map'+-- keeping track of all 'Path's that end in a given 'Identifier'+-- and evaluate to a derivation.+-- This can be used to find an attribute 'Path' for an arbitrary+-- package name using 'resolve'.+--+-- Note: Evaluation of nixpkgs is very expensive (takes multiple+-- seconds), so cache the result of this function if possible.+--+-- >>> readNixpkgPackageMap "<nixpkgs>" (Just "{ config = { allowAliases = false; }; }")+-- fromList [ … ]+readNixpkgPackageMap :: String+ -- ^ Path to nixpkgs, must be a valid nix path+ -- (absolute, relative or @NIX_PATH@ lookup)+ -> Maybe String+ -- ^ (Optional) argument attribute set to pass to+ -- nixpkgs. Must be a valid nix attribute set.+ -> IO PackageMap+readNixpkgPackageMap nixpkgsPath nixpkgsArgs =+ identifierSet2PackageMap <$> readNixpkgSet nixpkgsPath nixpkgsArgs -readNixpkgSet :: [String] -> IO (Set String)-readNixpkgSet extraArgs = do- (_, Just h, _, _) <- createProcess (proc "nix-env" (["-qaP", "--json"] ++ extraArgs))- { std_out = CreatePipe, env = Nothing } -- TODO: ensure that overrides don't screw up our results+readNixpkgSet :: String -> Maybe String -> IO (Set [String])+readNixpkgSet nixpkgsPath nixpkgsArgs = do+ pathsExpr <- getDataFileName "derivation-attr-paths.nix"+ let nixInstantiate = proc "nix-instantiate"+ [ "--strict"+ , "--json"+ , "--eval"+ , pathsExpr+ , "--arg", "nixpkgsPath", nixpkgsPath+ , "--arg", "nixpkgsArgs", fromMaybe "{}" nixpkgsArgs+ ]+ (_, Just h, _, _) <- -- TODO: ensure that overrides don't screw up our results+ createProcess nixInstantiate { std_out = CreatePipe, env = Nothing } buf <- LBS.hGetContents h- let pkgmap :: Either String (Map String JSON.Object)- pkgmap = JSON.eitherDecode buf- either fail (return . Map.keysSet) pkgmap+ either fail return $ JSON.eitherDecode buf -identifierSet2PackageMap :: Set String -> PackageMap-identifierSet2PackageMap pkgset = foldr (uncurry insertIdentifier) Map.empty pkglist+identifierSet2PackageMap :: Set [String] -> PackageMap+identifierSet2PackageMap = foldr insertIdentifier Map.empty where- pkglist :: [(Identifier, Path)]- pkglist = mapMaybe parsePackage (Set.toList pkgset)-- insertIdentifier :: Identifier -> Path -> PackageMap -> PackageMap- insertIdentifier i = Map.insertWith Set.union i . Set.singleton+ insertIdentifier :: [String] -> (PackageMap -> PackageMap)+ insertIdentifier rawPath =+ case parsePackage rawPath of+ Nothing -> id+ Just (i, p) -> Map.insertWith Set.union i $ Set.singleton p -parsePackage :: String -> Maybe (Identifier, Path)-parsePackage x | null x = error "Distribution.Nixpkgs.PackageMap.parsepackage: empty string is no valid identifier"- | xs <- splitOn "." x = if needsQuoting (head xs)- then Nothing- else Just (ident # last xs, path # map (review ident) xs)+parsePackage :: [String] -> Maybe (Identifier, Path)+parsePackage x+ | null x = -- this case would be a bug in derivation-attr-paths.nix+ error "Distribution.Nixpkgs.PackageMap.parsepackage: empty path is no valid identifier"+ | otherwise =+ if any needsQuoting x+ then Nothing+ else Just (ident # last x, path # map (review ident) x) +-- | Finds the shortest 'Path' in a 'PackageMap' that has the+-- given 'Identifier' as its last component.+--+-- >>> resolve nixpkgs (ident # "pam")+-- Just (Bind (Identifier "pam") (Path [Identifier "pam"])) resolve :: PackageMap -> Identifier -> Maybe Binding resolve nixpkgs i = case Map.lookup i nixpkgs of Nothing -> Nothing
src/Language/Nix/PrettyPrinting.hs view
@@ -22,7 +22,7 @@ #endif import Data.Char import Data.Function-import Data.List+import Data.List (sortBy) import Data.Set ( Set ) import qualified Data.Set as Set import "pretty" Text.PrettyPrint.HughesPJClass