refactor: extract the shared foundation into an installable library
The single file extension carried 260 lines of infrastructure under its
four Nemo providers: the config file with live reload, the git query
layer, the TTL cache with .git watching, and repository detection. Any
second extension wanting repository awareness had to repeat all of it.
Move that foundation into a nemoRepoCore package with a deliberate plugin
API rather than whatever the providers happened to leave behind:
* Config gains layered defaults, so a plugin registers its own keys and
an empty config file is still a working one
* RepoInfo gains a root, a named last commit tuple and a summary string
* RepoCache gains refresh, invalidate and an invalidation callback
* discovery separates the cheap root check used on every drawn folder
from the upward walk used by on demand work such as menus
* nemoFiles collapses the uri scheme and directory guards every
provider was repeating
* launchers learn the per emulator flag for running a command
* version negotiation lets a plugin state the core it was built for
The config file moves to nemo-repo-core.json and is seeded from the old
nemo-repo-emblems.json when one exists, so no key changes name and
nothing needs editing by hand.
This commit is contained in:
1 parent
d81b502300
commit
4ae3a496af
19 files changed
+871
-708
No files matched your search
@@ -0,0 +1,55 @@
|
||||
"""Deciding whether a directory is a repository, and finding which one."""
|
||||
|
||||
import os
|
||||
|
||||
from .RepoCache import repoCache
|
||||
|
||||
|
||||
def isRepoRoot(path):
|
||||
"""True when `path` itself holds the repository.
|
||||
|
||||
.git is a directory in a normal clone and a file in a worktree or
|
||||
submodule; both count.
|
||||
"""
|
||||
gitPath = os.path.join(path, ".git")
|
||||
return os.path.isdir(gitPath) or os.path.isfile(gitPath)
|
||||
|
||||
|
||||
def findRepoRoot(path):
|
||||
"""Repository root, but only if `path` is that root. Cheap: one stat.
|
||||
|
||||
This is what emblem and column plugins want, because they run for every
|
||||
folder Nemo draws and must not walk the filesystem upwards.
|
||||
"""
|
||||
return path if isRepoRoot(path) else None
|
||||
|
||||
|
||||
def findEnclosingRepoRoot(path, maximumDepth=64):
|
||||
"""Nearest repository root at or above `path`, or None.
|
||||
|
||||
For on-demand work such as a context menu, where walking a handful of
|
||||
parent directories is free and the user expects git actions to work from
|
||||
anywhere inside their checkout.
|
||||
"""
|
||||
current = os.path.abspath(path)
|
||||
for _ in range(maximumDepth):
|
||||
if isRepoRoot(current):
|
||||
return current
|
||||
parent = os.path.dirname(current)
|
||||
if parent == current:
|
||||
return None
|
||||
current = parent
|
||||
return None
|
||||
|
||||
|
||||
def hasMarkerDirectory(path, name):
|
||||
"""True when `path` directly contains a subdirectory called `name`."""
|
||||
return os.path.isdir(os.path.join(path, name))
|
||||
|
||||
|
||||
def repoInfoFor(path, walkUp=False):
|
||||
"""Cached RepoInfo for the repository at (or above) `path`, else None."""
|
||||
root = findEnclosingRepoRoot(path) if walkUp else findRepoRoot(path)
|
||||
if root is None:
|
||||
return None
|
||||
return repoCache.get(root)
|
||||
Reference in new issue
Block a user