Skip to content

Commit 77998ad

Browse files
committed
Allow resolving git repo from subdir
Currently if the kmono workspace is a subdirectory of a git repo then kmono will fail to properly interact with the git repository. This patch contains a fix which ensures the repository is resolved upwards from the current working directory (or repository root).
1 parent 338ec7a commit 77998ad

File tree

7 files changed

+98
-83
lines changed

7 files changed

+98
-83
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{:lint-as {k16.kmono.git/with-repo clojure.core/with-open}}
Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
(ns k16.kmono.git
22
(:import
33
[java.io File]
4-
[org.eclipse.jgit.api Git]
5-
[org.eclipse.jgit.errors RepositoryNotFoundException]))
4+
[org.eclipse.jgit.errors RepositoryNotFoundException]
5+
[org.eclipse.jgit.lib RepositoryBuilder]))
66

77
(set! *warn-on-reflection* true)
88

99
(def ^:dynamic ^:private *repo* nil)
1010

11-
(defmacro with-open-repo [repo-path f]
12-
`(if-let [[git# repo#] (var-get #'k16.kmono.git/*repo*)]
13-
(~f git# repo#)
14-
(try (with-open [git# (Git/open (File. (str ~repo-path)))]
15-
(let [repo# (Git/.getRepository git#)]
16-
(binding [k16.kmono.git/*repo* [git# repo#]]
17-
(~f git# repo#))))
18-
(catch RepositoryNotFoundException ex#
19-
(throw (ex-info "Project is not in a git repository"
20-
{:type :kmono/no-git-repository
21-
:path (str ~repo-path)}
22-
ex#))))))
11+
(defn- with-repo* [repo-path f]
12+
(if *repo*
13+
(f *repo*)
14+
(try (with-open [repo (-> (RepositoryBuilder.)
15+
(RepositoryBuilder/.findGitDir (File. repo-path))
16+
RepositoryBuilder/.readEnvironment
17+
RepositoryBuilder/.build)]
18+
(binding [*repo* repo]
19+
(f repo)))
20+
(catch RepositoryNotFoundException ex
21+
(throw (ex-info "Project is not in a git repository"
22+
{:type :kmono/no-git-repository
23+
:path (str repo-path)}
24+
ex))))))
2325

24-
(defmacro with-pre-open-repo [repo-path & body]
25-
`(with-open-repo ~repo-path
26-
(fn [_# _#] ~@body)))
26+
(defmacro with-repo [[var repo-path] & body]
27+
(let [fn-name '-with-git]
28+
`(let [f# (fn ~fn-name [git#]
29+
(let [~var git#]
30+
~@body))]
31+
(#'k16.kmono.git/with-repo* ~repo-path f#))))

packages/kmono-git/src/k16/kmono/git/commit.clj

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
[clojure.string :as str]
44
[k16.kmono.git :as git])
55
(:import
6-
[java.io File]
76
[org.eclipse.jgit.api Git LogCommand]
87
[org.eclipse.jgit.lib
98
AbbreviatedObjectId
@@ -56,21 +55,19 @@
5655
"Returns the current commit (HEAD) of the repository at `repo`.
5756
5857
Returns `nil` if the commit cannot be resolved."
59-
[^String repo]
60-
(with-open [git (Git/open (File. repo))]
61-
(let [repository (Git/.getRepository git)]
62-
(some-> (Repository/.resolve repository Constants/HEAD)
63-
(ObjectId/.getName)))))
58+
[^String repo-path]
59+
(git/with-repo [repo repo-path]
60+
(some-> (Repository/.resolve repo Constants/HEAD)
61+
(ObjectId/.getName))))
6462

6563
(defn get-current-commit-short
6664
"Like [[get-current-commit]] but returns the abbreviated commit sha instead"
67-
[^String repo]
68-
(with-open [git (Git/open (File. repo))]
69-
(let [repository (Git/.getRepository git)]
70-
(with-open [reader (Repository/.newObjectReader repository)]
71-
(some->> (Repository/.resolve repository Constants/HEAD)
72-
(ObjectReader/.abbreviate reader)
73-
(AbbreviatedObjectId/.name))))))
65+
[^String repo-path]
66+
(git/with-repo [repo repo-path]
67+
(with-open [reader (Repository/.newObjectReader repo)]
68+
(some->> (Repository/.resolve repo Constants/HEAD)
69+
(ObjectReader/.abbreviate reader)
70+
(AbbreviatedObjectId/.name)))))
7471

7572
(defn- commit->map [^RevCommit commit]
7673
(let [full (RevCommit/.getFullMessage commit)
@@ -90,16 +87,16 @@
9087
(defn find-commits-since
9188
"Find all commits since a given `ref` (or all, if excluded) and optionally
9289
filter by the commits which affect the provided `subdir`."
93-
[^String repo {:keys [ref subdir]}]
94-
(git/with-open-repo repo
95-
(fn with-open-repo [git repo]
96-
(let [log (Git/.log git)]
97-
(when ref
98-
(let [since (resolve-commit-id repo ref)
99-
head (resolve-commit-id repo Constants/HEAD)]
100-
(LogCommand/.addRange log since head)))
90+
[^String repo-path {:keys [ref subdir]}]
91+
(git/with-repo [repo repo-path]
92+
(let [git (Git. repo)
93+
log (Git/.log git)]
94+
(when ref
95+
(let [since (resolve-commit-id repo ref)
96+
head (resolve-commit-id repo Constants/HEAD)]
97+
(LogCommand/.addRange log since head)))
10198

102-
(when subdir
103-
(LogCommand/.addPath log subdir))
99+
(when subdir
100+
(LogCommand/.addPath log subdir))
104101

105-
(mapv commit->map (LogCommand/.call log))))))
102+
(mapv commit->map (LogCommand/.call log)))))

packages/kmono-git/src/k16/kmono/git/files.clj

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
(ns k16.kmono.git.files
22
(:require
3-
[clojure.string :as str])
3+
[clojure.string :as str]
4+
[k16.kmono.git :as git])
45
(:import
5-
[java.io ByteArrayOutputStream File]
6-
[org.eclipse.jgit.api Git]
6+
[java.io ByteArrayOutputStream]
77
[org.eclipse.jgit.diff DiffEntry DiffFormatter]
88
[org.eclipse.jgit.lib Constants Repository]))
99

@@ -12,11 +12,9 @@
1212
(defn find-changed-files-since
1313
"Return a seq of changed file paths since `ref` up to HEAD. If `subdir` is
1414
provided, only include files within that subdir."
15-
[^String repo {:keys [ref subdir]}]
16-
(with-open [git (Git/open (File. repo))]
17-
(let [repo (Git/.getRepository git)
18-
19-
start-commit (Repository/.resolve repo ref)
15+
[^String repo-path {:keys [ref subdir]}]
16+
(git/with-repo [repo repo-path]
17+
(let [start-commit (Repository/.resolve repo ref)
2018
end-commit (Repository/.resolve repo Constants/HEAD)
2119

2220
subdir (when subdir

packages/kmono-git/src/k16/kmono/git/tags.clj

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns k16.kmono.git.tags
2+
(:require
3+
[k16.kmono.git :as git])
24
(:import
3-
java.io.File
45
org.eclipse.jgit.api.Git
56
org.eclipse.jgit.api.ListTagCommand
67
org.eclipse.jgit.api.TagCommand
@@ -26,40 +27,40 @@
2627
first)"
2728
([^String repo-path] (get-sorted-tags repo-path Constants/HEAD))
2829
([^String repo-path rev]
29-
(with-open [git (Git/open (File. repo-path))
30-
repo (.getRepository git)
31-
walk (RevWalk. repo)]
32-
(let [rev (.resolve repo rev)]
33-
(when (nil? rev)
34-
(throw (ex-info (str "Cannot resolve rev: " rev) {:rev rev})))
30+
(git/with-repo [repo repo-path]
31+
(with-open [walk (RevWalk. repo)]
32+
(let [rev (.resolve repo rev)
33+
git (Git. repo)]
34+
(when (nil? rev)
35+
(throw (ex-info (str "Cannot resolve rev: " rev) {:rev rev})))
3536

36-
(let [^RevCommit rev-commit (RevWalk/.parseCommit walk rev)
37-
tags (into []
38-
(keep (fn [^Ref ref]
39-
(let [obj-id (Ref/.getObjectId ref)
40-
any-object (RevWalk/.parseAny walk obj-id)
41-
;; If annotated tag, unwrap to commit
42-
tag-commit (cond
43-
(instance? RevTag any-object)
44-
(->> any-object
45-
(RevTag/.getObject)
46-
(RevWalk/.parseCommit walk))
37+
(let [^RevCommit rev-commit (RevWalk/.parseCommit walk rev)
38+
tags (into []
39+
(keep (fn [^Ref ref]
40+
(let [obj-id (Ref/.getObjectId ref)
41+
any-object (RevWalk/.parseAny walk obj-id)
42+
;; If annotated tag, unwrap to commit
43+
tag-commit (cond
44+
(instance? RevTag any-object)
45+
(->> any-object
46+
(RevTag/.getObject)
47+
(RevWalk/.parseCommit walk))
4748

48-
(instance? RevCommit any-object)
49-
any-object
49+
(instance? RevCommit any-object)
50+
any-object
5051

51-
:else nil)]
52-
(when (and tag-commit
53-
(RevWalk/.isMergedInto walk
54-
tag-commit
55-
rev-commit))
56-
[(shorten-tag-name (.getName ref))
57-
(RevCommit/.getCommitTime tag-commit)]))))
58-
(-> git Git/.tagList ListTagCommand/.call))]
52+
:else nil)]
53+
(when (and tag-commit
54+
(RevWalk/.isMergedInto walk
55+
tag-commit
56+
rev-commit))
57+
[(shorten-tag-name (.getName ref))
58+
(RevCommit/.getCommitTime tag-commit)]))))
59+
(-> git Git/.tagList ListTagCommand/.call))]
5960

60-
(into []
61-
(map first)
62-
(sort-by second #(compare %2 %1) tags)))))))
61+
(into []
62+
(map first)
63+
(sort-by second #(compare %2 %1) tags))))))))
6364

6465
(defn- resolve-object
6566
[^Repository repo ref]
@@ -81,8 +82,8 @@
8182
[:tags [:sequential :string]]]
8283
:nil]}
8384
[^String repo-root {:keys [ref annotated tags]}]
84-
(with-open [git (Git/open (File. repo-root))]
85-
(let [repo (Git/.getRepository git)
85+
(git/with-repo [repo repo-root]
86+
(let [git (Git. repo)
8687
obj (resolve-object repo ref)]
8788
(doseq [tag tags]
8889
(let [cmd (Git/.tag git)]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
(ns k16.kmono.git-test
2+
(:require
3+
[babashka.fs :as fs]
4+
[clojure.test :refer [deftest is use-fixtures]]
5+
[k16.kmono.git.commit :as git.commit]
6+
[k16.kmono.test.helpers.repo :refer [*repo* with-test-repo] :as helpers.repo]))
7+
8+
(use-fixtures :each with-test-repo)
9+
10+
(deftest open-repo-subdir-test
11+
(let [dir (fs/file *repo* "subdir")]
12+
(fs/create-dir dir)
13+
(is (string? (git.commit/get-current-commit (str dir))))))

packages/kmono-version/src/k16/kmono/version.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070

7171
(defn- -resolve-package-changes-since
7272
[project-root packages rev-fn]
73-
(git/with-pre-open-repo project-root
73+
(git/with-repo [_ project-root]
7474
(into {}
7575
(core.thread/batch
7676
(fn find-commits [[pkg-name pkg]]

0 commit comments

Comments
 (0)