Skip to content

Instantly share code, notes, and snippets.

@CraZySacX
Last active November 24, 2020 19:23
Show Gist options
  • Save CraZySacX/10138634 to your computer and use it in GitHub Desktop.
Save CraZySacX/10138634 to your computer and use it in GitHub Desktop.
Clojure git wrapper
(ns org.ozias.git
(:require [me.raynes.conch :refer (with-programs)]))
(def ^:private git-porcelain
["add" "am" "bisect" "branch" "bundle" "checkout" "cherry-pick" "citool"
"clean" "clone" "commit" "describe" "diff" "fetch" "format-patch"
"gc" "grep" "gui" "init" "log" "merge" "mv" "notes" "pull" "push"
"rebase" "reset" "revert" "rm" "shortlog" "show" "stash" "status"
"submodule" "tag"])
(def ^:private git-ancillary-manipulators
["config" "fast-export" "fast-import" "filter-branch" "lost-found" "mergetool"
"packs-refs" "prune" "reflog" "relink" "remote" "repack" "replace" "repo-config"])
(def ^:private git-ancillary-interrogators
["annotate" "blame" "cherry" "count-objects" "difftool" "fsck" "get-tar-commit-id"
"help" "instaweb" "merge-tree" "rerere" "rev-parse" "show-branch" "verify-tag"
"whatchanged"])
(def ^:private git-interop
["archimport" "cvsexportcommit" "cvsimport" "cvsserver" "imap-send" "p4"
"quiltimport" "request-pull" "send-email" "svn"])
(def ^:private git-low-level-manipulators
["apply" "checkout-index" "commit-tree" "hash-object" "index-pack" "merge-file"
"merge-index" "mktag" "mktree" "pack-objects" "prune-packed" "read-tree"
"symbolic-ref" "unpack-objects" "update-index" "update-ref" "write-tree"])
(def ^:private git-low-level-interrogators
["cat-file" "diff-files" "diff-index" "diff-tree" "for-each-ref" "ls-files"
"ls-remote" "ls-tree" "merge-base" "name-rev" "pack-redundant" "rev-list"
"show-index" "show-ref" "tar-tree" "unpack-file" "var" "verify-pack"])
(defn assoc-if
"Same as assoc, but skip the assoc if v is nil"
[m & kvs]
(->> kvs (partition 2) (filter second) (map vec) (into m)))
(defn git [cmd & {:keys [dir verbose seq in out err timeout buffer]}]
(with-programs [git]
(fn [& opts]
(let [cmd (conj opts cmd)]
(->> (assoc-if {} :dir dir :verbose verbose :seq seq :in in :out out
:err err :timeout timeout :buffer buffer)
(conj (vec cmd))
(apply git))))))
(defmacro ^:private def-gitfn [cmd]
`(defn ~(symbol (str "git-" cmd)) [& {:keys [~'dir ~'verbose ~'seq ~'in ~'out ~'err ~'timeout ~'buffer]}]
(git ~cmd :dir ~'dir :verbose ~'verbose :seq ~'seq
:in ~'in :out ~'out :err ~'err :timeout ~'timeout :buffer ~'buffer)))
(defmacro ^:private def-gitfns []
`(do ~@(map (fn [cmd] `(def-gitfn ~cmd)) git-porcelain)
~@(map (fn [cmd] `(def-gitfn ~cmd)) git-ancillary-manipulators)
~@(map (fn [cmd] `(def-gitfn ~cmd)) git-ancillary-interrogators)
~@(map (fn [cmd] `(def-gitfn ~cmd)) git-interop)
~@(map (fn [cmd] `(def-gitfn ~cmd)) git-low-level-manipulators)
~@(map (fn [cmd] `(def-gitfn ~cmd)) git-low-level-interrogators)))
(def-gitfns)
@CraZySacX
Copy link
Author

Basic usage

((git-status)) ; run git status in the current directory
((git-status :verbose true)) ; run git stats verbosely in the current directory
((git-status :dir "otherdir")) ; run git status in otherdir
((git-status :dir "otherdir" :verbose true)) ; run git status verbosely in otherdir
((git-status) "-s") ; run git status -s in the current directory

; Note when running verbose, the result will be a map containing various keys as defined by the conch library.
; Otherwise, the value returned will be stdout, or a lazy seq if :seq true was set.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment