cabal-plan icon indicating copy to clipboard operation
cabal-plan copied to clipboard

Implement `why-depends` command

Open fendor opened this issue 5 years ago • 11 comments

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

fendor avatar Apr 11 '20 16:04 fendor

Ping. This feature is nice and you should have it, too :)

fendor avatar Jun 22 '20 21:06 fendor

Ping. Because I just found myself wanting this.

AndreasPK avatar Jan 11 '21 12:01 AndreasPK

@phadej Would you mind reviewing this PR?

fendor avatar Jun 14 '21 19:06 fendor

@fendor: Time for the next ping.

andreasabel avatar Nov 13 '21 11:11 andreasabel

could be this part of the incoming cabal info?, i guess, maybe it will be available sooner there than here 😝

jneira avatar Nov 13 '21 11:11 jneira

@fendor : The hackage maintainer for cabal-plan is @phadej. My capabilities are restricted to this repo.

@phadej : What's your plan with cabal-plan?

andreasabel avatar Sep 26 '23 09:09 andreasabel

@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 avatar Sep 26 '23 09:09 andreasabel

@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.

phadej avatar Sep 26 '23 12:09 phadej

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.

fendor avatar Sep 27 '23 13:09 fendor

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).

phadej avatar Sep 27 '23 13:09 phadej

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.

sellout avatar Aug 25 '24 17:08 sellout