Skip to content

Instantly share code, notes, and snippets.

Last active December 17, 2015 18:49
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