|
1 | 1 | (ns chrondb.func |
2 | | - (:require [clojure.data.json :as json] |
3 | | - [clojure.java.io :as io] |
4 | | - [clj-compress.core :as c] |
5 | | - [chrondb.config :as config]) |
6 | | - (:import (java.io ByteArrayOutputStream) |
7 | | - (org.eclipse.jgit.internal.storage.dfs InMemoryRepository$Builder DfsRepositoryDescription) |
8 | | - (org.eclipse.jgit.lib Repository PersonIdent ObjectId Constants FileMode RefUpdate$Result) |
9 | | - (org.eclipse.jgit.lib CommitBuilder TreeFormatter) |
10 | | - (org.eclipse.jgit.treewalk TreeWalk) |
11 | | - (org.eclipse.jgit.revwalk RevWalk))) |
| 2 | + (:require [clojure.data.json :as json]) |
| 3 | + (:import (org.eclipse.jgit.internal.storage.dfs InMemoryRepository$Builder DfsRepositoryDescription) |
| 4 | + (org.eclipse.jgit.lib CommitBuilder Constants FileMode ObjectId Repository TreeFormatter) |
| 5 | + (org.eclipse.jgit.revwalk RevTree) |
| 6 | + (org.eclipse.jgit.treewalk TreeWalk))) |
12 | 7 |
|
13 | 8 | (defn create-repository |
14 | | - "Create a new in-memory repository" |
15 | | - [& {:keys [branch-name] |
16 | | - :or {branch-name config/default-branch-name}}] |
17 | | - (let [repo (-> (InMemoryRepository$Builder.) |
18 | | - (.setRepositoryDescription (DfsRepositoryDescription. "chrondb")) |
19 | | - (.setInitialBranch branch-name) |
20 | | - (.build))] |
| 9 | + [path] |
| 10 | + (let [builder (doto (InMemoryRepository$Builder.) |
| 11 | + (.setRepositoryDescription (DfsRepositoryDescription. path))) |
| 12 | + repo (.build builder)] |
21 | 13 | (.create repo) |
22 | | - (with-open [inserter (.newObjectInserter repo)] |
23 | | - (let [tree-formatter (TreeFormatter.) |
24 | | - tree-id (.insert inserter tree-formatter) |
25 | | - commit (doto (CommitBuilder.) |
26 | | - (.setTreeId tree-id) |
27 | | - (.setAuthor (PersonIdent. "chrondb" "chrondb@localhost")) |
28 | | - (.setCommitter (PersonIdent. "chrondb" "chrondb@localhost")) |
29 | | - (.setMessage "Initial commit\n")) |
30 | | - commit-id (.insert inserter commit)] |
31 | | - (.flush inserter) |
32 | | - (let [ref-update (.updateRef repo (str "refs/heads/" branch-name))] |
33 | | - (.setNewObjectId ref-update commit-id) |
34 | | - (.setExpectedOldObjectId ref-update (ObjectId/zeroId)) |
35 | | - (.update ref-update)) |
36 | | - (let [ref-update (.updateRef repo Constants/HEAD)] |
37 | | - (.setNewObjectId ref-update commit-id) |
38 | | - (.setExpectedOldObjectId ref-update (ObjectId/zeroId)) |
39 | | - (.update ref-update)))) |
40 | 14 | repo)) |
41 | 15 |
|
42 | 16 | (defn save |
43 | | - "save (insert/update) information in the repository" |
44 | | - [^Repository repo key value |
45 | | - & {:keys [branch-name msg commiter] |
46 | | - :or {branch-name config/default-branch-name |
47 | | - msg "saving content" |
48 | | - commiter {:name "chrondb-anonymous"}}}] |
49 | | - (with-open [inserter (.newObjectInserter repo) |
50 | | - rw (RevWalk. repo)] |
51 | | - (let [ref-name (str "refs/heads/" branch-name) |
52 | | - current-ref (.exactRef repo ref-name)] |
53 | | - (when-not current-ref |
54 | | - (let [head-commit (.resolve repo Constants/HEAD) |
55 | | - ref-update (.updateRef repo ref-name)] |
56 | | - (.setNewObjectId ref-update head-commit) |
57 | | - (.setExpectedOldObjectId ref-update (ObjectId/zeroId)) |
58 | | - (.update ref-update))) |
59 | | - (let [head-ref (.updateRef repo Constants/HEAD)] |
60 | | - (.link head-ref ref-name) |
61 | | - (.update head-ref))) |
62 | | - |
63 | | - (let [data->str (json/write-str value) |
64 | | - baos (ByteArrayOutputStream.) |
65 | | - _ (c/compress-data (.getBytes data->str) baos config/compressor-type) |
66 | | - blob-id (.insert inserter Constants/OBJ_BLOB (.toByteArray baos)) |
67 | | - head-commit (when-let [head (.resolve repo Constants/HEAD)] |
68 | | - (.parseCommit rw head)) |
69 | | - old-tree (when head-commit |
70 | | - (.getTree head-commit)) |
71 | | - tree-formatter (doto (TreeFormatter.) |
72 | | - (.append (str key config/file-ext) FileMode/REGULAR_FILE blob-id)) |
73 | | - tree-id (.insert inserter tree-formatter) |
74 | | - head-id (or (.resolve repo Constants/HEAD) (ObjectId/zeroId)) |
75 | | - commit (doto (CommitBuilder.) |
76 | | - (.setTreeId tree-id) |
77 | | - (.setParentId head-id) |
78 | | - (.setAuthor (PersonIdent. (:name commiter) "chrondb@localhost")) |
79 | | - (.setCommitter (PersonIdent. (:name commiter) "chrondb@localhost")) |
80 | | - (.setMessage (str msg "\n"))) |
81 | | - commit-id (.insert inserter commit)] |
82 | | - (.flush inserter) |
83 | | - (let [ref-update (.updateRef repo Constants/HEAD)] |
| 17 | + [^Repository repository ^RevTree tree k v] |
| 18 | + (with-open [object-inserter (.newObjectInserter repository)] |
| 19 | + (let [branch (.resolve repository Constants/HEAD) |
| 20 | + blob-str (json/write-str v) |
| 21 | + blob (.getBytes blob-str) |
| 22 | + blob-id (.insert object-inserter Constants/OBJ_BLOB blob) |
| 23 | + |
| 24 | + ;; Create root tree with db tree and other keys |
| 25 | + root-tree-formatter (TreeFormatter.) |
| 26 | + |
| 27 | + ;; Add existing keys (except the one we're updating) |
| 28 | + _ (when tree |
| 29 | + (with-open [tw (doto (TreeWalk. repository) |
| 30 | + (.addTree tree) |
| 31 | + (.setRecursive true))] |
| 32 | + (while (.next tw) |
| 33 | + (let [path (.getPathString tw) |
| 34 | + mode (.getFileMode tw 0) |
| 35 | + obj-id (.getObjectId tw 0)] |
| 36 | + (when (not= path k) |
| 37 | + (.append root-tree-formatter path mode obj-id)))))) |
| 38 | + |
| 39 | + ;; Add the new/updated key |
| 40 | + _ (.append root-tree-formatter k FileMode/REGULAR_FILE blob-id) |
| 41 | + |
| 42 | + root-tree-id (.insert object-inserter root-tree-formatter) |
| 43 | + |
| 44 | + ;; Create and insert commit |
| 45 | + commit (doto (CommitBuilder.) |
| 46 | + (.setTreeId root-tree-id) |
| 47 | + (.setMessage (str "save " k))) |
| 48 | + _ (when branch |
| 49 | + (.setParentId commit branch)) |
| 50 | + commit-id (.insert object-inserter commit)] |
| 51 | + |
| 52 | + ;; Flush changes and update refs |
| 53 | + (.flush object-inserter) |
| 54 | + (let [ref-update (.updateRef repository Constants/HEAD)] |
| 55 | + (.setNewObjectId ref-update commit-id) |
| 56 | + (.setExpectedOldObjectId ref-update (if branch branch (ObjectId/zeroId))) |
| 57 | + (.update ref-update)) |
| 58 | + (let [ref-update (.updateRef repository "refs/heads/main")] |
84 | 59 | (.setNewObjectId ref-update commit-id) |
85 | | - (.setExpectedOldObjectId ref-update head-id) |
| 60 | + (.setExpectedOldObjectId ref-update (if branch branch (ObjectId/zeroId))) |
86 | 61 | (.update ref-update))))) |
87 | 62 |
|
88 | | -(defn find-by-key |
89 | | - "find by key registered in the git repository" |
90 | | - [^Repository repo key] |
91 | | - (when-let [head (.resolve repo Constants/HEAD)] |
92 | | - (with-open [reader (.newObjectReader repo) |
93 | | - rw (RevWalk. repo)] |
94 | | - (let [commit (.parseCommit rw head) |
95 | | - tree (.getTree commit) |
96 | | - tree-walk (doto (TreeWalk. repo) |
97 | | - (.addTree tree) |
98 | | - (.setRecursive true)) |
99 | | - file-name (str key config/file-ext)] |
100 | | - (loop [] |
101 | | - (when (.next tree-walk) |
102 | | - (if (= (.getNameString tree-walk) file-name) |
103 | | - (let [blob-id (.getObjectId tree-walk 0) |
104 | | - blob (.open reader blob-id) |
105 | | - compressed (.getCachedBytes blob) |
106 | | - baos (ByteArrayOutputStream.)] |
107 | | - (c/decompress-data compressed baos config/compressor-type) |
108 | | - (json/read-str (.toString baos))) |
109 | | - (recur)))))))) |
110 | | - |
111 | | -(defn delete-database |
112 | | - [^Repository repo] |
113 | | - (.close repo)) |
| 63 | +(defn get-value |
| 64 | + [^Repository repository ^RevTree tree k] |
| 65 | + (with-open [reader (.newObjectReader repository) |
| 66 | + tw (doto (TreeWalk. repository) |
| 67 | + (.addTree tree) |
| 68 | + (.setRecursive true))] |
| 69 | + (loop [] |
| 70 | + (if (.next tw) |
| 71 | + (let [path (.getPathString tw)] |
| 72 | + (if (= path k) |
| 73 | + (let [obj (.getObjectId tw 0) |
| 74 | + blob (.openStream (.open reader obj)) |
| 75 | + data (slurp blob)] |
| 76 | + (json/read-str data)) |
| 77 | + (recur))) |
| 78 | + nil)))) |
0 commit comments