cabal-plan
cabal-plan copied to clipboard
Implement `why-depends` command
Implementation idea is to re-use printing logic from dumpPlanJson and filtering the existing PlanJson to only contain packages that have in some dependency closure the given dependency.
Implementation details: uses the state monad to speed up logic (feedback welcome if this can be improved)
Example invocations:
cabal-plan why-depends exe:cabal-plan containers
Output
cabal-plan-0.6.2.0
[cabal-plan-0.6.2.0:exe:"cabal-plan"]
├─ Cabal-3.0.1.0
│ ├─ binary-0.8.7.0
│ │ └─ containers-0.6.2.1
│ ├─ containers-0.6.2.1 ┄┄
│ ├─ parsec-3.1.14.0
│ │ └─ text-1.2.4.0
│ │ └─ binary-0.8.7.0 ┄┄
│ └─ text-1.2.4.0 ┄┄
├─ async-2.2.2
│ └─ hashable-1.3.0.0
│ └─ text-1.2.4.0 ┄┄
├─ cabal-plan-0.6.2.0
│ ├─ aeson-1.4.7.1
│ │ ├─ attoparsec-0.13.2.4
│ │ │ ├─ containers-0.6.2.1 ┄┄
│ │ │ ├─ scientific-0.3.6.2
│ │ │ │ ├─ binary-0.8.7.0 ┄┄
│ │ │ │ ├─ containers-0.6.2.1 ┄┄
│ │ │ │ ├─ hashable-1.3.0.0 ┄┄
│ │ │ │ └─ text-1.2.4.0 ┄┄
│ │ │ └─ text-1.2.4.0 ┄┄
│ │ ├─ containers-0.6.2.1 ┄┄
│ │ ├─ hashable-1.3.0.0 ┄┄
│ │ ├─ scientific-0.3.6.2 ┄┄
│ │ ├─ text-1.2.4.0 ┄┄
│ │ ├─ th-abstraction-0.3.2.0
│ │ │ └─ containers-0.6.2.1 ┄┄
│ │ ├─ unordered-containers-0.2.10.0
│ │ │ └─ hashable-1.3.0.0 ┄┄
│ │ └─ uuid-types-1.0.3
│ │ ├─ binary-0.8.7.0 ┄┄
│ │ ├─ hashable-1.3.0.0 ┄┄
│ │ └─ text-1.2.4.0 ┄┄
│ ├─ containers-0.6.2.1 ┄┄
│ └─ text-1.2.4.0 ┄┄
├─ containers-0.6.2.1 ┄┄
├─ optics-core-0.2
│ └─ containers-0.6.2.1 ┄┄
├─ parsec-3.1.14.0 ┄┄
├─ semialign-1.1
│ ├─ containers-0.6.2.1 ┄┄
│ ├─ hashable-1.3.0.0 ┄┄
│ ├─ semigroupoids-5.3.4
│ │ ├─ bifunctors-5.5.7
│ │ │ ├─ comonad-5.0.6
│ │ │ │ ├─ containers-0.6.2.1 ┄┄
│ │ │ │ └─ distributive-0.6.1
│ │ │ │ [setup]
│ │ │ │ ├─ Cabal-3.0.1.0 ┄┄
│ │ │ │ └─ cabal-doctest-1.0.8
│ │ │ │ └─ Cabal-3.0.1.0 ┄┄
│ │ │ │ [setup]
│ │ │ │ ├─ Cabal-3.0.1.0 ┄┄
│ │ │ │ └─ cabal-doctest-1.0.8 ┄┄
│ │ │ ├─ containers-0.6.2.1 ┄┄
│ │ │ └─ th-abstraction-0.3.2.0 ┄┄
│ │ ├─ comonad-5.0.6 ┄┄
│ │ ├─ containers-0.6.2.1 ┄┄
│ │ ├─ distributive-0.6.1 ┄┄
│ │ ├─ hashable-1.3.0.0 ┄┄
│ │ └─ unordered-containers-0.2.10.0 ┄┄
│ │ [setup]
│ │ ├─ Cabal-3.0.1.0 ┄┄
│ │ └─ cabal-doctest-1.0.8 ┄┄
│ ├─ these-1.0.1
│ │ ├─ QuickCheck-2.14
│ │ │ └─ containers-0.6.2.1 ┄┄
│ │ ├─ aeson-1.4.7.1 ┄┄
│ │ ├─ assoc-1.0.1
│ │ │ └─ bifunctors-5.5.7 ┄┄
│ │ ├─ binary-0.8.7.0 ┄┄
│ │ ├─ hashable-1.3.0.0 ┄┄
│ │ ├─ semigroupoids-5.3.4 ┄┄
│ │ └─ unordered-containers-0.2.10.0 ┄┄
│ └─ unordered-containers-0.2.10.0 ┄┄
├─ tar-0.5.1.1
│ └─ containers-0.6.2.1 ┄┄
├─ text-1.2.4.0 ┄┄
├─ these-1.0.1 ┄┄
└─ topograph-1.0.0.1
└─ containers-0.6.2.1 ┄┄
cabal-plan why-depends exe:cabal-plan lib:cabal-plan
Output
cabal-plan-0.6.2.0
[cabal-plan-0.6.2.0:exe:"cabal-plan"]
└─ cabal-plan-0.6.2.0
Due to pattern to unit-id translation, this can also be used to get a why-depends for between dependencies
cabal-plan why-depends lib:semigroupoids lib:comonad
Output
semigroupoids-5.3.4
├─ bifunctors-5.5.7
│ └─ comonad-5.0.6
└─ comonad-5.0.6 ┄┄
Default to single target if only other target is "setup":
cabal-plan why-depends semigroupoids comonad
Output
semigroupoids-5.3.4
├─ bifunctors-5.5.7
│ └─ comonad-5.0.6
└─ comonad-5.0.6 ┄┄
Unknown target:
cabal-plan why-depends foo lib:comonad
Output
Could not find any unit with pattern: foo
Ambiguous target:
cabal-plan why-depends cabal-plan stm
Output
Ambiguous target "cabal-plan". Found the following targets:
lib:cabal-plan
exe:cabal-plan
No transitive dependency between targets.
cabal-plan why-depends hashable stm
Output
The unit hashable-1.3.0.0 does not depend on stm-2.5.0.0
Ping. This feature is nice and you should have it, too :)
Ping. Because I just found myself wanting this.
@phadej Would you mind reviewing this PR?
@fendor: Time for the next ping.
could be this part of the incoming cabal info?, i guess, maybe it will be available sooner there than here 😝
@fendor : The hackage maintainer for cabal-plan is @phadej. My capabilities are restricted to this repo.
@phadej : What's your plan with cabal-plan?
@fendor: Would it be possible to add a test along the lines of: https://github.com/haskell-hvr/cabal-plan/blob/b42d09e61d896c949403f2c05b7295d2e304ce6b/Makefile#L7-L8
@andreasabel I'm undecided about why-depends command. I acknowledge that it's useful as I often do cabal-plan tred | less and look at the package to see where it is in the graph.
And this looks like that, except that output has extra leaves...
I'd expect
cabal-plan-0.6.2.0
[cabal-plan-0.6.2.0:exe:"cabal-plan"]
├─ Cabal-3.0.1.0
│ ├─ binary-0.8.7.0
│ │ └─ containers-0.6.2.1
│ ├─ containers-0.6.2.1 ┄┄
│ └ ...
Like output (i.e. a bit terser).
Also I'm not sure about the cli UI. The cabal-plan why-depends root dependency is IMO confusing. I'd expect just cabal-plan why-depends dependency [dependency...] and then maybe optional (also n-ary) --root.
And this looks like that, except that output has extra leaves...
It doesn't have extra leaves, it doesn't print the full path to a dependency, if the path has already been explored before.
Same behaviour as cabal info has right now.
I am also not sure about the cli UI. The proposed UI makes it a bit more complicated to figure out the dependencies between a testsuite and its dependencies. However, I am also fine with it.
Ok I see, in
cabal-plan why-depends exe:cabal-plan containers
cabal-plan-0.6.2.0
[cabal-plan-0.6.2.0:exe:"cabal-plan"]
├─ Cabal-3.0.1.0
│ ├─ binary-0.8.7.0
│ │ └─ containers-0.6.2.1
│ ├─ containers-0.6.2.1 ┄┄
│ ├─ parsec-3.1.14.0
│ │ └─ text-1.2.4.0
│ │ └─ binary-0.8.7.0 ┄┄
│ └─ text-1.2.4.0 ┄┄
there is parsec - text - binary, but as binary - containers has already been printed, parsec - text - binary, nor last text should more.
This behavior makes sense for tred (cutting the graph, i.e. not printing the whole forest), but I'm unsure about why-depends. I'll have to use it a bit to see whether its fine. (containers is a bit bad example as almost everything depends on it).
I would like to see some options like cabal-plan why-depends --dot --tred dep [deps…], taking advantage of the existing implementations of the tred and dot subcommands after having pruned the graph.
But I’m also fine with those being added later. why-depends is useful regardless.