Source code for gitws.gitwsmanifestformat
# Copyright 2022-2023 c0fec0de
#
# This file is part of Git Workspace.
#
# Git Workspace is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Git Workspace is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Git Workspace. If not, see <https://www.gnu.org/licenses/>.
"""
Our Own Manifest Format.
"""
from pathlib import Path
from typing import Optional
import tomlkit
from ._util import add_comment, add_info, as_dict, resolve_relative
from .datamodel import Defaults, FileRef, MainFileRef, ManifestSpec, ProjectSpec, Remote
from .exceptions import ManifestError, ManifestNotFoundError
from .manifestformat import ManifestFormat
[docs]class GitWSManifestFormat(ManifestFormat):
"""
Our Manifest Format.
"""
prio: int = -1
[docs] def is_compatible(self, path: Path) -> bool:
"""Check If File At ``path`` Is Compatible."""
return path.suffix == ".toml"
[docs] def load(self, path: Path) -> ManifestSpec:
"""
Load Manifest From ``path``.
Raises:
ManifestNotFoundError: if file is not found
ManifestError: On Syntax Or Data Scheme Errors.
"""
try:
content = path.read_text()
except FileNotFoundError:
raise ManifestNotFoundError(resolve_relative(path)) from None
try:
doc = tomlkit.parse(content)
data = dict(doc)
return ManifestSpec(**data)
except Exception as exc:
raise ManifestError(resolve_relative(path), str(exc)) from None
[docs] def dump(self, spec: ManifestSpec, path: Optional[Path] = None) -> str:
"""
Return :any:`ManifestSpec` As String.
Args:
spec: Manifest Spec
Keyword Args:
path: Path To Possibly Existing Document.
"""
return self._dump(spec, path=path)
def _dump(self, spec: ManifestSpec, doc: Optional[tomlkit.TOMLDocument] = None, path: Optional[Path] = None) -> str:
assert not doc or not path, "'doc' and 'path' are mutually exclusive."
if doc is None:
if path and path.exists():
doc = tomlkit.parse(path.read_text())
else:
doc = self._create()
data = {
"version": ManifestSpec().version,
"remotes": tomlkit.aot(),
"group-filters": (),
"defaults": {},
"dependencies": tomlkit.aot(),
"linkfiles": tomlkit.aot(),
"copyfiles": tomlkit.aot(),
}
else:
data = {}
data.update(as_dict(spec))
for key, value in data.items():
doc[key] = value
return tomlkit.dumps(doc)
[docs] def upgrade(self, path: Path):
"""Upgrade :any:`ManifestSpec` at ``path`` To Latest Version Including Documentation."""
# read
content = path.read_text()
try:
olddoc = tomlkit.parse(content)
olddata = dict(olddoc)
olddata.pop("groups", None)
obj = ManifestSpec(**olddata)
except Exception as exc:
raise ManifestError(resolve_relative(path), str(exc)) from None
# merge
newdoc = self._create()
for key, value in olddata.items():
newdoc[key] = value
for key, value in as_dict(obj).items():
newdoc[key] = value
newdoc["version"] = "1.0"
# write
path.write_text(tomlkit.dumps(newdoc))
def _create(self) -> tomlkit.TOMLDocument:
doc = tomlkit.document()
# Version
doc.add("version", ManifestSpec().version) # type: ignore
# Intro
add_info(
doc,
"""
Git Workspace's Manifest. Please see the documentation at:
https://git-ws.readthedocs.io/en/stable/manual/manifest.html
""",
)
doc.add(tomlkit.nl())
doc.add(tomlkit.nl())
# Group Filtering
example = ManifestSpec(group_filters=("-doc", "-feature@path"))
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add("group-filters", tomlkit.array())
doc.add(tomlkit.nl())
doc.add(tomlkit.nl())
# Remotes
example = ManifestSpec(remotes=[Remote(name="myremote", url_base="https://github.com/myuser")])
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add("remotes", tomlkit.aot())
doc.add(tomlkit.nl())
doc.add(tomlkit.nl())
# Defaults
doc.add("defaults", as_dict(Defaults()))
example = ManifestSpec(
defaults=Defaults(
remote="myserver", revision="main", groups=("test",), with_groups=("doc",), submodules=True
)
)
add_comment(doc, "\n".join(self._dump(example, doc=tomlkit.document()).split("\n")[1:-1]))
doc.add(tomlkit.nl())
doc.add(tomlkit.nl())
add_info(doc, "A minimal dependency:")
example = ManifestSpec(dependencies=[ProjectSpec(name="my", submodules=None)])
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add(tomlkit.nl())
# Dependencies
add_info(doc, "A full flavored dependency using a 'remote':")
example = ManifestSpec(
dependencies=[
ProjectSpec(
name="myname",
remote="remote",
sub_url="my.git",
revision="main",
path="mydir",
manifest_path="git-ws.toml",
groups=("group",),
linkfiles=[
FileRef(src="file0-in-mydir.txt", dest="link0-in-workspace.txt"),
FileRef(src="file1-in-mydir.txt", dest="link1-in-workspace.txt"),
],
copyfiles=[
FileRef(src="file0-in-mydir.txt", dest="file0-in-workspace.txt"),
FileRef(src="file1-in-mydir.txt", dest="file1-in-workspace.txt"),
],
)
]
)
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add(tomlkit.nl())
add_info(doc, "A full flavored dependency using a 'url':")
example = ManifestSpec(
dependencies=[
ProjectSpec(
name="myname",
url="https://github.com/myuser/my.git",
revision="main",
path="mydir",
manifest_path="git-ws.toml",
groups=("group",),
linkfiles=[
FileRef(src="file0-in-mydir.txt", dest="link0-in-workspace.txt"),
FileRef(src="file1-in-mydir.txt", dest="link1-in-workspace.txt"),
],
copyfiles=[
FileRef(src="file0-in-mydir.txt", dest="file0-in-workspace.txt"),
FileRef(src="file1-in-mydir.txt", dest="file1-in-workspace.txt"),
],
)
]
)
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add(tomlkit.nl())
doc.add("dependencies", tomlkit.aot())
doc.add(tomlkit.nl())
doc.add(tomlkit.nl())
# linkfíles
example = ManifestSpec(linkfiles=[MainFileRef(src="file-in-main-clone.txt", dest="link-in-workspace.txt")])
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add("linkfiles", tomlkit.aot())
doc.add(tomlkit.nl())
doc.add(tomlkit.nl())
# copyfíles
example = ManifestSpec(copyfiles=[MainFileRef(src="file-in-main-clone.txt", dest="file-in-workspace.txt")])
add_comment(doc, self._dump(example, doc=tomlkit.document())[:-1])
doc.add("copyfiles", tomlkit.aot())
# Done
return doc
_FORMAT = GitWSManifestFormat()
dump = _FORMAT.dump
load = _FORMAT.load
save = _FORMAT.save
upgrade = _FORMAT.upgrade