packages feed

nix-tree 0.3.3 → 0.4.0

raw patch · 5 files changed

+113/−24 lines, 5 filesdep +dot

Dependencies added: dot

Files

CHANGELOG.md view
@@ -1,5 +1,13 @@ # Changelog +## 0.4.0 - 2024-01-21:++* feat: Allow passing `--store` for alternative nix store (e.g. remote binary cache) (thanks @bryango, PR: [#79][])+* feat: Graphviz export via `--dot` flag (thanks @SomeoneSerge, issue: [#59][])++[#79]: https://github.com/utdemir/nix-tree/pull/79+[#59]: https://github.com/utdemir/nix-tree/issues/59+ ## 0.3.3 - 2024-01-17:  * chore: Update 'brick' & 'optparse-applicative' library to work with the newer Stackage snapshot (thanks @ncfavier, PR: [#78][]) 
README.md view
@@ -12,9 +12,15 @@ `nix-tree` is on `nixpkgs` since `20.09`, so just use your preferred method for adding packages to your system, eg:  ```-nix-env -i nix-tree+nix-env -iA nix-tree ``` +Or, for flake enabled systems:++```+nix profile install 'nixpkgs#nix-tree'+```+ To run the current development version:  ```@@ -23,17 +29,21 @@  ## Usage -```+```console $ nix-tree --help-Usage: nix-tree [--version] [--derivation] [INSTALLABLE]+Usage: nix-tree [INSTALLABLE] [--store STORE] [--version] [--derivation] [--impure] [--dot]+   Interactively browse dependency graphs of Nix derivations.  Available options:-  --version                Show the nix-tree version.-  --derivation             Operate on the store derivation rather than its-                           outputs.-  INSTALLABLE              A store path or a flake reference. Paths default to-                           "~/.nix-profile" and "/var/run/current-system".+  INSTALLABLE              A store path or a flake reference.+                           Paths default to "~/.nix-profile" and "/var/run/current-system"+  --store STORE            The URL of the Nix store, e.g. "daemon" or "https://cache.nixos.org"+                           See "nix help-stores" for supported store types and settings.+  --version                Show the nix-tree version+  --derivation             Operate on the store derivation rather than its outputs+  --impure                 Allow access to mutable paths and repositories+  --dot                    Print the dependency graph in dot format   -h,--help                Show this help text  Keybindings:@@ -66,12 +76,12 @@ nix-build . --no-out-link | xargs -o nix-tree  # Build time dependencies (passing a `.drv` path)-nix-instantiate -r | xargs -o nix-tree --derivation+nix-instantiate . | xargs -o nix-tree --derivation  # Dependencies from shell.nix nix-build shell.nix -A inputDerivation | xargs -o nix-tree -# All outputs of a derivation in nixpkgs:+# All outputs of a derivation in nixpkgs nix-build '<nixpkgs>' -A openssl.all --no-out-link | xargs -o nix-tree ``` @@ -89,6 +99,20 @@  ```bash nix-tree /nix/var/nix/profiles/system+```++Query the binary cache before download, with the `--store` option:++```bash+# Query the runtime dependency of `stellarium` (2 GiB closure) without download+nix eval --raw 'nixpkgs#stellarium.outPath' | xargs -o nix-tree --store https://cache.nixos.org+```++For valid `--store` options, see [`nix help-stores`](https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-help-stores). For example,++```bash+# Build in a temporary chroot store and examine the output+nix build --store /tmp/chroot-store 'nixpkgs#hello' --print-out-paths | xargs -o nix-tree --store /tmp/chroot-store ```  ## Contributing
nix-tree.cabal view
@@ -3,7 +3,7 @@ name:                nix-tree synopsis:            Interactively browse a Nix store paths dependencies description:         A terminal curses application to browse a Nix store paths dependencies-version:             0.3.3+version:             0.4.0 homepage:            https://github.com/utdemir/nix-tree license:             BSD-3-Clause license-file:        LICENSE@@ -61,6 +61,7 @@                     , directory                     , optparse-applicative                     , microlens+                    , dot  executable nix-tree   import:             common-options
src/NixTree/Main.hs view
@@ -19,9 +19,11 @@  data Opts = Opts   { oInstallables :: [Installable],+    oStore :: String,     oVersion :: Bool,     oDerivation :: Bool,-    oImpure :: Bool+    oImpure :: Bool,+    oDot :: Bool   }  optsParser :: Opts.ParserInfo Opts@@ -49,9 +51,22 @@                       )                 )           )+        <*> Opts.strOption+          ( Opts.long "store"+              <> Opts.metavar "STORE"+              <> Opts.value "auto"+              <> Opts.helpDoc+                ( Just $+                    Opts.vsep+                      [ "The URL of the Nix store, e.g. \"daemon\" or \"https://cache.nixos.org\"",+                        "See \"nix help-stores\" for supported store types and settings."+                      ]+                )+          )         <*> Opts.switch (Opts.long "version" <> Opts.help "Show the nix-tree version")         <*> Opts.switch (Opts.long "derivation" <> Opts.help "Operate on the store derivation rather than its outputs")         <*> Opts.switch (Opts.long "impure" <> Opts.help "Allow access to mutable paths and repositories")+        <*> Opts.switch (Opts.long "dot" <> Opts.help "Print the dependency graph in dot format")      keybindingsHelp :: Opts.Doc     keybindingsHelp =@@ -96,7 +111,8 @@   let seo =         StoreEnvOptions           { seoIsDerivation = opts & oDerivation,-            seoIsImpure = opts & oImpure+            seoIsImpure = opts & oImpure,+            seoStoreURL = opts & oStore           }    withStoreEnv seo installables $ \env' -> do@@ -109,7 +125,9 @@       & chunks 50       & mapConcurrently_ (mapM_ (\p -> evaluate (rnf p) >> incProgress bar 1)) -    run env+    if opts & oDot+      then putTextLn $ storeEnvToDot env+      else run env  chunks :: Int -> [a] -> [[a]] chunks _ [] = []
src/NixTree/StorePath.hs view
@@ -14,8 +14,8 @@     seGetRoots,     seBottomUp,     seFetchRefs,-    getNixStore,     mkStoreName,+    storeEnvToDot,   ) where @@ -26,7 +26,9 @@ import qualified Data.ByteString.Lazy as BL import qualified Data.HashMap.Strict as HM import qualified Data.HashSet as HS+import qualified Data.Set as Set import qualified Data.Text as T+import qualified Dot import System.FilePath.Posix (addTrailingPathSeparator, splitDirectories, (</>)) import System.IO (hPutStrLn) import System.Process.Typed (proc, readProcessStdout_)@@ -48,10 +50,10 @@ unNixStore NixStore = "/nix/store/" unNixStore (NixStoreCustom fp) = fp -getNixStore :: IO NixStore-getNixStore = do+getStoreDir :: FilePath -> IO NixStore+getStoreDir seoNixStore = do   let prog = "nix-instantiate"-      args = ["--eval", "--expr", "(builtins.storeDir)", "--json"]+      args = ["--eval", "--expr", "(builtins.storeDir)", "--json", "--option", "store", seoNixStore]   out <-     readProcessStdout_ (proc prog args)       <&> fmap mkNixStore@@ -146,7 +148,8 @@ data PathInfoOptions = PathInfoOptions   { pioIsRecursive :: Bool,     pioIsDerivation :: Bool,-    pioIsImpure :: Bool+    pioIsImpure :: Bool,+    pioStoreURL :: FilePath   }  getPathInfo :: NixStore -> NixVersion -> PathInfoOptions -> NonEmpty Installable -> IO (NonEmpty (StorePath s (StoreName s) ()))@@ -160,6 +163,7 @@                 ++ ["--impure" | options & pioIsImpure]                 ++ ["--recursive" | options & pioIsRecursive]                 ++ ["--derivation" | (options & pioIsDerivation) && nixVersion >= Nix2_4]+                ++ ["--store", options & pioStoreURL]                 ++ (if nixVersion >= Nix2_4 then ["--extra-experimental-features", "nix-command flakes"] else [])                 ++ map (toString . installableToText) (toList names)             )@@ -200,7 +204,8 @@  data StoreEnvOptions = StoreEnvOptions   { seoIsDerivation :: Bool,-    seoIsImpure :: Bool+    seoIsImpure :: Bool,+    seoStoreURL :: String   }  withStoreEnv ::@@ -210,8 +215,8 @@   NonEmpty Installable ->   (forall s. StoreEnv s () -> m a) ->   m a-withStoreEnv StoreEnvOptions {seoIsDerivation, seoIsImpure} names cb = do-  nixStore <- liftIO getNixStore+withStoreEnv StoreEnvOptions {seoIsDerivation, seoIsImpure, seoStoreURL} names cb = do+  nixStore <- liftIO $ getStoreDir seoStoreURL    -- See: https://github.com/utdemir/nix-tree/issues/12   nixVersion <- liftIO getNixVersion@@ -225,7 +230,7 @@       getPathInfo         nixStore         nixVersion-        (PathInfoOptions {pioIsDerivation = seoIsDerivation, pioIsRecursive = False, pioIsImpure = seoIsImpure})+        (PathInfoOptions {pioIsDerivation = seoIsDerivation, pioIsRecursive = False, pioIsImpure = seoIsImpure, pioStoreURL = seoStoreURL})         names    paths <-@@ -233,7 +238,7 @@       getPathInfo         nixStore         nixVersion-        (PathInfoOptions {pioIsDerivation = seoIsDerivation, pioIsRecursive = True, pioIsImpure = seoIsImpure})+        (PathInfoOptions {pioIsDerivation = seoIsDerivation, pioIsRecursive = True, pioIsImpure = seoIsImpure, pioStoreURL = seoStoreURL})         (Installable . toText . storeNameToPath . spName <$> roots)    let env =@@ -314,6 +319,39 @@           let new = sp {spPayload = f sp {spRefs = refs}}           modify $ bimap (HM.delete spName) (HM.insert spName new)           return new++--------------------------------------------------------------------------------++storeEnvToDot :: StoreEnv s a -> Text+storeEnvToDot env =+  seBottomUp go env+    & seGetRoots+    & toList+    & map spPayload+    & mconcat+    & render+  where+    go sp =+      fromList [Set.singleton (spName sp, spName ref) <> spPayload ref | ref <- spRefs sp]+        & mconcat++    render :: Set (StoreName s, StoreName s) -> Text+    render edges =+      Dot.DotGraph+        Dot.Strict+        Dot.Directed+        Nothing+        [ Dot.StatementEdge+            ( Dot.EdgeStatement+                (Dot.ListTwo (Dot.EdgeNode (mkNodeId from)) (Dot.EdgeNode (mkNodeId to)) [])+                []+            )+          | (from, to) <- toList edges+        ]+        & Dot.encode++    mkNodeId :: StoreName s -> Dot.NodeId+    mkNodeId = fromString . toString . storeNameToShortText  --------------------------------------------------------------------------------