Skip to content

Commit bd5fc3e

Browse files
authored
Merge pull request #105 from posit-dev/chore/detect-git
feat: Only register git tools in a git repo
2 parents 5d8fab9 + a8174ce commit bd5fc3e

4 files changed

Lines changed: 73 additions & 34 deletions

File tree

‎R/tool-git.R‎

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
#' @include tool-result.R
22
NULL
33

4+
btw_can_register_git_tool <- function() {
5+
if (!rlang::is_installed("gert")) {
6+
return(FALSE)
7+
}
8+
9+
tryCatch(
10+
{
11+
gert::git_info()
12+
TRUE
13+
},
14+
error = function(e) FALSE
15+
)
16+
}
17+
418
# Git Status ------------------------------------------------------------------
519

620
#' Tool: Git Status
@@ -74,7 +88,7 @@ RETURNS: A list of file paths, their status (new, modified, deleted, etc.), and
7488
read_only_hint = TRUE,
7589
open_world_hint = FALSE,
7690
idempotent_hint = FALSE,
77-
btw_can_register = function() rlang::is_installed("gert")
91+
btw_can_register = btw_can_register_git_tool
7892
),
7993
arguments = list(
8094
include = ellmer::type_enum(
@@ -164,7 +178,7 @@ LIMITATION: This tool does not support diffing between two arbitrary commits.
164178
read_only_hint = TRUE,
165179
open_world_hint = FALSE,
166180
idempotent_hint = TRUE,
167-
btw_can_register = function() rlang::is_installed("gert")
181+
btw_can_register = btw_can_register_git_tool
168182
),
169183
arguments = list(
170184
ref = ellmer::type_string(
@@ -267,7 +281,7 @@ RETURNS: A list of commits with SHA (short), author, timestamp, number of files,
267281
read_only_hint = TRUE,
268282
open_world_hint = FALSE,
269283
idempotent_hint = FALSE,
270-
btw_can_register = function() rlang::is_installed("gert")
284+
btw_can_register = btw_can_register_git_tool
271285
),
272286
arguments = list(
273287
ref = ellmer::type_string(
@@ -365,7 +379,7 @@ RETURNS: The commit SHA and confirmation message.
365379
read_only_hint = FALSE,
366380
open_world_hint = FALSE,
367381
idempotent_hint = FALSE,
368-
btw_can_register = function() rlang::is_installed("gert")
382+
btw_can_register = btw_can_register_git_tool
369383
),
370384
arguments = list(
371385
message = ellmer::type_string(
@@ -451,7 +465,7 @@ RETURNS: A table of branch names, upstream tracking, and last update time.
451465
read_only_hint = TRUE,
452466
open_world_hint = FALSE,
453467
idempotent_hint = TRUE,
454-
btw_can_register = function() rlang::is_installed("gert")
468+
btw_can_register = btw_can_register_git_tool
455469
),
456470
arguments = list(
457471
include = ellmer::type_enum(
@@ -541,7 +555,7 @@ RETURNS: Confirmation message with branch name and ref.
541555
read_only_hint = FALSE,
542556
open_world_hint = FALSE,
543557
idempotent_hint = FALSE,
544-
btw_can_register = function() rlang::is_installed("gert")
558+
btw_can_register = btw_can_register_git_tool
545559
),
546560
arguments = list(
547561
branch = ellmer::type_string(
@@ -627,7 +641,7 @@ RETURNS: Confirmation message with branch name.
627641
read_only_hint = FALSE,
628642
open_world_hint = FALSE,
629643
idempotent_hint = FALSE,
630-
btw_can_register = function() rlang::is_installed("gert")
644+
btw_can_register = btw_can_register_git_tool
631645
),
632646
arguments = list(
633647
branch = ellmer::type_string(

‎R/tools.R‎

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,32 +47,32 @@ btw_tools <- function(...) {
4747
check_character(tools, allow_null = TRUE)
4848

4949
if (length(tools) == 0) {
50-
return(as_ellmer_tools(.btw_tools))
50+
tools <- names(.btw_tools)
51+
} else {
52+
tool_names <- map_chr(.btw_tools, function(x) x$name)
53+
tool_groups <- map_chr(.btw_tools, function(x) x$group)
54+
55+
allowed <- c(
56+
tool_groups,
57+
tool_names,
58+
sub("btw_tool_", "", tool_names, fixed = TRUE)
59+
)
60+
allowed <- unique(allowed)
61+
62+
tools <- tryCatch(
63+
arg_match(tools, allowed[!grepl("^btw_", allowed)], multiple = TRUE),
64+
error = function(err_short) {
65+
tryCatch(
66+
arg_match(tools, allowed, multiple = TRUE),
67+
error = function(err_long) {
68+
class(err_short) <- c("btw_unmatched_tool_error", class(err_short))
69+
cnd_signal(err_short)
70+
}
71+
)
72+
}
73+
)
5174
}
5275

53-
tool_names <- map_chr(.btw_tools, function(x) x$name)
54-
tool_groups <- map_chr(.btw_tools, function(x) x$group)
55-
56-
allowed <- c(
57-
tool_groups,
58-
tool_names,
59-
sub("btw_tool_", "", tool_names, fixed = TRUE)
60-
)
61-
allowed <- unique(allowed)
62-
63-
tools <- tryCatch(
64-
arg_match(tools, allowed[!grepl("^btw_", allowed)], multiple = TRUE),
65-
error = function(err_short) {
66-
tryCatch(
67-
arg_match(tools, allowed, multiple = TRUE),
68-
error = function(err_long) {
69-
class(err_short) <- c("btw_unmatched_tool_error", class(err_short))
70-
cnd_signal(err_short)
71-
}
72-
)
73-
}
74-
)
75-
7676
tools_to_keep <- map_lgl(.btw_tools, is_tool_match, tools)
7777
res <- .btw_tools[tools_to_keep]
7878
res <- as_ellmer_tools(res)

‎tests/testthat/test-tool-git.R‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,22 @@ test_that("btw_tool_git_branch_checkout()", {
241241
expect_equal(gert::git_branch(), current_branch)
242242
})
243243

244+
test_that("git tools are registered only when in a git repo", {
245+
skip_if_not_installed("gert")
246+
247+
# Not in a git repo
248+
withr::with_tempdir({
249+
expect_false(btw_can_register_git_tool())
250+
tool_names <- names(btw_tools())
251+
expect_no_match(tool_names, "btw_tool_git")
252+
})
253+
254+
# In a git repo
255+
local_temp_git_repo()
256+
expect_true(btw_can_register_git_tool())
257+
expect_true(all(grepl("btw_tool_git", names(btw_tools("git")))))
258+
})
259+
244260
test_that("git tools require gert to be installed", {
245261
skip_if_not_installed("gert")
246262

‎tests/testthat/test-tools.R‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
test_that("btw_tools works", {
2+
local_mocked_bindings(
3+
has_chromote = function() TRUE,
4+
rstudioapi_has_source_editor_context = function() TRUE,
5+
btw_can_register_git_tool = function() TRUE
6+
)
7+
28
# returns .btw_tools as-is with no `tools` argument
39
expect_equal(btw_tools(), as_ellmer_tools(.btw_tools))
410
expect_equal(btw_tools(NULL), as_ellmer_tools(.btw_tools))
@@ -61,7 +67,8 @@ test_that("btw_tools can be registered with a chat", {
6167
test_that("All btw tools have annotations", {
6268
local_mocked_bindings(
6369
# Force conditional tools to always be included in this test
64-
rstudioapi_has_source_editor_context = function() TRUE
70+
rstudioapi_has_source_editor_context = function() TRUE,
71+
btw_can_register_git_tool = function() TRUE
6572
)
6673

6774
tools <- btw_tools()
@@ -78,7 +85,8 @@ test_that("All btw tools have annotations", {
7885
test_that("All btw tools have a btw_can_register() annotation function", {
7986
local_mocked_bindings(
8087
# Force conditional tools to always be included in this test
81-
rstudioapi_has_source_editor_context = function() TRUE
88+
rstudioapi_has_source_editor_context = function() TRUE,
89+
btw_can_register_git_tool = function() TRUE
8290
)
8391

8492
tools <- btw_tools()
@@ -99,7 +107,8 @@ test_that("All btw tools have a btw_can_register() annotation function", {
99107
test_that("$tool() returns a tool definition for all .btw_tools", {
100108
local_mocked_bindings(
101109
has_chromote = function() FALSE,
102-
rstudioapi_has_source_editor_context = function() FALSE
110+
rstudioapi_has_source_editor_context = function() FALSE,
111+
btw_can_register_git_tool = function() FALSE
103112
)
104113

105114
for (name in names(.btw_tools)) {

0 commit comments

Comments
 (0)