Skip to content

Instantly share code, notes, and snippets.



Last active Dec 17, 2015
What would you like to do?
Storing a parse tree, or AST, in a git repository with Clojure and JGit
(ns gittree.core
(:require [ :refer [as-file]]
[instaparse.core :as insta]
[net.cgrand.enlive-html :as enlive]
[clojure.walk :as walk]
[clj-jgit.porcelain :as git])
(:import [gittree TreeIterator])
(defn render [nodes]
(walk/postwalk #(if (and (map? %) (:tag %))
(hash-map (:tag %) (:content %))
%) nodes))
(defn transform-data [data]
(enlive/at data
;[:S] enlive/unwrap
[:A] nil ;remove A nodes
(def parse (insta/parser
"S = AB*
AB = A B
A = 'a'+
B = 'b'+"
:output-format :enlive))
(defn -main [& args]
(let [dir (as-file "/Users/user1/Desktop/testrepo")
text "aaaaabbbaaaabb"
g (if (.exists dir)
(git/load-repo dir)
(git/git-init dir))
data (render (transform-data (parse text)))
itr (TreeIterator. (.getRepository g) data)]
(println text)
(println data)
(git/git-add g "." false itr)
(git/git-commit g "commit 1")))
(defproject gittree "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url ""
:license {:name "Eclipse Public License"
:url ""}
:dependencies [[org.clojure/clojure "1.5.1"]
[clj-jgit "0.3.9"]
[instaparse "1.2.2"]
[enlive "1.1.1"]]
:main gittree.core
:aot [gittree.TreeIterator])
(ns gittree.TreeIterator
(:import [org.eclipse.jgit.lib Repository FileMode]
[org.eclipse.jgit.treewalk WorkingTreeIterator WorkingTreeIterator$Entry WorkingTreeOptions]
[ ByteArrayInputStream])
(:gen-class :extends org.eclipse.jgit.treewalk.WorkingTreeIterator
:init init2
:post-init postinit
:state state
:constructors {[org.eclipse.jgit.lib.Repository Object] [org.eclipse.jgit.treewalk.WorkingTreeOptions]
[org.eclipse.jgit.lib.Repository Object org.eclipse.jgit.treewalk.WorkingTreeIterator] [org.eclipse.jgit.treewalk.WorkingTreeIterator]}))
(gen-interface :name gittree.IHasValue
:methods [[getValue [] Object]])
(defn toEntry
([[k v]] (toEntry k v))
([k v]
(let [node-name (if (keyword? k) (name k) (str k))
node-mode (if (coll? v) FileMode/TREE FileMode/REGULAR_FILE)
node-modified 0
node-value (if (string? v) (.getBytes v) (byte-array 0))
node-length (count node-value)]
(proxy [WorkingTreeIterator$Entry gittree.IHasValue] []
(getMode [] node-mode)
(getName [] node-name)
(getLength [] node-length)
(getLastModified [] node-modified)
(openInputStream [] (ByteArrayInputStream. node-value))
(getValue [] v)))))
(defn -init2
([^Repository repo data]
(let [options (-> repo (.getConfig) (.get WorkingTreeOptions/KEY))]
[[options] {:repo repo}]))
([^Repository repo data ^WorkingTreeIterator itr]
[[itr] {:repo repo}]))
(defn -postinit
([this repo data] (-postinit this repo data nil))
([this repo data _]
(let [entries (if (map? data) (map toEntry data) (map-indexed toEntry data))]
(.initRootIterator this repo)
(.init this (into-array WorkingTreeIterator$Entry entries)))))
(defn -createSubtreeIterator [this reader idBuffer]
(let [repo (:repo (.state this))]
(gittree.TreeIterator. repo (.getValue (.current this)) this)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.