Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Simpler DX when using this tool with custom templates. #46

Closed
rafaeldelboni opened this issue Feb 11, 2023 · 4 comments
Closed

Comments

@rafaeldelboni
Copy link
Sponsor Contributor

First of all thanks for your work on this, template tools are super useful even more when deep integrated with the current developer workflow.

But I found that using this tool with custom templates in the CLI a little bit verbose, for example:

clojure -Sdeps '{:deps {cc.delboni/helix-scratch {:git/url "https://github.com/rafaeldelboni/helix-scratch" :git/sha "8e4eb30" :git/tag "v0.1.1"}}}' -X:new :template cc.delboni/helix-scratch :name myusername/mycoolsite

Is quite a lot to type and I know that isn't case of everyday you will create a new project, but I really like when the command is something I can type by heart like was possible with clj-new and maven third-parties templates:

clojure -Tclj-new create :template cc.delboni/helix-scratch :name myusername/mycoolsite

I understand the fact of not using maven in this project, so I went ahead and searched for another similar tools that mainly use git as source of the third-party templates and I found cargo-generate.

The most interesting aspect of this tool is its CLI usage, here some examples:

cargo generate username-on-github/mytemplate
# is the same as 
cargo generate gh:username-on-github/mytemplate
# is the same as 
cargo generate --git https://github.com/username-on-github/mytemplate.git

If you have your templates not GitHub then you can leverage the lazy abbreviation prefixes:

# for gitlab.com
cargo generate gl:username-on-gitlab/mytemplate
# or for bitbucket.org
cargo generate bb:username-on-bitbucket/mytemplate
# or for github.com 
cargo generate gh:username-on-github/mytemplate

Do you think this project could fit a similar CLI "api"? I would be keen to contribute with a PR if so, we could discuss some new usage ways like for example:

clojure -X:new :template cc.delboni/helix-scratch@gh :name myusername/mycoolsite
# or
clojure -X:new :gh cc.delboni/helix-scratch :name myusername/mycoolsite

One thing cargo-generate lacks is the option to set the version or the commit hash you want from the template you will be using, but we could think some extra args for that as well.

WDYT?

@seancorfield
Copy link
Owner

Currently, deps-new does nothing for dependencies: it works with what is on the classpath already. To support what you're suggesting, it would need to be able to resolve dependencies itself, and build a new classpath based on that. In other words, it would need to duplicate some of the Clojure CLI itself -- which, as you observe, is what clj-new does.

I certainly could add this, using tools.deps and tools.gitlibs -- see https://github.com/seancorfield/dot-clojure/blob/develop/deps.edn#L115-L121 for how to resolve a branch to a SHA (but I'd have to research how to figure out the default branch since a lot of repos do not have master these days).

Part of why I created deps-new was to provide a simpler template system, that just built on tools.build and the existing CLI machinery.

Someone could build a wrapper for deps-new that provided this functionality -- and if they submitted it as a PR to enhance deps-new, I would consider it for review and possible inclusion...

@rafaeldelboni
Copy link
Sponsor Contributor Author

rafaeldelboni commented Feb 12, 2023

I was doing some experiments here, unfortunately the raw run-git is private and I don't know if this solution works in all the cases, but I will post here in order to document:

(ns cc.delboni.gitlib-poc
  (:require [clojure.string :as str]
            [clojure.tools.gitlibs.impl :as impl])
  (:gen-class))

(def run-git #'impl/run-git)

(defn git-rev-parse
  [git-dir]
  (let [{:keys [exit out]} (run-git "--git-dir" git-dir "rev-parse" "--abbrev-ref" "HEAD")]
    (when (zero? exit)
      (str/trimr out))))

(defn fetch-repository
  [url]
  (let [git-dir (impl/ensure-git-dir url)
        rev-parse (git-rev-parse git-dir)
        latest-hash (impl/git-rev-parse git-dir "HEAD")]
    {:git-dir git-dir
     :head-branch rev-parse
     :latest-hash latest-hash}))

(fetch-repository "https://github.com/clojure/clojure-site.git")
(fetch-repository "https://github.com/rafaeldelboni/helix-scratch.git")
(fetch-repository "https://github.com/seancorfield/next-jdbc.git")
(fetch-repository "https://gitlab.com/aszenz/exosphere.git")
(fetch-repository "https://bitbucket.org/fumming/todo-clj.git")

Outputs:

; --------------------------------------------------------------------------------
; eval (current-form): (fetch-repository "https://github.com/clojure/clo...
; (err) Cloning: https://github.com/clojure/clojure-site.git
{:git-dir
 "/Users/rafael.delboni/.gitlibs/_repos/https/github.com/clojure/clojure-site",
 :head-branch "master",
 :latest-hash "490e088af9d7de11ab3627c5ab566e9a8f714c25"}
; --------------------------------------------------------------------------------
; eval (current-form): (fetch-repository "https://github.com/rafaeldelbo...
; (err) Cloning: https://github.com/rafaeldelboni/helix-scratch.git
{:git-dir
 "/Users/rafael.delboni/.gitlibs/_repos/https/github.com/rafaeldelboni/helix-scratch",
 :head-branch "main",
 :latest-hash "a8121c785c6e861795113ff8c96526cae6363964"}
; --------------------------------------------------------------------------------
; eval (current-form): (fetch-repository "https://github.com/seancorfiel...
; (err) Cloning: https://github.com/seancorfield/next-jdbc.git
{:git-dir
 "/Users/rafael.delboni/.gitlibs/_repos/https/github.com/seancorfield/next-jdbc",
 :head-branch "develop",
 :latest-hash "a7833b1858ef908f69cf33b514b529ad216b297d"}
 ; --------------------------------------------------------------------------------
; eval (current-form): (fetch-repository "https://gitlab.com/aszenz/exos...
; (err) Cloning: https://gitlab.com/aszenz/exosphere.git
{:git-dir
 "/Users/rafael.delboni/.gitlibs/_repos/https/gitlab.com/aszenz/exosphere",
 :head-branch "master",
 :latest-hash "a9d26e0c364f13d15e47e2a0f747a4e3b94f8d0c"}
; --------------------------------------------------------------------------------
; eval (current-form): (fetch-repository "https://bitbucket.org/fumming/...
; (err) Cloning: https://bitbucket.org/fumming/todo-clj.git
{:git-dir
 "/Users/rafael.delboni/.gitlibs/_repos/https/bitbucket.org/fumming/todo-clj",
 :head-branch "master",
 :latest-hash "42b340686e09ec185d65c4340c0dcfb9f06e61ed"}

@seancorfield
Copy link
Owner

tools.build has https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-git-process so you don't need the private function. I'm a bit surprised you need any of that impl stuff -- once you have resolved the SHA, using the public API I linked to in my deps.edn file, you can use tools.deps to resolve the dependency. There are definitely multiple ways to make this work.

@rafaeldelboni
Copy link
Sponsor Contributor Author

I will close this issue for now, not super proud of my work, but this wrapper is working fine so far:
https://github.com/rafaeldelboni/deps-new-wrap

If you have some feedback to make it better I would love to hear.

Thanks a lot for your help here and in clojurians slack channel Sean, I really like your work and help to the community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants