require_last_push_approval blocked barrettruth from approving their
own push. Disabled that restriction in the ruleset — 1 approval is
still required for all PRs, but the approver can now be the pusher.
DIGEST_PAT (barrettruth) approves, CI runs via PAT push, auto-merge
fires when checks pass.
The GITHUB_TOKEN has admin-level bypass on the ruleset. When
gh pr merge --auto is called, the bypass satisfies the review
requirement automatically — no explicit approve step needed.
The self-review error is gone. PAT still handles the push so
CI triggers.
require_last_push_approval blocks barrettruth from approving their
own push. The bot (GITHUB_TOKEN) approves instead — different actor
from the PAT pusher, satisfying the rule.
Problem: actions/checkout sets an http.extraheader with GITHUB_TOKEN
that overrides any credentials in the remote URL, so git push uses
GITHUB_TOKEN regardless of the URL — suppressing CI triggers.
Solution: unset the extraheader before pushing, forcing git to use
the DIGEST_PAT embedded in the remote URL.
ci(digest): push branch with PAT so CI triggers
Problem: GITHUB_TOKEN suppresses all downstream workflow triggers
including push events, so CI never runs on the digest branch.
Solution: push with DIGEST_PAT (triggers CI as a real user push),
then reset the remote to GITHUB_TOKEN for PR creation. Admin bypass
on the ruleset handles the review requirement.
Problem: GITHUB_TOKEN-created PRs suppress pull_request triggers,
so CI never runs and auto-merge stalls.
Solution: add ci/upstream-digest to the push trigger in test and
quality workflows. CI runs on the branch push before the PR exists;
check results attach to the commit SHA so the PR sees them as
passing. The digest workflow reverts to GITHUB_TOKEN for PR
creation — no PAT needed, no contribution inflation.
Problem: GITHUB_TOKEN-created PRs suppress pull_request workflow
triggers, so CI never runs and auto-merge stalls indefinitely.
Solution: use DIGEST_PAT to create the PR. A PAT-created PR is
treated as a real user action, triggering CI normally. Auto-approve
handles the review requirement, auto-merge fires when checks pass.
Problem: the main branch ruleset requires 1 approving review, which
blocks auto-merge. The GITHUB_TOKEN cannot approve its own PR.
Solution: after creating the PR, approve it using DIGEST_PAT (a
fine-grained PAT stored as a repo secret), then enable auto-merge.
The approval comes from a different actor than the bot, satisfying
require_last_push_approval.
Problem: the workflow creates a new dated branch each run. If a digest
PR is not merged before the next run, duplicate PRs accumulate.
Solution: use a single canonical branch ci/upstream-digest with
--force push. Each run resets to main, applies any new items, and
force-pushes. If a PR is already open for the branch, GitHub updates
it in place. A new PR is only created (with auto-merge) when none
exists. The close-stale step is no longer needed.
Problem: if a digest PR is not merged before the next weekly run, a
second PR is created for the same items plus any new ones, leading
to duplicate open PRs.
Solution: before fetching upstream activity, close any open PRs
labeled upstream/digest (deleting their branches). The new run
re-fetches all items since the last merged baseline and produces a
single up-to-date PR.
Problem: new upstream issues and PRs slip through because there's no
mechanism to surface them — manual polling of stevearc/oil.nvim is
required and easy to forget.
Solution: add a Monday 9am UTC scheduled workflow that reads the
highest stevearc/oil.nvim number from doc/upstream.md, fetches merged
PRs and new open issues/PRs above that threshold via the gh CLI, and
creates a structured digest issue in barrettruth/canola.nvim. No issue
is created when there's nothing new. Falls back to a 30-day window if
doc/upstream.md can't be parsed.
Problem: when the nonicons direct API was detected, all icons were
returned with the generic 'OilFileIcon' highlight group, losing
per-filetype colors from nvim-web-devicons.
Solution: resolve highlight groups from devicons when available so
nonicons glyphs retain their per-filetype colors.
Problem: the full upstream PR and issue triage was removed from the
README during the repository modernization, leaving no user-facing
record of what the fork addresses.
Solution: restore the triage tables in a dedicated doc/upstream.md and
link to it from the top of the README. Keeps the README clean while
giving the full picture a permanent home.
Problem: the fork shared the same name as upstream, making it difficult
to distinguish and discover independently.
Solution: rename the repository to canola.nvim — a type of oil, making
the lineage obvious while establishing a distinct identity. Update all
references in the README, rockspec, and issue templates.
Problem: nonicons.nvim exposes a public get_icon/get_icon_by_filetype
API, but oil.nvim can only use nonicons glyphs indirectly through the
devicons monkey-patch. This couples oil to devicons even when nonicons
is available standalone.
Solution: add a nonicons provider in get_icon_provider() between
mini.icons and devicons. Feature-gated on nonicons.get_icon existing
so old nonicons versions fall through to devicons. Uses OilDirIcon
and OilFileIcon highlight groups.
* feat(icons): add nonicons.nvim icon provider support
Problem: oil.nvim only recognizes mini.icons and nvim-web-devicons as
icon providers. nonicons.nvim works when paired with devicons (via its
apply() monkey-patch), but has no standalone support.
Solution: add a nonicons.nvim fallback in get_icon_provider(), placed
after devicons so the patched devicons path is preferred when both are
installed. The standalone path handles directories via
nonicons.get('file-directory'), files via filetype/extension lookup with
a generic file icon fallback.
* fix(doc): improve readme phrasing
Problem: mrcjkb/lua-typecheck-action runs lua-language-server in a bare
nix sandbox without neovim installed, causing 71 type errors for all
vim.* and uv.* types. LuaLS 3.17.x also introduced stricter type
checking that flags uv.aliases.fs_types mismatches not present in
3.16.4. The .luarc.json workspace.library entries conflicted with the
action's auto-appended luvit-meta, producing duplicate uv type unions.
Solution: switch to stevearc/nvim-typecheck-action@v2 (matching
upstream), pin LuaLS to 3.16.4, convert .luarc.json to nested format
without workspace.library (let the action provide VIMRUNTIME and
luvit-meta), and add .direnv/* to selene.toml exclude for local use.
* build: clean up gitignore and remove empty gitmodules
Problem: .gitignore contained 48 lines of C/shared-object boilerplate
irrelevant to a Lua Neovim plugin. .gitmodules was tracked but empty.
Solution: replace .gitignore with minimal entries covering only files
this project actually produces. Delete the vestigial .gitmodules.
* build: add editorconfig and prettierrc
Problem: no editor or formatter configuration, inconsistent with
cp.nvim and diffs.nvim conventions.
Solution: add .editorconfig (2-space Lua indent, utf-8, final newline)
and .prettierrc (prose wrap, 80 cols, single quotes, no semi) matching
the other repos.
* build: add Makefile for lint and test targets
Problem: .github/pre-commit calls `make fastlint` and .github/pre-push
calls `make lint && make test`, but no Makefile existed, so the git
hooks failed.
Solution: add Makefile with lint (stylua + selene), fastlint
(pre-commit), and test (luarocks test) targets.
* docs: add fork copyright to LICENSE
Problem: LICENSE only contained the original author's copyright notice.
Solution: add a second copyright line for the fork maintainer. MIT
requires retaining the original notice; adding a line for derivative
work is standard practice.
* ci: restructure workflows to quality/test/luarocks pattern
Problem: CI used a single tests.yml for linting, typechecking, and
testing. No conditional path filtering, no markdown format check, and
a stale mirror_upstream_prs.yml and duplicate luarocks.yml existed.
Solution: replace tests.yml with quality.yaml (stylua, selene,
lua-typecheck, prettier with dorny/paths-filter) and test.yaml
(nvim-busted, stable+nightly matrix). Update luarocks.yaml to
reference quality.yaml. Delete mirror_upstream_prs.yml and duplicate
luarocks.yml. Fix automation workflow sender check.
* build: rewrite issue templates
Problem: issue templates used upstream stevearc references, severity
dropdowns, outdated lazy.nvim bootstrap, and the .yml extension
inconsistent with other repos.
Solution: replace with .yaml templates matching cp.nvim/diffs.nvim
style. Bug report uses prerequisites checkboxes, checkhealth output,
modern lazy.nvim bootstrap with vim.g.oil pattern. Feature request
uses problem/solution/alternatives format. Add config.yaml to disable
blank issues and link discussions.
* docs: rewrite README
Problem: README contained upstream triage tables, severity dropdowns,
the old setup() pattern, a tree view question, and references to
stevearc/oil.nvim as the primary source.
Solution: full rewrite matching cp.nvim/diffs.nvim style with bold
tagline, features list, requirements, installation, documentation,
FAQ (lazy.nvim setup with vim.g.oil, migration guide, alternatives),
and acknowledgements crediting the original author.
* revert: remove Makefile
Problem: Makefile was added in b9279b5 but was previously deleted
intentionally.
Solution: remove it.
* fix(test): resolve busted migration test isolation issues
Problem: Two issues introduced during the plenary-to-busted migration
(6be0148). First, altbuf_spec waited for two BufEnter events but
oil:// → file resolution only fires one async BufEnter (the synchronous
one from vim.cmd.edit fires before wait_for_autocmd is registered).
Second, reset_editor kept the first window which could be a preview
window with stale oil_preview/oil_source_win state, causing
close_preview_window_if_not_in_oil to close the wrong window in
subsequent tests.
Solution: Wait for a single BufEnter in the altbuf test. Replace the
window-keeping logic in reset_editor with vim.cmd.new() +
vim.cmd.only() to guarantee a fresh window with no inherited state.
This also fixes the preview_spec.lua:30 timeout which had the same
root cause. 114/114 tests pass.
* fix(ci): fix nightly tests and remove unused Makefile
Problem: Neovim nightly's ftplugin/markdown.lua now calls
vim.treesitter.start() unconditionally, which crashes in CI where the
markdown parser is not installed. The Makefile is unused — CI runs
selene, stylua, and nvim-busted-action directly.
Solution: Change filetype plugin indent on to filetype on in
minimal_init.lua. Tests only need filetype detection for
vim.bo.filetype assertions, not ftplugin or indent loading. Remove
the Makefile.
Problem: plenary.nvim is deprecated. The test suite depends on
plenary's async test runner and coroutine-based utilities, tying the
project to an unmaintained dependency. CI also tests against Neovim
0.8-0.11, which are no longer relevant.
Solution: replace plenary with busted + nlua (nvim -l). Convert all
async test patterns (a.wrap, a.util.sleep, a.util.scheduler) to
synchronous equivalents using vim.wait. Rename tests/ to spec/ to
follow busted convention. Replace the CI test matrix with
nvim-busted-action targeting stable/nightly only. Add .busted config,
luarocks test_dependencies, and update the nix devshell.
* build: replace luacheck with selene
Problem: luacheck is unmaintained (last release 2018) and required
suppressing four warning classes to avoid false positives. It also
lacks first-class vim/neovim awareness.
Solution: switch to selene with std='vim' for vim-aware linting.
Replace the luacheck CI job with selene, update the Makefile lint
target, and delete .luacheckrc.
* build: add nix devshell and pre-commit hooks
Problem: oil.nvim had no reproducible dev environment. The .envrc
set up a Python venv for the now-removed docgen pipeline, and there
were no pre-commit hooks for local formatting checks.
Solution: add flake.nix with stylua, selene, and prettier in the
devshell. Replace the stale Python .envrc with 'use flake'. Add
.pre-commit-config.yaml with stylua and prettier hooks matching
other plugins in the repo collection.
* fix: format with stylua
* build(selene): configure lints and add inline suppressions
Problem: selene fails on 5 errors and 3 warnings from upstream code
patterns that are intentional (mixed tables in config API, unused
callback parameters, identical if branches for readability).
Solution: globally allow mixed_table and unused_variable (high volume,
inherent to the codebase design). Add inline selene:allow directives
for the 8 remaining issues: if_same_then_else (4), mismatched_arg_count
(1), empty_if (2), global_usage (1). Remove .envrc from tracking.
* build: switch typecheck action to mrcjkb/lua-typecheck-action
Problem: oil.nvim used stevearc/nvim-typecheck-action, which required
cloning the action repo locally for the Makefile lint target. All
other plugins in the collection use mrcjkb/lua-typecheck-action.
Solution: swap to mrcjkb/lua-typecheck-action@v0 for consistency.
Remove the nvim-typecheck-action git clone from the Makefile and
.gitignore. Drop LuaLS from the local lint target since it requires
a full language server install — CI handles it.
Problem: oil.nvim had no luarocks rockspec, so users of rocks.nvim
and similar tools could not install it from the registry. The stylua
CI action was also pinned to an older version.
Solution: add scm-1 rockspec and a luarocks publish workflow that
gates on tests passing before publishing on version tags. Bump
stylua action from v2.0.2 to v2.1.0.
Closes: barrettruth/oil.nvim#14
* feat: support vim.g.oil declarative configuration
Problem: oil.nvim requires an imperative require("oil").setup(opts)
call to initialize. The Neovim ecosystem is moving toward vim.g.plugin
as a declarative config source that works without explicit setup calls.
Solution: fall back to vim.g.oil in config.setup() when no opts are
passed, and add plugin/oil.lua to auto-initialize when vim.g.oil is
set. Explicit setup(opts) calls still take precedence. Update docs
and add tests for the new resolution order.
Closes: barrettruth/oil.nvim#1
* doc: minor phrasing "improvements"
* fix(doc): restore Q/A format in FAQ and close lua block
* feat: support vim.g.oil declarative configuration
Problem: oil.nvim requires an imperative require("oil").setup(opts)
call to initialize. The Neovim ecosystem is moving toward vim.g.plugin
as a declarative config source that works without explicit setup calls.
Solution: fall back to vim.g.oil in config.setup() when no opts are
passed, and add plugin/oil.lua to auto-initialize when vim.g.oil is
set. Explicit setup(opts) calls still take precedence. Update docs
and add tests for the new resolution order.
Closes: barrettruth/oil.nvim#1
* build: remove release-please pipeline
Problem: the release-please action creates automated releases that
are not needed for this fork's workflow.
Solution: remove the release job from tests.yml and the
release-please branch exclusion from the review request workflow.
* fix(doc): improve readme phrasing
* doc: minor phrasing "improvements"
* ci: add luarocks release on tag push
Problem: there is no automated way to publish oil.nvim to luarocks
when a new version is tagged.
Solution: add a luarocks workflow that triggers on v* tag pushes,
runs the test suite via workflow_call, then publishes via
luarocks-tag-release. Add workflow_call trigger to tests.yml so it
can be reused.
* docs: centralize documentation into helpdoc
Problem: documentation was spread across four files (README.md,
doc/oil.txt, doc/api.md, doc/recipes.md) with duplication and gaps.
User events were undocumented, and adapter docs only lived in the
README.
Solution: expand doc/oil.txt with five new sections (introduction,
requirements, adapters, recipes, events) from existing content. Trim
README to a landing page pointing to :help oil. Delete doc/api.md
and doc/recipes.md since their content now lives in the helpdoc.
Closes: barrettruth/oil.nvim#6
* build: remove docgen pipeline
Problem: the Python docgen pipeline (scripts/generate.py,
scripts/main.py, nvim_doc_tools) was designed for upstream's doc
layout and is incompatible with the centralized helpdoc structure.
It overwrites doc/oil.txt entirely and expects sections in README.md
that no longer exist.
Solution: delete the pipeline scripts (generate.py, main.py,
requirements.txt), remove the update_docs CI job, and clean up the
Makefile and .gitignore references. Linting and typechecking remain
unchanged.
* docs: replace changelog with upstream divergence table in README
Problem: fork changes were not documented anywhere user-facing. The
auto-generated CHANGELOG.md tracked upstream releases, not fork
divergence.
Solution: delete CHANGELOG.md and add a collapsed <details> block to
README.md with two tables — cherry-picked PRs (by number, with commit
hashes) and triaged upstream issues (by number, with status and
resolution). This gives users a single place to see what the fork
offers over upstream.
* ci: add daily upstream PR mirror workflow
Problem: new upstream PRs required manual monitoring of
stevearc/oil.nvim to discover.
Solution: add a GitHub Actions workflow that runs daily at 08:00 UTC
and creates issues in the fork for any upstream PRs opened in the last
24 hours. Skips dependabot PRs and deduplicates by title prefix.
Issues are labeled upstream/pr for easy filtering.
Problem: when the preview window opens a directory that already has a
loaded oil buffer with unsaved edits, open_preview() unconditionally
calls load_oil_buffer() on it. This re-initializes the buffer via
view.initialize() -> render_buffer_async(), which re-fetches the
directory listing from disk and replaces all buffer lines, destroying
the user's pending edits. The mutation parser then can't see the
deleted entry in the source buffer, so it produces a COPY action
instead of a MOVE.
Solution: guard the load_oil_buffer() call in open_preview() with a
check for vim.b[filebufnr].oil_ready. Buffers that are already
initialized and rendered are not re-loaded, preserving any unsaved
modifications the user has made.
Closes: stevearc/oil.nvim#632