nemo-repo-core dropped from 1.0.0 to 0.1.0 while its API is still unsettled, and requireCore treats the minor as the breaking component in the 0.x range.
132 lines
4.1 KiB
Python
132 lines
4.1 KiB
Python
#!/usr/bin/python3
|
|
"""nemo-repo-emblems: emblem overlays for repository folders in Nemo.
|
|
|
|
Four indicators ship by default: the folder is a git repository, it holds a
|
|
.claude directory, its working tree is dirty, it has commits the remote does
|
|
not. Indicators are declared in the config file, so extra ones can be added
|
|
without touching this file.
|
|
|
|
Requires nemo-repo-core: https://github.com/dualfroz/nemo-repo-core
|
|
"""
|
|
|
|
import importlib.util
|
|
import os
|
|
import sys
|
|
|
|
|
|
def _ensureCoreOnPath():
|
|
if importlib.util.find_spec("nemoRepoCore") is not None:
|
|
return
|
|
dataHome = os.environ.get("XDG_DATA_HOME") or os.path.expanduser("~/.local/share")
|
|
dataDirs = (os.environ.get("XDG_DATA_DIRS") or "/usr/local/share:/usr/share").split(":")
|
|
for base in [dataHome] + dataDirs:
|
|
candidate = os.path.join(base, "nemo-repo-core")
|
|
if os.path.isdir(os.path.join(candidate, "nemoRepoCore")):
|
|
sys.path.insert(0, candidate)
|
|
return
|
|
|
|
|
|
_ensureCoreOnPath()
|
|
|
|
import gi
|
|
|
|
gi.require_version("Nemo", "3.0")
|
|
from gi.repository import GObject, Nemo
|
|
|
|
from nemoRepoCore import (coreConfig, findRepoRoot, hasMarkerDirectory,
|
|
localDirectoryPath, pluginLogger, repoCache,
|
|
requireCore)
|
|
|
|
requireCore("0.1.0")
|
|
|
|
logger = pluginLogger("emblems")
|
|
|
|
gitIndicators = ("git_repo", "uncommitted_changes", "unpushed_commits")
|
|
|
|
pluginDefaults = {
|
|
"indicators": {
|
|
"git_repo": {
|
|
"enabled": True,
|
|
"emblem": "emblem-repo-git",
|
|
"description": "Folder contains a .git directory (or worktree file)",
|
|
},
|
|
"claude_dir": {
|
|
"enabled": True,
|
|
"emblem": "emblem-repo-claude",
|
|
"marker_directory": ".claude",
|
|
"description": "Folder contains a .claude directory",
|
|
},
|
|
"uncommitted_changes": {
|
|
"enabled": True,
|
|
"emblem": "emblem-repo-dirty",
|
|
"description": "git status shows staged, unstaged or untracked changes",
|
|
},
|
|
"unpushed_commits": {
|
|
"enabled": True,
|
|
"emblem": "emblem-repo-unpushed",
|
|
"description": "Branch is ahead of its upstream, or has no upstream",
|
|
},
|
|
},
|
|
}
|
|
|
|
coreConfig.registerDefaults(pluginDefaults)
|
|
|
|
|
|
def _enabledIndicators():
|
|
"""Config entries that are switched on and name an emblem, by key."""
|
|
active = {}
|
|
for key, entry in coreConfig.section("indicators").items():
|
|
if not isinstance(entry, dict) or not entry.get("enabled"):
|
|
continue
|
|
if entry.get("emblem"):
|
|
active[key] = entry
|
|
return active
|
|
|
|
|
|
def _markerMatches(path, entry):
|
|
markerDirectory = entry.get("marker_directory")
|
|
if markerDirectory and hasMarkerDirectory(path, markerDirectory):
|
|
return True
|
|
markerFile = entry.get("marker_file")
|
|
return bool(markerFile) and os.path.isfile(os.path.join(path, markerFile))
|
|
|
|
|
|
class RepoEmblemProvider(GObject.GObject, Nemo.InfoProvider,
|
|
Nemo.NameAndDescProvider):
|
|
|
|
def update_file_info(self, file):
|
|
path = localDirectoryPath(file)
|
|
if path is None:
|
|
return
|
|
|
|
active = _enabledIndicators()
|
|
for key, entry in active.items():
|
|
if key not in gitIndicators and _markerMatches(path, entry):
|
|
file.add_emblem(entry["emblem"])
|
|
|
|
repoRoot = findRepoRoot(path)
|
|
if repoRoot is None:
|
|
return
|
|
|
|
if "git_repo" in active:
|
|
file.add_emblem(active["git_repo"]["emblem"])
|
|
|
|
wantsDirty = "uncommitted_changes" in active
|
|
wantsUnpushed = "unpushed_commits" in active
|
|
if not (wantsDirty or wantsUnpushed):
|
|
return
|
|
|
|
repoCache.registerFileObject(repoRoot, file)
|
|
info = repoCache.get(repoRoot)
|
|
if info.error:
|
|
return
|
|
|
|
if wantsDirty and info.dirty:
|
|
file.add_emblem(active["uncommitted_changes"]["emblem"])
|
|
if wantsUnpushed and info.unpushed:
|
|
file.add_emblem(active["unpushed_commits"]["emblem"])
|
|
|
|
def get_name_and_desc(self):
|
|
return ["nemo-repo-emblems:::Emblem overlays for git repositories "
|
|
"and marker directories"]
|