feat: add install scripts, packaging and an example plugin
install.sh places the package in a version independent directory under XDG_DATA_HOME instead of site-packages, which would be orphaned the day the distribution moves to a new Python. It verifies the package imports before reporting success, and warns when the pre-split extension is still installed alongside it. pyproject.toml makes pip install --user an equally valid route; the bootstrap in each plugin finds the package either way. examples/nemoRepoLastCommit.py is a complete working plugin in sixty lines, which is the point of the split.
This commit is contained in:
1 parent
4ae3a496af
commit
0cd7a24adb
4 files changed
+201
No files matched your search
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/python3
|
||||
"""Example plugin: a "Last Commit" column for Nemo's list view.
|
||||
|
||||
Copy this file to ~/.local/share/nemo-python/extensions/ and restart Nemo
|
||||
with `nemo -q` to try it. It is about sixty lines of real work because
|
||||
nemo-repo-core already owns the config file, the git call and the cache.
|
||||
|
||||
The block above the imports is the core bootstrap. Copy it verbatim into
|
||||
every plugin: it makes the plugin work whether the core was installed with
|
||||
its install.sh or with pip, and it is the only piece that knows where the
|
||||
core lives.
|
||||
"""
|
||||
|
||||
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 (findRepoRoot, localDirectoryPath, repoCache,
|
||||
requireCore)
|
||||
|
||||
requireCore("1.0.0")
|
||||
|
||||
|
||||
class LastCommitColumnProvider(GObject.GObject, Nemo.ColumnProvider,
|
||||
Nemo.InfoProvider, Nemo.NameAndDescProvider):
|
||||
|
||||
def get_columns(self):
|
||||
return [
|
||||
Nemo.Column(name="NemoRepoExample::last_commit",
|
||||
attribute="repo_last_commit",
|
||||
label="Last Commit",
|
||||
description="Subject and age of the most recent commit"),
|
||||
]
|
||||
|
||||
def update_file_info(self, file):
|
||||
path = localDirectoryPath(file)
|
||||
if path is None:
|
||||
return
|
||||
root = findRepoRoot(path)
|
||||
if root is None:
|
||||
file.add_string_attribute("repo_last_commit", "")
|
||||
return
|
||||
|
||||
repoCache.registerFileObject(root, file)
|
||||
info = repoCache.get(root)
|
||||
if info.error or not info.lastCommit:
|
||||
file.add_string_attribute("repo_last_commit", "")
|
||||
return
|
||||
|
||||
commit = info.lastCommit
|
||||
file.add_string_attribute("repo_last_commit",
|
||||
"%s (%s)" % (commit.subject, commit.relativeDate))
|
||||
|
||||
def get_name_and_desc(self):
|
||||
return ["nemo-repo-example:::Example column showing the last commit"]
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
# Installs the nemoRepoCore library for the current user. No root needed.
|
||||
#
|
||||
# ./install.sh link the package (edits in this checkout go live)
|
||||
# ./install.sh --copy copy the package instead of linking it
|
||||
#
|
||||
# The package is placed in a version independent directory under
|
||||
# XDG_DATA_HOME, so a Python upgrade cannot orphan it. Plugins locate it from
|
||||
# there; see "Writing a plugin" in README.md.
|
||||
set -euo pipefail
|
||||
|
||||
sourceDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
dataHome="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
installDir="$dataHome/nemo-repo-core"
|
||||
configDir="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
extensionsDir="$dataHome/nemo-python/extensions"
|
||||
|
||||
mode="link"
|
||||
if [ "${1:-}" = "--copy" ]; then
|
||||
mode="copy"
|
||||
elif [ -n "${1:-}" ]; then
|
||||
echo "usage: $0 [--copy]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "python3 is required but was not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$installDir"
|
||||
rm -rf "$installDir/nemoRepoCore"
|
||||
|
||||
if [ "$mode" = "copy" ]; then
|
||||
cp -r "$sourceDir/nemoRepoCore" "$installDir/nemoRepoCore"
|
||||
echo "Copied nemoRepoCore -> $installDir/nemoRepoCore"
|
||||
else
|
||||
ln -s "$sourceDir/nemoRepoCore" "$installDir/nemoRepoCore"
|
||||
echo "Linked nemoRepoCore -> $installDir/nemoRepoCore"
|
||||
fi
|
||||
|
||||
if ! PYTHONPATH="$installDir" python3 -c "import nemoRepoCore" 2>/dev/null; then
|
||||
echo
|
||||
echo "WARNING: the package was installed but could not be imported."
|
||||
echo "Check that python3-gi and gir1.2-nemo-3.0 are installed:"
|
||||
echo " sudo apt install python3-gi gir1.2-nemo-3.0 python-nemo"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
coreVersion="$(PYTHONPATH="$installDir" python3 -c 'import nemoRepoCore; print(nemoRepoCore.coreVersion)')"
|
||||
echo "Import check passed, core version $coreVersion"
|
||||
|
||||
legacyConfig="$configDir/nemo-repo-emblems.json"
|
||||
newConfig="$configDir/nemo-repo-core.json"
|
||||
if [ -f "$legacyConfig" ] && [ ! -f "$newConfig" ]; then
|
||||
echo
|
||||
echo "Found a config from the pre-split extension:"
|
||||
echo " $legacyConfig"
|
||||
echo "It will be copied to $newConfig the first time a plugin loads."
|
||||
echo "The old file is left untouched."
|
||||
fi
|
||||
|
||||
legacyExtension="$extensionsDir/nemo_repo_emblems.py"
|
||||
if [ -e "$legacyExtension" ]; then
|
||||
echo
|
||||
echo "WARNING: the pre-split single file extension is still installed:"
|
||||
echo " $legacyExtension"
|
||||
echo "Running it alongside the new plugins duplicates emblems, columns and"
|
||||
echo "menu entries. Remove it when you are ready to switch over:"
|
||||
echo " rm \"$legacyExtension\""
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Core installed. It does nothing on its own: install at least one plugin."
|
||||
@@ -0,0 +1,27 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "nemo-repo-core"
|
||||
version = "1.0.0"
|
||||
description = "Shared foundation for repository-aware Nemo file manager plugins"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.8"
|
||||
license = { text = "MIT" }
|
||||
authors = [{ name = "DualFroz" }]
|
||||
keywords = ["nemo", "cinnamon", "git", "file-manager", "nemo-python"]
|
||||
classifiers = [
|
||||
"Environment :: X11 Applications :: GTK",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Topic :: Desktop Environment :: File Managers",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/dualfroz/nemo-repo-core"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["nemoRepoCore"]
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Removes the installed nemoRepoCore library. The checkout and the user's
|
||||
# config file are left alone.
|
||||
set -euo pipefail
|
||||
|
||||
dataHome="${XDG_DATA_HOME:-$HOME/.local/share}"
|
||||
installDir="$dataHome/nemo-repo-core"
|
||||
extensionsDir="$dataHome/nemo-python/extensions"
|
||||
|
||||
if [ -e "$installDir/nemoRepoCore" ]; then
|
||||
rm -rf "$installDir/nemoRepoCore"
|
||||
echo "Removed $installDir/nemoRepoCore"
|
||||
else
|
||||
echo "Nothing installed at $installDir/nemoRepoCore"
|
||||
fi
|
||||
|
||||
rmdir "$installDir" 2>/dev/null || true
|
||||
|
||||
remaining="$(find "$extensionsDir" -maxdepth 1 -name 'nemoRepo*.py' -o -maxdepth 1 -name 'nemoFolderTools.py' 2>/dev/null || true)"
|
||||
if [ -n "$remaining" ]; then
|
||||
echo
|
||||
echo "WARNING: these plugins still expect the core and will now fail to load:"
|
||||
echo "$remaining"
|
||||
echo "Uninstall them too, then restart Nemo with: nemo -q"
|
||||
fi
|
||||
Reference in new issue
Block a user