Currently, "ls dependencies" just outputs a flat list of package names and versions of all transitive dependencies of a project. However, it would be nice to maintain the tree hierarchy of dependencies to see their parent / child relationship. On the console, the tree output could look similar to Maven's mvn dependency:tree output, but ideally there would also be an option to output to a machine readable format like JSON.
Hello @sschuberth . That sounds like a helpful enhancement. How much of what you would like to do can you achieve with stack dot --external (perhaps with --include-base, too)?
I was thinking about (mis-)using stack dot, too, but while it basically provides the parent -> child relationship, it's a bit inconvenient to parse, also because it repeats the parent for each child. The versions are missing, too, but together with the output from stack ls dependencies I could probably get what I want. I'll give it a try.
That's all useful to know. It may be relatively straightforward to reuse the code required for the dot output. Would you be willing to contribute a PR yourself?
I'm sorry, I'm not a Haskell guy (and I don't intend to become one π), I'm just trying to add basic Haskell support to the OSS Review Toolkit.
Oh, that's an interesting project. Is there anything else that would be helpful for you to achieve that, from stack?
It might also be possible for you to do what you intend using the hackage or stackage APIs directly (depending on scale), though they are quite limited. If stack meets your other requirements, then great.
Is there anything else that would be helpful for you to achieve that, from stack?
Thanks for asking. Besides listing dependencies as a tree (optionally in a machine readable format), it would be nice if the shown meta-data would not only include the name and version, but also the dependency's declared license (as an SPDX identifier). That would be the very minimum, IMO. More meta-data like the download URL would also be interesting and could be added, or simply a link to the respective hackage or stackage (REST?) APIs endpoints where more information can be gathered by the client (the program using the meta-data output) on demand.
In general, from a performance perspective it would be nice if all this meta-data could be gathered without internally downloading and unpacking the whole (source code of a) package, i.e. ideally meta-data for a package and the package itself should be separated, similar to Maven POM and JAR files.
using the hackage or stackage APIs directly
While I've found http://hackage.haskell.org/api, I didn't find something similar for stackage. Is there? Edit: I just found https://groups.google.com/forum/#!topic/stackage/9h_RA-jNz_g.
Perhaps we should broaden the issue, then. It seems like a useful addition, though it may not be a priority for the core team.
So to summarize,
[ ] List license as SPDX in addition to name and version
Most cabal files don't use these identifiers; internally Cabal (which processes these files and is different to cabal-install, the provider of the command line program cabal) uses an enumeration, though, so you may wish to take a look thee.
[ ] List URI too
In general, from a performance perspective it would be nice if all this meta-data could be gathered without internally downloading and unpacking the whole (source code of a) package, i.e. ideally meta-data for a package and the package itself should be separated, similar to Maven POM and JAR files.
stack downloads and unpacks the hackage tarball (~100MB compressed), which contains the cabal files where the metadata is located; this might update incrementally (I've never investigated). The cabal files themselves are reachable directly (/package/:package/:cabal.cabal). So the trade-off is a space vs latency one. If you're happy with the space use, stack would be useful for this.
I didn't find something similar for stackage
I think I might have just tried the hackage endpoints when I was looking for snapshot informationβ¦ or I may have checked the api calls in the debugger. I think the hackage api is most relevant, though β I only needed stackage because of stack snapshots. That said, it may be useful to add the hackage mirrors, if you go that way.
@borsboom β it may be worth supporting this enhancement to support the OSS review toolkit project mentioned earlier.
I'm very much in favour. I've often wished for an ls-dependencies that shows the tree structure. That said, I'm going to un-assign myself as it's very unlikely I'll actually be able to work on implementing it.
$ cargo tree
lefortovo v0.1.0 (file:///home/callen/work/lefortovo)
βββ bytes v0.4.8
β βββ byteorder v1.0.0
β βββ iovec v0.1.2
β βββ libc v0.2.42
βββ clap v2.25.0
β βββ ansi_term v0.9.0
β βββ atty v0.2.2
β β βββ libc v0.2.42 (*)
β βββ bitflags v0.9.1
β βββ strsim v0.6.0
β βββ term_size v0.3.0
β β βββ libc v0.2.42 (*)
β βββ textwrap v0.6.0
β β βββ term_size v0.3.0 (*)
β β βββ unicode-width v0.1.4
β βββ unicode-segmentation v1.1.0
β βββ unicode-width v0.1.4 (*)
β βββ vec_map v0.8.0
βββ hyper v0.12.5
β βββ bytes v0.4.8 (*)
β βββ futures v0.1.21
β βββ futures-cpupool v0.1.8
β β βββ futures v0.1.21 (*)
β β βββ num_cpus v1.6.2
β β βββ libc v0.2.42 (*)
β βββ h2 v0.1.10
β β βββ byteorder v1.0.0 (*)
β β βββ bytes v0.4.8 (*)
β β βββ fnv v1.0.6
β β βββ futures v0.1.21 (*)
β β βββ http v0.1.7
β β β βββ bytes v0.4.8 (*)
β β β βββ fnv v1.0.6 (*)
β β β βββ itoa v0.4.1
β β βββ indexmap v1.0.1
β β βββ log v0.4.3
β β β βββ cfg-if v0.1.4
β β βββ slab v0.4.0
β β βββ string v0.1.0
β β βββ tokio-io v0.1.7
β β βββ bytes v0.4.8 (*)
β β βββ futures v0.1.21 (*)
β β βββ log v0.4.3 (*)
β βββ http v0.1.7 (*)
β βββ httparse v1.2.3
β βββ iovec v0.1.2 (*)
β βββ itoa v0.4.1 (*)
β βββ log v0.4.3 (*)
β βββ net2 v0.2.33
β β βββ cfg-if v0.1.4 (*)
β β βββ libc v0.2.42 (*)
β βββ time v0.1.37
β β βββ libc v0.2.42 (*)
β βββ tokio v0.1.7
β β βββ futures v0.1.21 (*)
β β βββ mio v0.6.14
β β β βββ iovec v0.1.2 (*)
β β β βββ lazycell v0.6.0
β β β βββ libc v0.2.42 (*)
β β β βββ log v0.4.3 (*)
β β β βββ net2 v0.2.33 (*)
β β β βββ slab v0.4.0 (*)
β β βββ tokio-executor v0.1.2
β β β βββ futures v0.1.21 (*)
β β βββ tokio-fs v0.1.1
β β β βββ futures v0.1.21 (*)
β β β βββ tokio-io v0.1.7 (*)
β β β βββ tokio-threadpool v0.1.4
β β β βββ crossbeam-deque v0.3.1
β β β β βββ crossbeam-epoch v0.4.3
β β β β β βββ arrayvec v0.4.7
β β β β β β βββ nodrop v0.1.12
β β β β β βββ cfg-if v0.1.4 (*)
β β β β β βββ crossbeam-utils v0.3.2
β β β β β β βββ cfg-if v0.1.4 (*)
β β β β β βββ lazy_static v1.0.1
β β β β β βββ memoffset v0.2.1
β β β β β βββ scopeguard v0.3.3
β β β β βββ crossbeam-utils v0.3.2 (*)
β β β βββ futures v0.1.21 (*)
β β β βββ log v0.4.3 (*)
β β β βββ num_cpus v1.6.2 (*)
β β β βββ rand v0.4.2
β β β β βββ libc v0.2.42 (*)
β β β βββ tokio-executor v0.1.2 (*)
β β β [dev-dependencies]
β β β βββ tokio-io v0.1.7 (*)
β β βββ tokio-io v0.1.7 (*)
β β βββ tokio-reactor v0.1.2
β β β βββ futures v0.1.21 (*)
β β β βββ log v0.4.3 (*)
β β β βββ mio v0.6.14 (*)
β β β βββ slab v0.4.0 (*)
β β β βββ tokio-executor v0.1.2 (*)
β β β βββ tokio-io v0.1.7 (*)
β β βββ tokio-tcp v0.1.0
β β β βββ bytes v0.4.8 (*)
β β β βββ futures v0.1.21 (*)
β β β βββ iovec v0.1.2 (*)
β β β βββ mio v0.6.14 (*)
β β β βββ tokio-io v0.1.7 (*)
β β β βββ tokio-reactor v0.1.2 (*)
β β βββ tokio-threadpool v0.1.4 (*)
β β βββ tokio-timer v0.2.4
β β β βββ futures v0.1.21 (*)
β β β βββ tokio-executor v0.1.2 (*)
β β βββ tokio-udp v0.1.1
β β βββ bytes v0.4.8 (*)
β β βββ futures v0.1.21 (*)
β β βββ log v0.4.3 (*)
β β βββ mio v0.6.14 (*)
β β βββ tokio-codec v0.1.0
β β β βββ bytes v0.4.8 (*)
β β β βββ futures v0.1.21 (*)
β β β βββ tokio-io v0.1.7 (*)
β β βββ tokio-io v0.1.7 (*)
β β βββ tokio-reactor v0.1.2 (*)
β βββ tokio-executor v0.1.2 (*)
β βββ tokio-io v0.1.7 (*)
β βββ tokio-reactor v0.1.2 (*)
β βββ tokio-tcp v0.1.0 (*)
β βββ tokio-timer v0.2.4 (*)
β βββ want v0.0.5
β βββ futures v0.1.21 (*)
β βββ log v0.4.3 (*)
β βββ try-lock v0.2.2
βββ hyper-tls v0.2.1
β βββ bytes v0.4.8 (*)
β βββ futures v0.1.21 (*)
β βββ hyper v0.12.5 (*)
β βββ native-tls v0.1.4
β β βββ openssl v0.9.14
β β βββ bitflags v0.9.1 (*)
β β βββ foreign-types v0.2.0
β β βββ lazy_static v0.2.8
β β βββ libc v0.2.42 (*)
β β βββ openssl-sys v0.9.14
β β βββ libc v0.2.42 (*)
β β [build-dependencies]
β β βββ gcc v0.3.51
β β βββ pkg-config v0.3.9
β βββ tokio-io v0.1.7 (*)
β βββ tokio-tls v0.1.4
β βββ futures v0.1.21 (*)
β βββ native-tls v0.1.4 (*)
β βββ tokio-core v0.1.17
β β βββ bytes v0.4.8 (*)
β β βββ futures v0.1.21 (*)
β β βββ iovec v0.1.2 (*)
β β βββ log v0.4.3 (*)
β β βββ mio v0.6.14 (*)
β β βββ scoped-tls v0.1.0
β β βββ tokio v0.1.7 (*)
β β βββ tokio-executor v0.1.2 (*)
β β βββ tokio-io v0.1.7 (*)
β β βββ tokio-reactor v0.1.2 (*)
β β βββ tokio-timer v0.2.4 (*)
β βββ tokio-io v0.1.7 (*)
βββ pretty_env_logger v0.2.3
β βββ ansi_term v0.11.0
β βββ env_logger v0.5.10
β β βββ atty v0.2.2 (*)
β β βββ humantime v1.1.1
β β β βββ quick-error v1.2.2
β β βββ log v0.4.3 (*)
β β βββ regex v1.0.1
β β β βββ aho-corasick v0.6.5
β β β β βββ memchr v2.0.1
β β β β βββ libc v0.2.42 (*)
β β β βββ memchr v2.0.1 (*)
β β β βββ regex-syntax v0.6.1
β β β β βββ ucd-util v0.1.1
β β β βββ thread_local v0.3.5
β β β β βββ lazy_static v1.0.1 (*)
β β β β βββ unreachable v1.0.0
β β β β βββ void v1.0.2
β β β βββ utf8-ranges v1.0.0
β β βββ termcolor v0.3.6
β βββ log v0.4.3 (*)
βββ tokio-core v0.1.17 (*)
cargo tree has nice output. Cf. https://github.com/sfackler/cargo-tree
I think stack ls dependencies needs to go unchanged as other tools reuse the output for things like license checking, but a --tree flag or similar would be nice.
And so do Maven (mvn dependency:tree), Gradle (gradle dependencies), and several other package managers / dependency tools / build systems / whatever you call them...
NPM does as well:
$ npm ls | head
[email protected] /home/christopher/dev/proj
βββ [email protected]
βββ¬ [email protected]
β βββ¬ [email protected]
β β βββ¬ [email protected]
β β β βββ [email protected]
β β β βββ [email protected]
β β β βββ¬ [email protected]
β β β β βββ [email protected]
β β β βββ¬ [email protected]
@sschuberth I'm sure you've seen stack ls dependencies --license? It's not SPDX format afaik, but may still be a useful interim solution.
$ stack ls dependencies --separator=- --license | head
Cabal-BSD3
HTTP-BSD3
HUnit-BSD3
HsOpenSSL-PublicDomain
JuicyPixels-BSD3
MonadRandom-OtherLicense
QuickCheck-BSD3
RSA-BSD3
SHA-BSD3
StateVar-BSD3
@borsboom Why does --license discard the version number?
The problem with NPM is that it can only show the tree for installed dependencies. But ideally I'd like to see the list / tree of dependencies before I even install them. Maven and Gradle can do that just fine.
Thanks @creichert, I've seen stack ls dependencies --license, but I've already implemented a solution that uses a mix of calling stack and parsing *.cabal files directly from Hackage.
I was exploring the newcomer friendly tag and came across this. It looks interesting and also seem like nobody is try to implement this feature. I am going to take a dig at implementing this, please give me a shout if somebody is already doing it.
@akshaymankar For machine readable output I suggest json (unless @sschuberth has a better suggestion). It might be simple enough to implement some aeson instances and then plumb them in.
SPDX is well defined.
For the URI, I'm not sure what to go with. I don't really understand the use case, so perhaps @sschuberth can explain.
JSON is indeed fine from my perspective. But if e.g. more common in the Haskell community, YAML could be another option.
URI / URL was referring to the direct download location for the source code to the package. At the example of the memory package version 0.14.11, the URL would be https://hackage.haskell.org/package/memory-0.14.11/memory-0.14.11.tar.gz. The use-case is to perform automated license checks by scanning the source code of the package.
The URL in the JSON doesn't really work, because a package could either be from hackage, a local package, an archive specified by URL or a git repository. So, I guess a URL to a will not always be possible.
I am not sure what the best possible format for this would be. @sschuberth, do you have any suggestions/preferences?
@dbaynard I also couldn't find a place where stack figures out URL from PakcageLocation object. Can you please point me to it, so I don't invent the logic again.
@akshaymankar what's the problem to use file:// for local packages and git:// for git?
And I think you'll need a custom function for that, I don't think there's already some code doing that.
I was also about to say a URL should work:
file:// URLgit:// protocol (as that protocol offers no authentication). So either we come up with a convention that says that http(s) URLs that refer to Git repos have to end in .git (which is the common case anyway), or we introduce some additional meta-data field to indicate which type of URL this is. If packages are never going to be hosted in some other VCS than Git, the former approach would probably work fine. But e.g. for Mercurial there is no convention that the http(s) URL to a Mercurial repo should end in .hg, and we'd need the second approach of additional meta-data.@dbaynard I also couldn't find a place where stack figures out URL from PakcageLocation object. Can you please point me to it, so I don't invent the logic again.
And I think you'll need a custom function for that, I don't think there's already some code doing that.
I think @qrilka was answering the question you asked of me.
I think file:// is a good idea for local packages.
For git and hg repositories, even if we go with any URL specification, we still won't be able to show the commit in the URL. So, I'm leaning towards the second approach of additional metadata.
Maybe it could look something like this for git (and similar for hg):
{
"name": "foo",
"version": "1.0.0.0",
"license": "MIT",
"location": {
"type": "git",
"url": "<URL provided by user>",
"commit": "<sha>"
}
}
For hackage:
{
"name": "foo",
"version": "1.0.0.0",
"license": "MIT",
"location": {
"type": "hackage",
"url": "<computed hackage URL>"
}
}
Most helpful comment
I think
file://is a good idea for local packages.For git and hg repositories, even if we go with any URL specification, we still won't be able to show the commit in the URL. So, I'm leaning towards the second approach of additional metadata.
Maybe it could look something like this for git (and similar for hg):
For hackage: