11(ns datomic.codeq.core-test
22 (:use clojure.test
3- datomic.codeq.core))
3+ datomic.codeq.core
4+ datomic.codeq.util
5+ datomic.codeq.test-datomic-util
6+ datomic.codeq.test-git-util)
7+ (:require [datomic.codeq.git :as git]
8+ [datomic.api :as d]
9+ [clojure.java.io :as io]))
410
5- (deftest a-test
6- (testing " FIXME, I fail."
7- (is (= 1 1 ))))
11+
12+ (def ^:dynamic *conn*
13+ " A dynamic var to hold the Datomic connection."
14+ nil )
15+
16+ (def ^:dynamic *git*
17+ " A dynamic var to hold the GitPorcelain API."
18+ nil )
19+
20+ (def ^:dynamic *repo*
21+ " A dynamic var to hold the Git repository."
22+ nil )
23+
24+ (def ^:dynamic *repo-dir*
25+ " A dynamic var to hold a File object to the repository directory."
26+ nil )
27+
28+
29+ (defn datomic-fixture
30+ [f]
31+ (let [uri (str " datomic:mem://" (d/squuid ))]
32+ (d/create-database uri)
33+ (let [c (d/connect uri)]
34+ @(d/transact c schema)
35+ (binding [*conn* c]
36+ (f )))
37+ (d/delete-database uri)))
38+
39+ (defn git-fixture
40+ [f]
41+ (let [d (create-temp-dir )
42+ [g r] (init-repo d)]
43+ (binding [*git* g
44+ *repo* r
45+ *repo-dir* d]
46+ (f ))))
47+
48+ (use-fixtures :each (compose-fixtures datomic-fixture git-fixture))
49+
50+
51+ (defmacro is-only
52+ [x coll]
53+ `(do
54+ (is (= 1 (count ~coll)))
55+ (is (= ~x (first ~coll)))))
56+
57+ (defmacro is-coll
58+ [coll-expected coll-found]
59+ `(let [c# ~coll-found]
60+ (do
61+ (is (= (count ~coll-expected)
62+ (count c#)))
63+ (are [e#]
64+ (some #(= e# %) c#)
65+ ~@coll-expected))))
66+
67+
68+ (deftest test-extract-and-import-commit
69+ (testing " creating, extracting, and importing a commit:"
70+ (let [commit (do
71+ (spit (io/file *repo-dir* " a.txt" ) " contents of a\n " )
72+ (add-file-to-index *git* " a.txt" )
73+ (git/extract-commit-info
74+ (git-commit-all *git* " added a.txt\n " )))]
75+
76+ (testing " extract the map of commit information"
77+ 78+ (:author commit)))
79+ 80+ (:committer commit)))
81+ (is (empty? (:parents commit)))
82+ (is (= " added a.txt\n "
83+ (:msg commit))))
84+
85+ (testing " importing the commit"
86+ (let [repoid (transact-repo-uri *conn* " test/.git" )
87+ {db :db-after }
88+ @(d/transact *conn*
89+ (commit-tx-data (d/db *conn*) *repo* repoid " test" commit))
90+ root-tree-node
91+ (get-root-tree-node db (:sha commit))
92+ children
93+ (get-tree-node-children root-tree-node)]
94+ (is (= 1 (count children)))
95+ (let [node (first children)]
96+ (is (= " a.txt" (node-name node)))
97+ (is (= '(" test/a.txt" ) (node-paths node)))))))))
98+
99+
100+ (deftest test-file-append
101+ (testing " a linear history of two commits, where a file is updated:"
102+ (let [f (io/file *repo-dir* " a.txt" )
103+ c1 (do
104+ (spit f " line 1\n " )
105+ (add-file-to-index *git* " a.txt" )
106+ (git/extract-commit-info
107+ (git-commit-all *git* " added a.txt" )))
108+ c2 (do
109+ (spit f " line 2\n " :append true )
110+ (git/extract-commit-info
111+ (git-commit-all *git* " updated a.txt" )))
112+ repoid (transact-repo-uri *conn* " test/.git" )
113+ _ (doseq [c [c1 c2]]
114+ @(d/transact *conn*
115+ (commit-tx-data (d/db *conn*) *repo* repoid " test" c)))
116+ db (d/db *conn*)]
117+
118+ (testing " examining first commit"
119+ (is-only " a.txt"
120+ (find-commit-filenames db (:sha c1)))
121+ (is-only " test/a.txt"
122+ (find-commit-filepaths db (:sha c1)))
123+ ; ;hardcoded sha corresponds to "line 1\n"
124+ (is-only (:sha c1)
125+ (find-blob-commits db " 89b24ecec50c07aef0d6640a2a9f6dc354a33125" )))
126+
127+ (testing " examining second commit"
128+ (is-only " a.txt"
129+ (find-commit-filenames db (:sha c2)))
130+ (is-only " test/a.txt"
131+ (find-commit-filepaths db (:sha c2)))
132+ ; ;hardcoded sha corresponds to "line 1\nline 2\n"
133+ (is-only (:sha c2)
134+ (find-blob-commits db " 7bba8c8e64b598d317cdf1bb8a63278f9fc241b1" )))
135+
136+ (testing " finding commits by file name and path"
137+ (is-coll [(:sha c1) (:sha c2)]
138+ (find-filename-commits db " a.txt" ))
139+ (is-coll [(:sha c1) (:sha c2)]
140+ (find-filepath-commits db " test/a.txt" ))))))
141+
142+
143+ (deftest test-rename-file
144+ (testing " a linear history of two commits, where a file is renamed:"
145+ (let [f1 (io/file *repo-dir* " a.txt" )
146+ c1 (do
147+ (spit f1 " line 1\n " )
148+ (add-file-to-index *git* " a.txt" )
149+ (git/extract-commit-info
150+ (git-commit-all *git* " added a.txt" )))
151+ f2 (io/file *repo-dir* " b.txt" )
152+ c2 (do
153+ (io/copy f1 f2)
154+ (io/delete-file f1)
155+ (add-file-to-index *git* " b.txt" )
156+ (git/extract-commit-info
157+ (git-commit-all *git* " renamed a.txt to b.txt" )))
158+ repoid (transact-repo-uri *conn* " test/.git" )
159+ _ (doseq [c [c1 c2]]
160+ @(d/transact *conn*
161+ (commit-tx-data (d/db *conn*) *repo* repoid " test" c)))
162+ db (d/db *conn*)]
163+
164+ (testing " examining first commit"
165+ (is-only " a.txt"
166+ (find-commit-filenames db (:sha c1))))
167+
168+ (testing " examining second commit"
169+ (is-only " b.txt"
170+ (find-commit-filenames db (:sha c2))))
171+
172+ (testing " finding commits by file contents"
173+ (is-coll [(:sha c1) (:sha c2)]
174+ (find-blob-commits db " 89b24ecec50c07aef0d6640a2a9f6dc354a33125" ))))))
175+
176+
177+ (deftest test-merge-commit
178+ (testing " a branch and recursive merge in one file:"
179+ (let [f (io/file *repo-dir* " a.txt" )
180+ c1 (do
181+ (spit f " line 1\n " )
182+ (add-file-to-index *git* " a.txt" )
183+ (git/extract-commit-info
184+ (git-commit-all *git* " added a.txt\n " )))
185+ c2 (do
186+ (checkout-branch *git* " branch" true )
187+ (spit f " line 0\n line 1\n " )
188+ (git/extract-commit-info
189+ (git-commit-all *git* " prepended a line to a.txt\n " )))
190+ c3 (do
191+ (checkout-branch *git* " master" )
192+ (spit f " line 1\n line 2\n " )
193+ (git/extract-commit-info
194+ (git-commit-all *git* " appended a line to a.txt\n " )))
195+ c4 (do
196+ (merge-branch-no-commit *git* " branch" )
197+ (git/extract-commit-info
198+ (git-commit-all *git* (str " Merged branch 'branch'\n " ))))
199+ repoid (transact-repo-uri *conn* " test/.git" )
200+ _ (doseq [c [c1 c2 c3 c4]]
201+ @(d/transact *conn*
202+ (commit-tx-data (d/db *conn*) *repo* repoid " test" c)))
203+ db (d/db *conn*)]
204+
205+ (testing " examining initial commit on master"
206+ (is-only (:sha c1)
207+ (find-blob-commits db " 89b24ecec50c07aef0d6640a2a9f6dc354a33125" )))
208+
209+ (testing " examining second commit on branch"
210+ (is-only (:sha c1)
211+ (:parents c2))
212+ (is-only (:sha c2)
213+ (find-blob-commits db " 2bbfc232c2e71c62004c15806843df3ffc3688d0" )))
214+
215+ (testing " examining third commit on master"
216+ (is-only (:sha c1)
217+ (:parents c3))
218+ (is-only (:sha c3)
219+ (find-blob-commits db " 7bba8c8e64b598d317cdf1bb8a63278f9fc241b1" )))
220+
221+ (testing " examining merge commit"
222+ (is-coll [(:sha c2) (:sha c3)]
223+ (:parents c4))
224+ (is-only (:sha c4)
225+ (find-blob-commits db " 73fc08f0c8b6a87eaad8f5991df3a150b501462d" )))
226+
227+ (testing " finding commits by file name and path"
228+ (is-coll [(:sha c1) (:sha c2) (:sha c3) (:sha c4)]
229+ (find-filename-commits db " a.txt" ))
230+ (is-coll [(:sha c1) (:sha c2) (:sha c3) (:sha c4)]
231+ (find-filepath-commits db " test/a.txt" ))))))
232+
233+
234+ (deftest test-mix-of-file-ops
235+ (testing " a linear history of five commits, involving add, update, delete, revert:"
236+ (let [f (io/file *repo-dir* " a.txt" )
237+ ; ;start with initial commit of two files a.txt and b.txt
238+ c1 (do
239+ (spit f " line 1\n " )
240+ (add-file-to-index *git* " a.txt" )
241+ (spit (io/file *repo-dir* " b.txt" )
242+ " contents of b.txt\n " )
243+ (add-file-to-index *git* " b.txt" )
244+ (git/extract-commit-info
245+ (git-commit-all *git* " added a.txt and b.txt\n " )))
246+ ; ;then update a.txt by appending a line, and adding a new
247+ ; ;file c.txt
248+ c2 (do
249+ (spit f " line 2\n " :append true )
250+ (spit (io/file *repo-dir* " c.txt" )
251+ " contents of c.txt\n " )
252+ (add-file-to-index *git* " c.txt" )
253+ (git/extract-commit-info
254+ (git-commit-all *git* " updated a.txt and added c.txt\n " )))
255+ ; ;then add a new file d.txt
256+ g (io/file *repo-dir* " d.txt" )
257+ c3 (do
258+ (spit g " contents of d.txt\n " )
259+ (add-file-to-index *git* " d.txt" )
260+ (git/extract-commit-info
261+ (git-commit-all *git* " added d.txt\n " )))
262+ ; ;then only to delete that file -- this is equivalent to
263+ ; ;reverting commit c3
264+ c4 (do
265+ (io/delete-file g)
266+ (git/extract-commit-info
267+ (git-commit-all *git* " deleted d.txt\n " )))
268+ ; ;finally, revert file a.txt to how it was after the
269+ ; ;first commit
270+ c5 (do
271+ (spit f " line 1\n " )
272+ (git/extract-commit-info
273+ (git-commit-all *git* " revert a.txt\n " )))
274+ repoid (transact-repo-uri *conn* " test/.git" )
275+ _ (doseq [c [c1 c2 c3 c4 c5]]
276+ @(d/transact *conn*
277+ (commit-tx-data (d/db *conn*) *repo* repoid " test" c)))
278+ db (d/db *conn*)]
279+
280+ (testing " examining first commit"
281+ (is-coll [" a.txt" " b.txt" ]
282+ (find-commit-filenames db (:sha c1))))
283+
284+ (testing " finding commits with blobs containing 'line 1\\ n'"
285+ ; ;TODO might have expected c5 here?
286+ (is-only (:sha c1)
287+ (find-blob-commits db " 89b24ecec50c07aef0d6640a2a9f6dc354a33125" )))
288+
289+ (testing " examining second commit"
290+ (is-coll [" a.txt" " c.txt" ]
291+ (find-commit-filenames db (:sha c2))))
292+
293+ (testing " finding commits with blobs containing 'line 1\\ nline 2\\ n'"
294+ ; ;TODO this is because c4 has the same root tree as c2 as
295+ ; ;it reverted c3
296+ (is-coll [(:sha c2) (:sha c4)]
297+ (find-blob-commits db " 7bba8c8e64b598d317cdf1bb8a63278f9fc241b1" )))
298+
299+ (testing " examining third commit"
300+ (is-only " d.txt"
301+ (find-commit-filenames db (:sha c3))))
302+
303+ (testing " examining fourth commit"
304+ ; ;TODO as said above, c2 and c4 share a root tree
305+ (is-coll [" a.txt" " c.txt" ]
306+ (find-commit-filenames db (:sha c4))))
307+
308+ (testing " examining fifth commit"
309+ ; ;TODO maybe a tad surprising?
310+ (is (empty? (find-commit-filenames db (:sha c5)))))
311+
312+ (testing " find commits"
313+ ; ;TODO might have expected c5 here?
314+ (is-coll [(:sha c1) (:sha c2) (:sha c4)]
315+ (find-filename-commits db " a.txt" ))))))
316+
317+
318+ (deftest test-path-trickery
319+ (testing " a linear history of four commits, to examine file path behavior:"
320+ (let [; ;start with an initial commit of file a.txt in
321+ ; ;subdirectory d1
322+ dir1 (doto (io/file *repo-dir* " d1" ) (.mkdir ))
323+ f1 (io/file dir1 " a.txt" )
324+ c1 (do
325+ (spit f1 " line 1\n " )
326+ (add-file-to-index *git* " d1/a.txt" )
327+ (git/extract-commit-info
328+ (git-commit-all *git* " added d1/a.txt\n " )))
329+ ; ;then add a file with the same name but distinct
330+ ; ;contents into subdirectory d2
331+ dir2 (doto (io/file *repo-dir* " d2" ) (.mkdir ))
332+ f2 (io/file dir2 " a.txt" )
333+ c2 (do
334+ (spit f2 " line 2\n " )
335+ (add-file-to-index *git* " d2/a.txt" )
336+ (git/extract-commit-info
337+ (git-commit-all *git* " added d2/a.txt\n " )))
338+ ; ;then add a file with the same name and contents as the
339+ ; ;previous commit but in subdirectory d3
340+ dir3 (doto (io/file *repo-dir* " d3" ) (.mkdir ))
341+ f3 (io/file dir3 " a.txt" )
342+ c3 (do
343+ (spit f3 " line 2\n " )
344+ (add-file-to-index *git* " d3/a.txt" )
345+ (git/extract-commit-info
346+ (git-commit-all *git* " added d3/a.txt\n " )))
347+ ; ;the repository is now is a state where there are three
348+ ; ;files, all of which have the same name, two of which
349+ ; ;have the same content, and all are in distinct
350+ ; ;subdirectories
351+ ; ;finally overwrite the contents of d2/a.txt with the
352+ ; ;contents of d1/a.txt
353+ c4 (do
354+ (spit f2 " line 1\n " )
355+ (git/extract-commit-info
356+ (git-commit-all *git* " copied d1/a.txt to d2/a.txt\n " )))
357+ ; ;before, two files contained 'line 2\\n'
358+ ; ;now, two files contain 'line 1\\n'
359+ repoid (transact-repo-uri *conn* " test/.git" )
360+ _ (doseq [c [c1 c2 c3 c4]]
361+ @(d/transact *conn*
362+ (commit-tx-data (d/db *conn*) *repo* repoid " test" c)))
363+ db (d/db *conn*)]
364+
365+ (testing " find commits with file a.txt"
366+ (is-coll [(:sha c1) (:sha c2) (:sha c3) (:sha c4)]
367+ (find-filename-commits db " a.txt" )))
368+
369+ (testing " find commits with path d1/a.txt"
370+ ; ;TODO might have expected just c1?
371+ (is-coll [(:sha c1) (:sha c4)]
372+ (find-filepath-commits db " test/d1/a.txt" )))
373+
374+ (testing " find commits with path d2/a.txt"
375+ ; ;TODO might have expected just c2 and c4?
376+ (is-coll [(:sha c1) (:sha c2) (:sha c3) (:sha c4)]
377+ (find-filepath-commits db " test/d2/a.txt" )))
378+
379+ (testing " find commits with path d3/a.txt"
380+ ; ;TODO might have expected just c3?
381+ (is-coll [(:sha c2) (:sha c3)]
382+ (find-filepath-commits db " test/d3/a.txt" )))
383+
384+ (testing " find commits for blob with contents 'line 1\\ n'"
385+ (is-coll [(:sha c1) (:sha c4)]
386+ (find-blob-commits db " 89b24ecec50c07aef0d6640a2a9f6dc354a33125" )))
387+
388+ (testing " find commits for blob with contents 'line 2\\ n'"
389+ (is-coll [(:sha c2) (:sha c3)]
390+ (find-blob-commits db " b7e242c00cdad96cf88a626557eba4deab43b52f" ))))))
0 commit comments