This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-15
Channels
- # announcements (2)
- # beginners (13)
- # calva (17)
- # cider (21)
- # clerk (3)
- # clojure (42)
- # clojure-austin (1)
- # clojure-doc (8)
- # clojure-europe (82)
- # datahike (1)
- # deps-new (13)
- # emacs (5)
- # fulcro (3)
- # hyperfiddle (7)
- # missionary (1)
- # off-topic (16)
- # portal (6)
- # releases (1)
- # shadow-cljs (3)
- # tools-build (1)
- # vim (7)
- # xtdb (3)
they don't have any necessary relationship, so no
assuming there even is a Maven library name
I understand that sometimes there isn't a relationship, but for cases when there is, I'd like to be able to make the connection.
I'm ultimately looking for a way to determine from a lib repo's GitHub URL whether that lib is used as a dependency in a sample deps.edn
file.
published maven artifacts usually have scm info in their pom (always for Maven central) which may include the github url
so you could look up the pom for every Maven dep, and check it's scm url
for example, tools.build has both. in it's pom https://repo1.maven.org/maven2/io/github/clojure/tools.build/0.9.6/tools.build-0.9.6.pom there is <scm><url> of [email protected]:clojure/tools.build.git
If that info isn't there, is it reasonable to assume that the :git/lib name is the predominant way the library would be included in the deps.edn file?
@U0NCTKEV8 aren't the options just git, local, and Maven? Why isn't it a reasonable assumption?
There are many repos, many git repos, scm is optional, maven group and artifact name has no relation to git repo url
As Alex said, Maven's pom -> Github repo is kinda possible sometimes. The other way around is not quite.
Yeah, I think the Clojars feed file contains that particular connection most of the time. https://github.com/clojars/clojars-web/wiki/Data#useful-extracts-from-the-poms
You can, hypothetically, search Clojars using the name of the Github repo as the query, then iterate over all responses (as there could be several of them) and check for <scm> tag in the pom if you can get a match.
I'm thinking to use that POM extract info from Clojars as first priority, followed by the assumption that the :git/lib as a second priority is the most likely candidate, and calling it a day from there. Does it seem like a fair heuristic? Best effort is indeed the criteria.
I didn't quite understand what are your inputs, tbh. What info do you have and what do you need to obtain?
I have a list of Clojure libraries hosted on GitHub and their GitHub URL, along with a sample deps.edn
file. I want to understand which of the libraries is being used in the deps.edn
file.
Essentially, for some particular Clojure project with a deps.edn
file, I'm trying to determine the GitHub URLs of its dependencies, when available. I recognize that it's not always available.
I'm using the Clojars feed with POM extracts as a helper source.
I see. Then, all the dependencies in that deps.edn
file would either be io.github.*
which immediately gives you the repo, or a :mvn/version
dependency that you can download a POM file for, parse it as XML, and search for <scm>
or <url>
tag.
Just FYI, don't even need to use any special API, poms can be obtained by direct URL, e.g. https://repo.clojars.org/cheshire/cheshire/1.0.2/cheshire-1.0.2.pom
Why does calling .fexpr
throw an error when extending a protocol but work when not?
This is very interesting. I think what happens is that in the first case, you are calling a method fexpr()
(via reflection), and in the second case it tries to access a field, which is private.
Using clj-java-decompiler:
(decompile (.fexpr invoke-expr))
...
public static void load() {
Reflector.invokeNoArgInstanceMember(cjd__init.__user_invoke_expr.getRawRoot(), "fexpr", false);
}
(decompile (extend-protocol P clojure.lang.Compiler$InvokeExpr (f [this] (.fexpr this))))
...
public static Object invokeStatic(final Object this) {
return ((Compiler.InvokeExpr)this).fexpr;
}
My bad, there is no fexpr()
method there. But the difference is certainly in reflection.
See the difference between:
user=> (clojure.lang.Reflector/getInstanceField invoke-expr "fexpr")
#object[clojure.lang.Compiler$FnExpr 0x7a1f45ed "clojure.lang.Compiler$FnExpr@7a1f45ed"]
user=> (.fexpr ^clojure.lang.Compiler$InvokeExpr invoke-expr)
Execution error (IllegalAccessError) at user/eval7288 (REPL:1).
tried to access class clojure.lang.Compiler$InvokeExpr from class user$eval7288
Thanks! That makes sense. I should've thought of decompiling. ð Except that I thought that fexpr
was public, but I must've misread.
It looks like, having default
visibility for a nested class prevents normal access to it while letting reflective access.
Very helpful, thanks! Looks like I have to manually reflect when extending the protocol, then.
It's a weird interaction you've discovered, saving this for some conference gotcha/puzzler in the future ð
when doing the reflective lookup it is code in the clojure.lang package that is doing it, but when not doing it reflectively the compiled code doesn't live in the clojure.lang package
Are there any good resources/blogs/videos that take you through how the clojure compiler works?
There's a decent list here: https://clojureverse.org/t/resources-for-learning-how-the-clojure-compiler-works/9059 (well, by "decent", what I mean is "this seems to be all there is") The last link, the video with Mike Fikes, is extremely good, but it's about the Clojurescript compiler. If you find that useful, you'll also enjoy Fogus' Clojurescript Anatomy talk, and accompanying blog posts