How to display project dependencies in a tree?

Using the package manager I can display the direct dependencies of my package:

(KiteModels) pkg> st
     Project KiteModels v0.2.2
      Status `~/repos/KiteModels/Project.toml`
  [39dd38d3] Dierckx v0.5.2
  [ffbed154] DocStringExtensions v0.8.6
  [9de5dc81] KitePodModels v0.1.2
  [90980105] KiteUtils v0.3.2
  [2774e3e8] NLsolve v4.5.1
  [d96e819e] Parameters v0.12.3
  [90137ffa] StaticArrays v1.4.3
  [c3572dad] Sundials v4.9.3
  [1e6cf692] TestEnv v1.7.2
  [37e2e46d] LinearAlgebra

Is there a way to also display the sub-dependencies and sub-sub-dependencies in a tree like structure similar to the command tree in Linux?

2 Likes

Donโ€™t know of a tree-like visualization option, but there is st --manifest for showing all dependencies (typing on my mobile phone and canโ€™t check the precise name of the option.)

1 Like

You could read in the Manifest.toml using TOML and then use REPLTreeViews.jl to look at the dictionary.

2 Likes

Thank you!
But how did you know about that option? I could not find any options for any Pkg commands yetโ€ฆ

(KiteModels) pkg> st --help
ERROR: option 'help' is not a valid option

OK, found it:

(KiteModels) pkg> ?st
  [st|status] [-d|--diff] [pkgs...]
  [st|status] [-d|--diff] [-p|--project] [pkgs...]
  [st|status] [-d|--diff] [-m|--manifest] [pkgs...]

  Show the status of the current environment. In --project mode (default), the status of the project file is summarized. In --manifest mode the output also includes the recursive dependencies of added packages given in the manifest. If there are any packages listed as arguments the output will be limited to those
  packages. The --diff option will, if the environment is in a git repository, limit the output to the difference as compared to the last git commit.

  โ”‚ Julia 1.1
  โ”‚
  โ”‚  pkg> status with package arguments requires at least Julia 1.1.

  โ”‚ Julia 1.3
  โ”‚
  โ”‚  The --diff option requires Julia 1.3. In earlier versions --diff is the default for environments in git repositories.

Thanks for suggesting this package!
But does Manifest.toml contain the information needed to create a tree?
I thought it is just a flat list.

For pedagogical reasons I will write out how I came about the solution (since I am not a Pkg expert โ€“ i would bet there are easier ways to access this information).

The documentation of Pkg.status cross-refs the functions Pkg.project and Pkg.dependencies as alternatives that donโ€™t print out the results, so we are going to use those.

Now the hard part: knowing that AbstractTrees.jl โ€“ which we can use to transverse the tree โ€“ already has a print function so all we have to do is chain both.

using AbstractTrees
using Pkg

function AbstractTrees.printnode(io::IO, uuid::Base.UUID)
    dep = get(Pkg.dependencies(), uuid, nothing)
    print(io, dep.name)
end

function AbstractTrees.children(uuid::Base.UUID)
    dep = get(Pkg.dependencies(), uuid, nothing)
    dep.dependencies
end

# Example (with some package you have in your Project.toml -- in my case Pluto)
AbstractTrees.print_tree(Pkg.project().dependencies["Pluto"])

# Print all dependencies: definitely do not recommend
# AbstractTrees.children(x::Pkg.API.ProjectInfo) = x.dependencies
# AbstractTrees.printnode(io::IO, x::Pkg.API.ProjectInfo) = x.name
# AbstractTrees.print_tree(Pkg.project())
7 Likes

Very nice and easy solution!

Does anybody know what the meaning is of the triple dots that appear for example here:

โ”‚  โ”œโ”€ Tables
โ”‚  โ”‚  โ”œโ”€ DataAPI
โ”‚  โ”‚  โ”œโ”€ OrderedCollections
โ”‚  โ”‚  โ”œโ”€ LinearAlgebra
โ”‚  โ”‚  โ”‚  โ”œโ”€ libblastrampoline_jll
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ OpenBLAS_jll
โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ‹ฎ
โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  
โ”‚  โ”‚  โ”‚  โ”‚  โ”œโ”€ Libdl
โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ‹ฎ
โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  
โ”‚  โ”‚  โ”‚  โ”‚  โ””โ”€ Artifacts
โ”‚  โ”‚  โ”‚  โ”‚     โ‹ฎ
โ”‚  โ”‚  โ”‚  โ”‚     
โ”‚  โ”‚  โ”‚  โ””โ”€ Libdl

If you check the documentation of print_tree

?AbstractTrees.print_tree

youโ€™ll see that thereโ€™s a maxdepth keyword argument that truncates the output. Setting it to a large value should get rid of those dots

AbstractTrees.print_tree(Pkg.project().dependencies["Pluto"], maxdepth=Inf)
4 Likes

Perfect! Thank you.

Learning a lot by studying these trees! :grinning:

1 Like

For anyone landing on this topic: there is now GitHub - peng1999/PkgDependency.jl: Show dependency tree of Julia project

9 Likes

I was thinking that the right visualization would not be a tree, since, if we root at the current environment, the same package might appear at several places. A directed graph would be a better representation.

4 Likes

Crosspost for a way to visualize dependencies with their import timings: