-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move
rads.deps-info
into babashka.bbin.deps
- Loading branch information
Showing
6 changed files
with
305 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
(ns babashka.bbin.deps | ||
(:require [babashka.fs :as fs] | ||
[clojure.edn :as edn] | ||
[clojure.set :as set] | ||
[clojure.tools.gitlibs.impl :as gitlibs-impl] | ||
[babashka.bbin.git :as git])) | ||
|
||
(def lib-opts->template-deps-fn | ||
"A map to define valid CLI options. | ||
- Each key is a sequence of valid combinations of CLI opts. | ||
- Each value is a function which returns a tools.deps lib map." | ||
{[#{:local/root}] | ||
(fn [_ lib-sym lib-opts] | ||
{lib-sym (select-keys lib-opts [:local/root])}) | ||
|
||
[#{} #{:git/url}] | ||
(fn [client lib-sym lib-opts] | ||
(let [url (or (:git/url lib-opts) (git/git-repo-url client lib-sym)) | ||
tag (git/latest-git-tag client url)] | ||
(if tag | ||
{lib-sym {:git/url url | ||
:git/tag (:name tag) | ||
:git/sha (-> tag :commit :sha)}} | ||
(let [sha (git/latest-git-sha client url)] | ||
{lib-sym {:git/url url | ||
:git/sha sha}})))) | ||
|
||
[#{:git/tag} #{:git/url :git/tag}] | ||
(fn [client lib-sym lib-opts] | ||
(let [url (or (:git/url lib-opts) (git/git-repo-url client lib-sym)) | ||
tag (:git/tag lib-opts) | ||
{:keys [commit]} (git/find-git-tag client url tag)] | ||
{lib-sym {:git/url url | ||
:git/tag tag | ||
:git/sha (:sha commit)}})) | ||
|
||
[#{:git/sha} #{:git/url :git/sha}] | ||
(fn [client lib-sym lib-opts] | ||
(let [url (or (:git/url lib-opts) (git/git-repo-url client lib-sym)) | ||
sha (:git/sha lib-opts)] | ||
{lib-sym {:git/url url | ||
:git/sha sha}})) | ||
|
||
[#{:latest-sha} #{:git/url :latest-sha}] | ||
(fn [client lib-sym lib-opts] | ||
(let [url (or (:git/url lib-opts) (git/git-repo-url client lib-sym)) | ||
sha (git/latest-git-sha client url)] | ||
{lib-sym {:git/url url | ||
:git/sha sha}})) | ||
|
||
[#{:git/url :git/tag :git/sha}] | ||
(fn [_ lib-sym lib-opts] | ||
{lib-sym (select-keys lib-opts [:git/url :git/tag :git/sha])})}) | ||
|
||
(def valid-lib-opts | ||
"The set of all valid combinations of CLI opts." | ||
(into #{} cat (keys lib-opts->template-deps-fn))) | ||
|
||
(defn- cli-opts->lib-opts | ||
"Returns parsed lib opts from raw CLI opts." | ||
[cli-opts] | ||
(-> cli-opts | ||
(set/rename-keys {:sha :git/sha}) | ||
(select-keys (into #{} cat valid-lib-opts)))) | ||
|
||
(defn- find-template-deps-fn | ||
"Returns a template-deps-fn given lib-opts parsed from raw CLI opts." | ||
[lib-opts] | ||
(some (fn [[k v]] (and (contains? (set k) (set (keys lib-opts))) v)) | ||
lib-opts->template-deps-fn)) | ||
|
||
(defn- invalid-lib-opts-error [provided-lib-opts] | ||
(ex-info (str "Provided invalid combination of CLI options") | ||
{:provided-opts (set (keys provided-lib-opts)) | ||
:valid-combinations valid-lib-opts})) | ||
|
||
(def ^:private default-deps-info-client | ||
{:ensure-git-dir gitlibs-impl/ensure-git-dir | ||
:git-fetch gitlibs-impl/git-fetch}) | ||
|
||
(defn infer | ||
"Returns a tools.deps lib map for the given CLI opts." | ||
([cli-opts] (infer nil cli-opts)) | ||
([client cli-opts] | ||
(let [client (merge default-deps-info-client client) | ||
lib-opts (cli-opts->lib-opts cli-opts) | ||
lib-sym (edn/read-string (:lib cli-opts)) | ||
template-deps-fn (find-template-deps-fn lib-opts)] | ||
(if-not template-deps-fn | ||
(throw (invalid-lib-opts-error lib-opts)) | ||
(template-deps-fn client lib-sym lib-opts))))) | ||
|
||
(def ^:private symbol-regex | ||
(re-pattern | ||
(str "(?i)^" | ||
"(?:((?:[a-z0-9-]+\\.)*[a-z0-9-]+)/)?" | ||
"((?:[a-z0-9-]+\\.)*[a-z0-9-]+)" | ||
"$"))) | ||
|
||
(defn- lib-str? [x] | ||
(boolean (and (string? x) (re-seq symbol-regex x)))) | ||
|
||
(defn- local-script-path? [x] | ||
(boolean (and (string? x) (fs/exists? x)))) | ||
|
||
(defn- http-url? [x] | ||
(boolean (and (string? x) (re-seq #"^https?:https://" x)))) | ||
|
||
(defn- git-ssh-url? [x] | ||
(boolean (and (string? x) (re-seq #"^.+@.+:.+\.git$" x)))) | ||
|
||
(defn- git-http-url? [x] | ||
(boolean (and (string? x) (re-seq #"^https?:https://.+\.git$" x)))) | ||
|
||
(defn git-repo-url? [s] | ||
(or (git-http-url? s) (git-ssh-url? s))) | ||
|
||
(def ^:private deps-types | ||
[{:lib lib-str? | ||
:coords #{:local/root} | ||
:procurer :local} | ||
|
||
{:lib lib-str? | ||
:coords #{:mvn/version} | ||
:procurer :maven} | ||
|
||
{:lib local-script-path? | ||
:coords #{:bbin/url} | ||
:procurer :local} | ||
|
||
{:lib #(or (git-http-url? %) (git-ssh-url? %)) | ||
:coords #{:bbin/url} | ||
:procurer :git} | ||
|
||
{:lib http-url? | ||
:coords #{:bbin/url} | ||
:procurer :http} | ||
|
||
{:lib lib-str? | ||
:coords #{:git/sha :git/url :git/tag} | ||
:procurer :git} | ||
|
||
{:lib local-script-path? | ||
:coords #{} | ||
:procurer :local} | ||
|
||
{:lib #(or (git-http-url? %) (git-ssh-url? %) (lib-str? %)) | ||
:coords #{} | ||
:procurer :git} | ||
|
||
{:lib http-url? | ||
:coords #{} | ||
:procurer :http}]) | ||
|
||
|
||
(defn- deps-type-match? [cli-opts deps-type] | ||
(and ((:lib deps-type) (:script/lib cli-opts)) | ||
(or (empty? (:coords deps-type)) | ||
(seq (set/intersection (:coords deps-type) (set (keys cli-opts))))) | ||
deps-type)) | ||
|
||
(defn- match-deps-type [cli-opts] | ||
(or (some #(deps-type-match? cli-opts %) deps-types) | ||
{:procurer :unknown-procurer})) | ||
|
||
(defn- match-artifact [cli-opts procurer] | ||
(cond | ||
(or (#{:maven} procurer) | ||
(and (#{:local} procurer) | ||
(or (and (:script/lib cli-opts) (re-seq #"\.jar$" (:script/lib cli-opts))) | ||
(and (:local/root cli-opts) (re-seq #"\.jar$" (:local/root cli-opts))))) | ||
(and (#{:http} procurer) (re-seq #"\.jar$" (:script/lib cli-opts)))) | ||
:jar | ||
|
||
(or (#{:git} procurer) | ||
(and (#{:local} procurer) | ||
(or (and (:script/lib cli-opts) (fs/directory? (:script/lib cli-opts))) | ||
(and (:local/root cli-opts) (fs/directory? (:local/root cli-opts))))) | ||
(and (#{:http} procurer) (re-seq #"\.git$" (:script/lib cli-opts)))) | ||
:dir | ||
|
||
(or (and (#{:local} procurer) (and (:script/lib cli-opts) | ||
(fs/regular-file? (:script/lib cli-opts)))) | ||
(and (#{:http} procurer) (re-seq #"\.(cljc?|bb)$" (:script/lib cli-opts)))) | ||
:file | ||
|
||
:else :unknown-artifact)) | ||
|
||
(defn summary [cli-opts] | ||
(let [{:keys [procurer]} (match-deps-type cli-opts) | ||
artifact (match-artifact cli-opts procurer)] | ||
{:procurer procurer | ||
:artifact artifact})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
(ns babashka.bbin.git | ||
(:require [clojure.string :as str] | ||
[babashka.fs :as fs] | ||
[babashka.process :refer [sh]])) | ||
|
||
(defn- ensure-git-dir [client git-url] | ||
(binding [*err* (java.io.StringWriter.)] | ||
(let [path ((:ensure-git-dir client) git-url)] | ||
((:git-fetch client) (fs/file path)) | ||
path))) | ||
|
||
(defn default-branch [client git-url] | ||
(let [lib-dir (ensure-git-dir client git-url) | ||
remote-info (sh "git remote show origin" {:dir lib-dir | ||
:extra-env {"LC_ALL" "C"}}) | ||
[[_ branch]] (->> (:out remote-info) | ||
str/split-lines | ||
(some #(re-seq #"HEAD branch: (\w+)" %)))] | ||
branch)) | ||
|
||
(defn latest-git-sha [client git-url] | ||
(let [lib-dir (ensure-git-dir client git-url) | ||
branch (default-branch client git-url) | ||
log-result (sh ["git" "log" "-n" "1" branch "--pretty=format:%H"] | ||
{:dir lib-dir})] | ||
(str/trim-newline (:out log-result)))) | ||
|
||
(defn find-git-tag [client git-url tag] | ||
(let [lib-dir (ensure-git-dir client git-url) | ||
log-result (sh ["git" "log" "-n" "1" tag "--pretty=format:%H"] | ||
{:dir lib-dir}) | ||
sha (str/trim-newline (:out log-result))] | ||
{:name (str tag) | ||
:commit {:sha sha}})) | ||
|
||
(defn latest-git-tag [client git-url] | ||
(let [lib-dir (ensure-git-dir client git-url) | ||
describe-result (sh "git describe --tags --abbrev=0" {:dir lib-dir}) | ||
tag (str/trim-newline (:out describe-result))] | ||
(when-not (str/blank? tag) | ||
(find-git-tag client git-url tag)))) | ||
|
||
(def providers | ||
{#"^(com|io)\.github\." :github | ||
#"^(com|io)\.gitlab\." :gitlab | ||
#"^(org|io)\.bitbucket\." :bitbucket | ||
#"^(com|io)\.beanstalkapp\." :beanstalk | ||
#"^ht\.sr\." :sourcehut}) | ||
|
||
(defn- clean-lib-str [lib] | ||
(->> (reduce #(str/replace %1 %2 "") lib (keys providers)) | ||
symbol)) | ||
|
||
(defn git-http-url [lib] | ||
(let [provider (some #(when (re-seq (key %) (str lib)) %) providers) | ||
s (clean-lib-str (str lib))] | ||
(case (val provider) | ||
:github (str "https://github.com/" s ".git") | ||
:gitlab (str "https://gitlab.com/" s ".git") | ||
:bitbucket (let [[u] (str/split (str s) #"/")] | ||
(str "https://" u "@bitbucket.org/" s ".git")) | ||
:beanstalk (let [[u] (str/split (str s) #"/")] | ||
(str "https://" u ".git.beanstalkapp.com/" (name lib) ".git")) | ||
:sourcehut (str "https://git.sr.ht/~" s)))) | ||
|
||
(defn git-ssh-url [lib] | ||
(let [provider (some #(when (re-seq (key %) (str lib)) %) providers) | ||
s (clean-lib-str (str lib))] | ||
(case (val provider) | ||
:github (str "[email protected]:" s ".git") | ||
:gitlab (str "[email protected]:" s ".git") | ||
:bitbucket (str "[email protected]:" s ".git") | ||
:beanstalk (let [[u] (str/split (str s) #"/")] | ||
(str "git@" u ".git.beanstalkapp.com:/" s ".git")) | ||
:sourcehut (str "[email protected]:~" s)))) | ||
|
||
(defn git-repo-url [client lib] | ||
(try | ||
(let [url (git-http-url lib)] | ||
(ensure-git-dir client url) | ||
url) | ||
(catch Exception e | ||
(if (re-seq #"^Unable to clone " (ex-message e)) | ||
(let [url (git-ssh-url lib)] | ||
(ensure-git-dir client url) | ||
url) | ||
(throw e))))) |
Oops, something went wrong.