Welcome! Please see the About page for a little more info on how this works.

+2 votes
in Tools by
retagged by

clojure.tools.cli.api/tree prints hierarchical dependency data in either a "human friendly tree" (:format :print, the default) or pretty-printing edn (:format :edn) data

To get the result as data, you can use with-out-str and edn/read-string

(-> (deps/tree {:project deps-map, 
                :format :edn})

Works a treat. That said, the round-tripping from pprint within cli/tree and re-parsing makes me suspect I’m doing it wrong. It'd be nice to be able to get the edn back directly as data.

2 Answers

0 votes

Here's one idea (called from within the clojure.tools.deps repo itself):

% clj -e "(require 'clojure.tools.cli.api)(->> (clojure.tools.cli.api/tree {:format :tree}) :children count prn)"

Didn't see a way to attach a patch, but here's one for completeness (though the change is pretty straightforward and simple).

From 7cc05b1913af8ee9982852fd618b775a1c339b0e Mon Sep 17 00:00:00 2001
From: Michael Glaesemann <grzm@seespotcode.net>
Date: Wed, 6 Apr 2022 07:28:28 -0500
Subject: [PATCH] Add :tree format option to cli.api/tree to return tree as

 src/main/clojure/clojure/tools/cli/api.clj | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git src/main/clojure/clojure/tools/cli/api.clj src/main/clojure/clojure/tools/cli/api.clj
index 931df53..96d8835 100644
--- src/main/clojure/clojure/tools/cli/api.clj
+++ src/main/clojure/clojure/tools/cli/api.clj
@@ -114,7 +114,7 @@
 (defn tree
-  "Print deps tree for the current project's deps.edn built from either the
+  "Return deps tree for the current project's deps.edn built from either the
   a basis, or if provided, the trace file.
   This program accepts the same basis-modifying arguments from the `basis` program.
@@ -122,7 +122,7 @@
   Sources are merged in the order - :root, :user, :project, :extra.
   By default, :format will :print to the console in a human friendly tree. Use
-  :edn mode to print the tree to edn.
+  :edn mode to print the tree to edn. Use :tree mode to return the tree as data.
   In print mode, deps are printed with prefix of either . (included) or X (excluded).
   A reason code for inclusion/exclusion may be added at the end of the line.
@@ -138,7 +138,7 @@
     :file      Path to trace.edn file (from clj -Strace) to use in computing the tree
   Output mode:
-    :format    :print (default) or :edn
+    :format    :print (default), :edn (pretty-printed edn), or :tree (data)
   Print output mode modifiers:
     :indent    Indent spacing (default = 2)
@@ -157,6 +157,7 @@
       (case format
         :print (tree/print-tree tree opts)
         :edn (pprint/pprint tree)
+        :tree tree
         (throw (ex-info (str "Unknown format " format) {}))))
     (catch Throwable t
       (printerrln "Error generating tree:" (.getMessage t))
2.32.0 (Apple Git-132)
The functions in clojure.tools.cli.api are really designed for use from the CLI, not programmatic use, so I would probably not put this functionality on cli.api/tree, but rather expand clojure.tools.deps.alpha.* (not sure where exactly without looking at it more).
That makes sense. Thanks for the pointer to https://clojure.atlassian.net/browse/TDEPS-225. I'll follow up there.
0 votes
The original Slack post mentioned monorepos and it is interesting our own attempts at work lead us to needing the tree programmatically as well. Presumably, the tree will help us definitely nailing our attempts at reconciling Clojure CLI with Nix mentioned in [this post](https://ask.clojure.org/index.php/11644/re-building-without-internet-access-with-nix)

Hence, TDEPS-225 is welcome so that getting the tree is less hack-ish :)
To add to Adam's remark:

We found that the info contained in (:libs deps/create-basis) is not sufficient to pre-fetch all the things needed to let classpath resolution run fully offline.

The issue is that there is no trace of superseded library versions that were encountered during the resolution process.
That sounds fine, because the final basis will not use them, but while trying to generate a classpath, t.d.a will still at least want to look at the POM files for these superseded deps.
I extracted out a new function to calculate the trace in clojure.tools.deps.alpha.tree/calc-trace that can be combined with the existing ctda.tree/trace->tree to get the data. Will be in next release.