Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Start each test file with `local T = helpers.new_set()`. The hooks of this set i
read `helpers.notifications`.
- They unset `GITHUB_API_TOKEN` and `GITLAB_TOKEN`.
- They isolate git from your user config and your system config.
- They set `XDG_CACHE_HOME` to a temporary directory, so that the cache of the GitHub and GitLab items is empty.
- They restore the cwd, the buffers, and the values that `helpers.stub` replaced.
- They delete the directories from `helpers.tempdir` and `helpers.git_repo`.

Expand Down Expand Up @@ -116,7 +117,8 @@ until the completion items show. Nothing in them uses the network.

The `e2e/` cases run the real git commands. A fake `gh` in a temporary directory answers the GitHub requests at once,
so the times include the process starts, but not the network or the run time of the real `gh`. `cold` cases use a new
source for each request. `warm` cases repeat a request that the cache can answer.
source and an empty cache for each request. `warm` cases repeat a request that the cache can answer. `disk` cases use a
new source and the cache files of an earlier request, as in a new Neovim.

The `startup/` cases measure the cost to load cmp-git. `startup/setup` is the cost of `setup`. Core loads the sources
and the repository module when a request first needs them, so `startup/require_all` loads all the modules. The test
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SELENE ?= selene
LUA_LANGUAGE_SERVER ?= lua-language-server
MINI_VERSION := v0.18.0
MINI_DIR := deps/mini.nvim
LUA_PATHS := lua tests benchmarks
LUA_PATHS := lua plugin tests benchmarks
REF ?= main

.PHONY: test-deps test test-file bench bench-compare format format-check lint typecheck ci
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ require("cmp_git").setup({
remotes = { "upstream", "origin" }, -- in order of most to least prioritized
enableRemoteUrlRewrites = false, -- enable git url rewrites, see https://git-scm.com/docs/git-config#Documentation/git-config.txt-urlltbasegtinsteadOf
ssh_aliases = {}, -- SSH host aliases and their real hosts, such as { ["github-work"] = "github.com" }
cache = {
ttl = 300, -- seconds after which a request also gets the GitHub and GitLab items again in the background
},
git = {
commits = {
limit = 100,
Expand Down Expand Up @@ -254,6 +257,7 @@ require("cmp_git").setup({
- [Remotes and SSH aliases](docs/configuration.md#remotes-and-ssh-aliases)
- [GitHub CLI, GitLab CLI, and curl](docs/configuration.md#github-cli-gitlab-cli-and-curl)
- [Hosted GitHub and GitLab instances](docs/configuration.md#hosted-github-and-gitlab-instances)
- [Cache](docs/configuration.md#cache), and the `:CmpGitClearCache` command
- [Troubleshooting](docs/configuration.md#troubleshooting)

## Contributing
Expand Down
35 changes: 27 additions & 8 deletions benchmarks/cases/e2e.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---Completion requests from start to the final callback, in a git repository with 1000 commits. Each request runs the
---real git commands and a fake `gh` (see `fixtures.isolate_environment`), so the times include process starts but no
---network. `cold` cases use a new source for each request, and `warm` cases repeat a request that the cache can
---answer.
---network. `cold` cases use a new source and an empty cache for each request, and `warm` cases repeat a request that
---the cache can answer. `disk` cases use a new source and the cache files of an earlier request, as in a new session.
local fixtures = require("benchmarks.fixtures")

local COMMITS = 1000
Expand All @@ -26,13 +26,22 @@ local REQUESTS = {
github_mentions = { row = 3, line = "See @", trigger_character = "@" },
}

---Remove the cached GitHub and GitLab items from memory and from disk. Revisions before the disk cache have no cache
---module, and a new source is cold there.
local function clear_cache()
local ok, cache = pcall(require, "cmp_git.cache")
if ok then
cache.clear_all()
end
end

---@param name string A key of `REQUESTS`.
---@param cold boolean
---@param mode "cold" | "warm" | "disk"
---@return bench.AsyncCase
local function request_case(name, cold)
local function request_case(name, mode)
local request = REQUESTS[name]
return {
name = string.format("e2e/%s/%s", name, cold and "cold" or "warm"),
name = string.format("e2e/%s/%s", name, mode),
async = true,
setup = function()
local dir = fixtures.repo(COMMITS)
Expand All @@ -43,7 +52,13 @@ local function request_case(name, cold)
end,
before_each = function(state)
vim.api.nvim_set_current_buf(state.bufnr)
if cold then
if mode == "cold" then
clear_cache()
elseif mode == "disk" then
-- The warm-up run writes the files
require("cmp_git.cache").forget()
end
if mode ~= "warm" then
state.core = require("cmp_git.core").new({})
end
end,
Expand Down Expand Up @@ -77,8 +92,12 @@ for _, name in ipairs({
"github_issues_and_prs",
"github_mentions",
}) do
table.insert(cases, request_case(name, true))
table.insert(cases, request_case(name, false))
table.insert(cases, request_case(name, "cold"))
table.insert(cases, request_case(name, "warm"))
end
-- Only the GitHub and GitLab items have cache files
for _, name in ipairs({ "github_issues_and_prs", "github_mentions" }) do
table.insert(cases, request_case(name, "disk"))
end

return cases
1 change: 1 addition & 0 deletions benchmarks/fixtures.lua
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ function M.isolate_environment()

vim.env.HOME = home
vim.env.XDG_CONFIG_HOME = home .. "/.config"
vim.env.XDG_CACHE_HOME = home .. "/.cache"
vim.env.GIT_CONFIG_GLOBAL = "/dev/null"
vim.env.GIT_CONFIG_NOSYSTEM = "1"
vim.env.GIT_CEILING_DIRECTORIES = root
Expand Down
44 changes: 41 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,46 @@ the path prefix for this remote when these conditions are true:

Path prefixes are only for GitLab. GitHub Enterprise does not use a path prefix.

## Cache

cmp-git keeps the GitHub and GitLab items in a cache on disk: the issues, the pull requests, the merge requests, and
the mentions. The cache is in `stdpath("cache")/cmp-git`, usually `~/.cache/nvim/cmp-git`, with a directory for each
remote, such as `github.com/owner/repo`. All buffers of a remote use the same items, also in a new Neovim. So the first
`#`, `!`, or `@` in a new commit message shows the items without a wait for the network.

The remote is the first remote in `remotes` that has a supported URL. For GitHub, the items come from the repository
that `gh repo set-default` chose, if any. A change of the default repository shows after the next refresh.

When the items are older than `cache.ttl` seconds, a request still shows them at once. The request also gets the items
again in the background, and the next request shows the new items. The default TTL is 300 seconds:

```lua
require("cmp_git").setup({
cache = {
ttl = 300,
},
})
```

With `ttl = 0`, each request gets the items again in the background. With `ttl = math.huge`, cmp-git never gets them
again.

cmp-git does not cache the result of a failed command or an HTTP error, so the next request tries again. If a
background refresh fails, cmp-git keeps the old items and tries again after `cache.ttl` seconds.

The cache holds the titles and the bodies of the issues and the pull requests, and the users of the repository, also
for private repositories. Only your user can read the cache files.

To clear the cache, use these commands:

- `:CmpGitClearCache` clears the items of the remote of the current buffer. It also clears the commits and the
trailers of the buffer.
- `:CmpGitClearCache!` clears the items of all remotes, and the commits and the trailers of all buffers.

The commits and the trailers come from the local repository. cmp-git keeps them in memory for each buffer and does not
refresh them. To get new commits and trailers, run `:CmpGitClearCache`, or wipe the buffer with `:bwipeout` and open
the file again.

## Troubleshooting

If no items show, make sure that these conditions are true:
Expand All @@ -316,6 +356,4 @@ If no items show, make sure that these conditions are true:
To log missing executables, and the exit code and stderr of failed commands, set `vim.g.cmp_git_debug = true`. cmp-git
sends the messages with `vim.notify`.

cmp-git caches the items for each buffer and does not refresh them. To get new items, wipe the buffer with
`:bwipeout` and open the file again, or restart Neovim. cmp-git does not cache the result of a failed command or an
HTTP error, so the next request tries again.
If the items are old or missing, run `:CmpGitClearCache`. The next request gets them again. See [Cache](#cache).
Loading
Loading