A Neovim plugin for repo manifests. Find the manifest a workspace is built
from, read it, edit it in place so the next repo sync picks the change up, and
move the whole workspace onto another branch, tag or commit without retyping the
repo init line.
Nothing is configured per workspace: the .repo directory above the current
buffer says which manifest is in use, and the git config repo init left behind
says where it came from.
- Neovim 0.10 or newer
repoandgiton$PATH- Optional:
xmllint, to have an edit checked against a real XML parser
With lazy.nvim:
{ 'SafaeOuajih/manifest.nvim', cmd = 'Manifest', opts = {} }Everything hangs off one command.
| Command | What it does |
|---|---|
:Manifest |
show the manifest this workspace uses |
:Manifest show |
the same |
:Manifest show pinned |
it, with every project pinned to the commit it sits on |
:Manifest show effective |
every <include> flattened into one manifest |
:Manifest show list |
pick from every manifest behind the workspace |
:Manifest update |
open it for editing, ready for repo sync |
:Manifest update local |
a local_manifests/ override instead |
:Manifest take <rev> |
re-init on that branch, tag, commit or change ref |
<Tab> completes: the subcommands, then the manifests for show and update,
and the branches and tags of the manifest repository for take.
:Manifest show resolves .repo/manifest.xml the generated stub that only
holds an <include> down to the real file inside .repo/manifests and opens
it read-only, with XML highlighting.
| Key | Action |
|---|---|
e |
reopen this manifest writable |
p |
toggle the pinned view |
r |
re-read it |
q |
close |
Two views are generated by repo rather than read off disk:
pinnedisrepo manifest --revision-as-HEAD: the same manifest with every project'srevisionreplaced by the commit it is actually checked out at. This is what to copy when a build has to be reproducible.effectiveisrepo manifest: every include resolved, which is what repo really acts on when the manifest is split across files.
:Manifest update opens the manifest itself a normal buffer on the real file,
so :w writes it and there is nothing to publish or apply. On write the XML is
checked (with xmllint when it is installed) and the command to run next is
printed:
repo sync --no-manifest-update
That flag matters. A plain repo sync starts by fast-forwarding
.repo/manifests to the server's copy, which either refuses to run or throws
the edit away; --no-manifest-update syncs the projects against the manifest as
it stands, which is the point of having edited it.
:Manifest update local opens .repo/local_manifests/local.xml instead,
creating it with a skeleton if it is not there. Local manifests are merged on
top of the manifest and are never touched by repo sync, so they are the right
place for an override that has to survive one.
Syncing is deliberately left to the terminal: it takes minutes, it wants to be interruptible, and it is not an editing operation.
:Manifest take <rev> re-runs repo init against the URL this workspace was
already initialised from, changing only the revision:
:Manifest take master
:Manifest take platform-2.4-rc1
:Manifest take 9f16393f9e9a2c9c2c0cf1e0f8b0e6a0d3c2b1a0
:Manifest take refs/changes/24/12324/3
Anything repo init -b accepts works, which includes a Gerrit change ref, so a
manifest change can be tried out before it is merged.
The URL, the manifest file name and the group filter are read back out of the workspace and passed in again, so nothing but the revision moves. What is about to run is shown first:
Re-initialise /home/me/src/platform?
url ssh://gerrit.example.com/platform/manifest
manifest default.xml
from refs/changes/24/12324/3
to master
repo init -u ssh://gerrit.example.com/platform/manifest -b master -m default.xml
Project checkouts are left alone until you run repo sync.
Output streams into a floating window. repo init only rewrites
.repo/manifests; every project checkout stays exactly where it is until you
run repo sync yourself.
:Manifest take with no revision asks for one, with the current revision filled
in.
Defaults, all optional:
require('manifest').setup {
repo = 'repo', -- the launcher, a name on $PATH or an absolute path
root = nil, -- workspace root; nil walks up from the current buffer
manifest = nil, -- manifest file name; nil reads it from .repo/manifest.xml
split = 'tab', -- how views open: tab, vsplit, split or none
timeout = 120000, -- ms before a repo or git call is abandoned
confirm = true, -- ask before `repo init` rewrites the workspace
validate = true, -- check the XML parses after an edit is written
keys = {
show = { edit = 'e', refresh = 'r', pinned = 'p', quit = 'q' },
console = { quit = 'q' },
},
}Set any key to false to leave it unmapped.
:checkhealth manifest reports which workspace was found, which manifest files
are behind it, the URL and revision repo init recorded, and whether the
manifest checkout has uncommitted edits. The two things it usually catches:
- no
.repoabove the buffer the workspace is somewhere else, orrootneeds setting - no
remote.origin.urlthe workspace was not made byrepo init, and:Manifest takehas nothing to re-init from
.repo/manifest.xmlis generated and holds an<include>naming the real manifest; resolving it is what "find the manifest" means.repo/manifests.gitis whererepo initrecordsremote.origin.url,branch.default.mergeandmanifest.groups, which is everythingtakeneeds.repo/manifests/.gitis the checkout, and owns HEAD and the index, so it is what says whether the manifest has been editedrepo manifest [--revision-as-HEAD]produces the flattened and pinned viewsrepo init -u <recorded url> -b <revision> -m <name> -g <groups>moves the workspace, and nothing else