about summary refs log tree commit diff stats
path: root/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/spec.py
blob: 0f2fb29cd4037f16606b2215ad315658911bbb31 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import enum
import re

from .nix import License


class RepositoryHost(enum.Enum):
    """A repository host."""

    GITHUB = "github"
    GITLAB = "gitlab"
    SOURCEHUT = "sourcehut"


class PluginSpec:
    """A Vim plugin Spec."""

    @classmethod
    def from_spec(cls, spec):
        """The spec line must be in the format:
            [<repository_host>:]<owner>/<repo>[:<branch>][:name].

        repository_host is one of github (default), gitlab, or sourcehut.
        owner is the repository owner.
        repo is the repository name.
        branch is the git branch.
        name is the name to use for the plugin (default is value of repo).
        """
        repository_host = RepositoryHost.GITHUB
        # gitref = "master"

        repository_host_regex = r"((?P<repository_host>[^:]+):)"
        owner_regex = r"(?P<owner>[^/:]+)"
        repo_regex = r"(?P<repo>[^:]+)"
        branch_regex = r"(:(?P<branch>[^:]+)?)"
        name_regex = r"(:(?P<name>[^:]+)?)"
        license_regex = r"(:(?P<license>[^:]+)?)"
        marked_duplicate_regex = r"(:(?P<duplicate>duplicate))"

        spec_regex = re.compile(
            f"^{repository_host_regex}?{owner_regex}/{repo_regex}{branch_regex}?{name_regex}?{license_regex}?{marked_duplicate_regex}?$",
        )

        match = spec_regex.match(spec)
        if match is None:
            raise ValueError(f"Invalid spec: {spec}")

        group_dict = match.groupdict()

        repository_host = RepositoryHost(group_dict.get("repository_host") or "github")

        owner = group_dict.get("owner")
        if owner is None:
            raise RuntimeError("Could not get owner")

        repo = group_dict.get("repo")
        if repo is None:
            raise RuntimeError("Could not get repo")

        branch = group_dict.get("branch")
        name = group_dict.get("name")
        license = group_dict.get("license")
        marked_duplicate = bool(group_dict.get("duplicate"))  # True if 'duplicate', False if None

        line = spec

        return cls(repository_host, owner, repo, line, branch, name, license, marked_duplicate)

    def __init__(
        self,
        repository_host: RepositoryHost,
        owner: str,
        repo: str,
        line: str,
        branch: str | None = None,
        name: str | None = None,
        license: str | None = None,
        marked_duplicate: bool = False,
    ) -> None:
        """Initialize a VimPluginSpec."""
        self.repository_host = repository_host
        self.owner = owner
        self.repo = repo
        self.branch = branch
        self.custom_name = name
        self.name = name or repo.replace(".", "-").replace("_", "-")
        self.license = License(license) if license else None
        self.line = line
        self.marked_duplicate = marked_duplicate

    def __str__(self) -> str:
        """Return a string representation of a VimPluginSpec."""
        spec = ""

        if self.repository_host != RepositoryHost.GITHUB:
            spec += f"{self.repository_host.value}:"

        spec += f"{self.owner}/{self.repo}"

        spec += ":"
        if self.branch is not None:
            spec += self.branch

        spec += ":"
        if self.custom_name is not None:
            spec += self.custom_name

        spec += ":"
        if self.license is not None:
            spec += str(self.license)

        spec += ":"
        if self.marked_duplicate:
            spec += "duplicate"

        return spec.rstrip(":")

    def __repr__(self):
        """Return the representation of the specs"""
        return f"PluginSpec({self.owner}/{self.repo}, {self.name})"

    def to_spec(self):
        """Return a spec line for a VimPluginSpec."""
        return str(self)

    def __lt__(self, o: object) -> bool:
        if not isinstance(o, PluginSpec):
            return False

        return self.name.lower() < o.name.lower()

    def __eq__(self, o: object) -> bool:
        """Return True if the two specs are equal."""
        if not isinstance(o, PluginSpec):
            return False

        return (
            self.repository_host == o.repository_host
            and self.owner == o.owner
            and self.repo == o.repo
            and self.branch == o.branch
            and self.name == o.name
        )