Source code for repomatic.upstream

# Copyright Kevin Deldycke <[email protected]> and contributors.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

"""The identity of the upstream toolkit, as downstream repositories see it.

A downstream repository reaches `kdeldycke/repomatic` through the `uses:` refs
of its workflows, the inline self-pin of its `run:` commands, and the paths the
canonical workflows filter on. Every writer and checker of those references
reads the names here, so a rename of the project is a change to this module.

A leaf module: it imports only {mod}`repomatic.github.urls`, which imports
nothing of the package, so any module can use it without an import cycle.
"""

from __future__ import annotations

from .github.urls import repo_name

TYPE_CHECKING = False
if TYPE_CHECKING:
    from pathlib import Path

DEFAULT_REPO: str = "kdeldycke/repomatic"
"""Default upstream repository for reusable workflows."""

INSTALL_GUIDE_PATH = "docs/install.md"
"""Install guide the release freeze pins download URLs in.

Shared by {class}`~repomatic.release.prepare_release.PrepareRelease`, which
rewrites those URLs, and
{func}`~repomatic.lint_repo.repo.check_install_guide_downloads`, which verifies
the release they name actually carries the files.
"""

UPSTREAM_ASSET_GLOB: str = ".claude/**"
"""Path glob for the bundled skills and agents in canonical workflows.

The package ships them through symlinks under `repomatic/data/`, so editing one
changes no path {data}`UPSTREAM_SOURCE_GLOB` matches, while the test suite reads
every one. Downstream, `.claude/` holds synced copies that no test reads, so the
glob is dropped there like the {data}`UPSTREAM_SOURCE_PREFIX` paths.
"""

UPSTREAM_PACKAGE: str = repo_name(DEFAULT_REPO)
"""Distribution name of the upstream toolkit, derived from {data}`DEFAULT_REPO`.

The freeze, cooldown-exemption, and lint code that handles the `uses:` refs
and the inline self-pin all key on this name: deriving it here keeps the
writer/checker pairs in lockstep and makes a rename a one-line change. It is
also the name of the import package, which {func}`is_source_repo` looks for.
"""

UPSTREAM_REPO_SLUGS: tuple[str, ...] = (
    DEFAULT_REPO,
    "kdeldycke/repokit",
    "kdeldycke/workflows",
)
"""Upstream repository slugs across the project's renames, current first.

A downstream thin-caller's `uses:` line references whichever slug was current
when it was generated. Workflow-tombstone detection matches against all of
them (current first, since most callers are recent) so an orphaned thin-caller
is recognized regardless of which era set it up."""

UPSTREAM_SOURCE_GLOB: str = f"{UPSTREAM_PACKAGE}/**"
"""Path glob for the upstream source directory in canonical workflows.

Canonical workflow `paths:` filters use this glob to match source code
changes. In downstream repos, this is replaced with the project's own source
directory.
"""

UPSTREAM_SOURCE_PREFIX: str = f"{UPSTREAM_PACKAGE}/"
"""Path prefix for upstream-specific files in canonical workflows.

Paths starting with this prefix (but not matching
{data}`UPSTREAM_SOURCE_GLOB`) are dropped in downstream thin callers because
they reference files that only exist in the upstream repository (like
`repomatic/data/labels.toml`).
"""


[docs] def is_awesome_repo(name: str) -> bool: """Whether a repository name marks an `awesome-*` curated list. The one spelling of the prefix test: repository-trait detection, the broken-links label choice and the awesome-template auto-inclusion all classify on it. """ return name.startswith("awesome-")
[docs] def is_source_repo(root: Path) -> bool: """Whether *root* is a checkout of the upstream source repository. Only the upstream repository holds the package source tree, its `__init__.py` and its `data/` folder. `repomatic init` reads this to never flag the bundled files of that tree as stale, and the pin updaters to leave the in-tree targets of those files to their own sync. ```{note} Detection reads the contents of *root*, not `__file__`: `uvx --from .` installs the package into a temporary virtual environment, where `__file__` no longer points into the source checkout. ``` :param root: Root directory of the repository to probe. :return: `True` for a checkout of the upstream source repository. """ package = root.resolve() / UPSTREAM_PACKAGE return (package / "__init__.py").exists() and (package / "data").is_dir()