gitd-client 0.14.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gitd/__init__.py +88 -0
- gitd/changes.py +77 -0
- gitd/client.py +245 -0
- gitd/comparison.py +111 -0
- gitd/connection.py +128 -0
- gitd/contract.json +3189 -0
- gitd/contract.py +50 -0
- gitd/credentials_calls.py +69 -0
- gitd/endpoint_calls.py +52 -0
- gitd/endpoint_tokens.py +55 -0
- gitd/errors.py +36 -0
- gitd/kept_credentials.py +107 -0
- gitd/messages.py +92 -0
- gitd/methods.py +58 -0
- gitd/models.py +369 -0
- gitd/publishing_calls.py +47 -0
- gitd/publishing_settings.py +216 -0
- gitd/timestamps.py +22 -0
- gitd/warm_layers.py +34 -0
- gitd_client-0.14.0.dist-info/METADATA +92 -0
- gitd_client-0.14.0.dist-info/RECORD +22 -0
- gitd_client-0.14.0.dist-info/WHEEL +4 -0
gitd/contract.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""gitd's contract, read at run time from contract.json, which `make generate` builds from
|
|
2
|
+
proto/gitd/v1/gitd.proto. Only protobuf's public API is used: no code is generated."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from importlib import resources
|
|
7
|
+
|
|
8
|
+
from google.protobuf import descriptor_pb2, descriptor_pool, json_format, message_factory
|
|
9
|
+
from google.protobuf.descriptor import EnumDescriptor
|
|
10
|
+
from google.protobuf.message import Message
|
|
11
|
+
|
|
12
|
+
PACKAGE = "gitd.v1"
|
|
13
|
+
CONTRACT_FILE = "contract.json"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Enumeration:
|
|
17
|
+
"""An enumeration of the contract, by the names and numbers of its values."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, descriptor: EnumDescriptor) -> None:
|
|
20
|
+
self.descriptor = descriptor
|
|
21
|
+
|
|
22
|
+
def number(self, name: str) -> int:
|
|
23
|
+
return self.descriptor.values_by_name[name].number
|
|
24
|
+
|
|
25
|
+
def name(self, number: int) -> str:
|
|
26
|
+
"""The value's name, or an empty one for a value newer than this client."""
|
|
27
|
+
value = self.descriptor.values_by_number.get(number)
|
|
28
|
+
return value.name if value else ""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Contract:
|
|
32
|
+
"""The messages and enumerations of gitd's API."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, pool: descriptor_pool.DescriptorPool) -> None:
|
|
35
|
+
self.pool = pool
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def load(cls) -> Contract:
|
|
39
|
+
text = resources.files(__package__).joinpath(CONTRACT_FILE).read_text(encoding="utf-8")
|
|
40
|
+
files = json_format.Parse(text, descriptor_pb2.FileDescriptorSet())
|
|
41
|
+
pool = descriptor_pool.DescriptorPool()
|
|
42
|
+
for file in files.file:
|
|
43
|
+
pool.Add(file)
|
|
44
|
+
return cls(pool)
|
|
45
|
+
|
|
46
|
+
def message(self, name: str) -> type[Message]:
|
|
47
|
+
return message_factory.GetMessageClass(self.pool.FindMessageTypeByName(f"{PACKAGE}.{name}"))
|
|
48
|
+
|
|
49
|
+
def enumeration(self, name: str) -> Enumeration:
|
|
50
|
+
return Enumeration(self.pool.FindEnumTypeByName(f"{PACKAGE}.{name}"))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""The calls that manage the credentials gitd keeps: for a platform's own pages, never for
|
|
2
|
+
an agent."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from . import messages, methods
|
|
7
|
+
from .connection import Connection
|
|
8
|
+
from .kept_credentials import AppToCreate, Connected, KeptCredential, SignIn
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Credentials:
|
|
12
|
+
"""The credentials gitd keeps, as gitd.credentials.
|
|
13
|
+
|
|
14
|
+
app = gitd.credentials.begin_github_app("acme-agents", "https://platform.example.com/github/created",
|
|
15
|
+
organization="acme")
|
|
16
|
+
# the browser posts app.manifest to app.form_action; GitHub sends it back with a code
|
|
17
|
+
connected = gitd.credentials.complete_github_app(code, app.state)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, connection: Connection) -> None:
|
|
21
|
+
self.connection = connection
|
|
22
|
+
|
|
23
|
+
def list(self) -> list[KeptCredential]:
|
|
24
|
+
"""Every credential gitd keeps, gitd.toml's included, never a secret."""
|
|
25
|
+
response = self.connection.call(methods.LIST_CONNECTIONS, messages.ListConnectionsRequest())
|
|
26
|
+
return [KeptCredential.from_message(connection) for connection in response.connections]
|
|
27
|
+
|
|
28
|
+
def remove(self, credential_id: str) -> None:
|
|
29
|
+
"""Forgets a credential kept through the API."""
|
|
30
|
+
self.connection.call(methods.REMOVE_CONNECTION, messages.RemoveConnectionRequest(id=credential_id))
|
|
31
|
+
|
|
32
|
+
def add_token(self, url_prefix: str, token: str, *, user: str = "") -> KeptCredential:
|
|
33
|
+
"""Keeps a token for the repositories under url_prefix, which names the host."""
|
|
34
|
+
request = messages.AddTokenRequest(url_prefix=url_prefix, token=token, user=user)
|
|
35
|
+
return KeptCredential.from_message(self.connection.call(methods.ADD_TOKEN, request).connection)
|
|
36
|
+
|
|
37
|
+
def add_github_app(
|
|
38
|
+
self, app_id: int, private_key: str, *, host: str = "", url_prefix: str = ""
|
|
39
|
+
) -> KeptCredential:
|
|
40
|
+
"""Keeps a GitHub App a platform already has, once GitHub takes the key as its own."""
|
|
41
|
+
request = messages.AddGitHubAppRequest(
|
|
42
|
+
host=host, app_id=app_id, private_key=private_key, url_prefix=url_prefix
|
|
43
|
+
)
|
|
44
|
+
return KeptCredential.from_message(self.connection.call(methods.ADD_GITHUB_APP, request).connection)
|
|
45
|
+
|
|
46
|
+
def begin_github_app(
|
|
47
|
+
self, name: str, redirect_url: str, *, organization: str = "", host: str = ""
|
|
48
|
+
) -> AppToCreate:
|
|
49
|
+
"""Starts creating the organisation's own GitHub App, named name; GitHub sends the
|
|
50
|
+
person back to redirect_url with a code and the state."""
|
|
51
|
+
request = messages.BeginGitHubAppRequest(
|
|
52
|
+
host=host, organization=organization, name=name, redirect_url=redirect_url
|
|
53
|
+
)
|
|
54
|
+
return AppToCreate.from_message(self.connection.call(methods.BEGIN_GITHUB_APP, request))
|
|
55
|
+
|
|
56
|
+
def complete_github_app(self, code: str, state: str) -> Connected:
|
|
57
|
+
"""Finishes creating the App with the code and state GitHub sent back."""
|
|
58
|
+
request = messages.CompleteGitHubAppRequest(code=code, state=state)
|
|
59
|
+
return Connected.from_message(self.connection.call(methods.COMPLETE_GITHUB_APP, request))
|
|
60
|
+
|
|
61
|
+
def start_github_login(self, *, host: str = "") -> SignIn:
|
|
62
|
+
"""Asks GitHub for the code a person enters to sign in through gitd's public App."""
|
|
63
|
+
request = messages.StartGitHubLoginRequest(host=host)
|
|
64
|
+
return SignIn.from_message(self.connection.call(methods.START_GITHUB_LOGIN, request))
|
|
65
|
+
|
|
66
|
+
def finish_github_login(self, login_id: str) -> Connected:
|
|
67
|
+
"""Waits until the person has entered the code, and keeps the sign-in."""
|
|
68
|
+
request = messages.FinishGitHubLoginRequest(login_id=login_id)
|
|
69
|
+
return Connected.from_message(self.connection.call(methods.FINISH_GITHUB_LOGIN, request))
|
gitd/endpoint_calls.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""The calls of gitd's endpoint: tokens for sandboxes elsewhere. What a sandbox pushes is
|
|
2
|
+
published with Gitd.publish and its sandbox."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from datetime import timedelta
|
|
7
|
+
|
|
8
|
+
from . import messages, methods
|
|
9
|
+
from .connection import Connection
|
|
10
|
+
from .endpoint_tokens import IssuedToken, TokenInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Endpoint:
|
|
14
|
+
"""gitd's endpoint, as gitd.endpoint.
|
|
15
|
+
|
|
16
|
+
issued = gitd.endpoint.issue("https://github.com/acme/web", lifetime=timedelta(hours=2))
|
|
17
|
+
# in the sandbox: git clone issued.authenticated_url() …; git push origin HEAD:agents/fix
|
|
18
|
+
gitd.publish("", "agents/fix", sandbox=issued.info.sandbox)
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, connection: Connection) -> None:
|
|
22
|
+
self.connection = connection
|
|
23
|
+
|
|
24
|
+
def issue(
|
|
25
|
+
self,
|
|
26
|
+
url: str,
|
|
27
|
+
*,
|
|
28
|
+
branch: str = "",
|
|
29
|
+
lifetime: timedelta | None = None,
|
|
30
|
+
read_only: bool = False,
|
|
31
|
+
sandbox: str = "",
|
|
32
|
+
) -> IssuedToken:
|
|
33
|
+
"""A token for a sandbox: it reads url and pushes to its own sandbox repository (an
|
|
34
|
+
earlier one when sandbox names it), for lifetime (an hour by default, a day at most)."""
|
|
35
|
+
request = messages.IssueTokenRequest(
|
|
36
|
+
url=url,
|
|
37
|
+
branch=branch,
|
|
38
|
+
lifetime_seconds=int(lifetime.total_seconds()) if lifetime else 0,
|
|
39
|
+
read_only=read_only,
|
|
40
|
+
sandbox=sandbox,
|
|
41
|
+
)
|
|
42
|
+
return IssuedToken.from_message(self.connection.call(methods.ISSUE_TOKEN, request))
|
|
43
|
+
|
|
44
|
+
def revoke(self, token_id: str, *, remove_sandbox: bool = False) -> None:
|
|
45
|
+
"""Ends a token now, and removes its sandbox repository when asked."""
|
|
46
|
+
request = messages.RevokeTokenRequest(id=token_id, remove_sandbox=remove_sandbox)
|
|
47
|
+
self.connection.call(methods.REVOKE_TOKEN, request)
|
|
48
|
+
|
|
49
|
+
def tokens(self) -> list[TokenInfo]:
|
|
50
|
+
"""The tokens alive, never their secrets."""
|
|
51
|
+
response = self.connection.call(methods.LIST_TOKENS, messages.ListTokensRequest())
|
|
52
|
+
return [TokenInfo.from_message(info) for info in response.tokens]
|
gitd/endpoint_tokens.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Tokens of gitd's endpoint, for sandboxes that clone over HTTP instead of mounting a
|
|
2
|
+
workspace: a microVM, a remote sandbox, a CI runner elsewhere."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from .timestamps import Timestamp
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class TokenInfo:
|
|
15
|
+
"""A token as gitd shows it, never its secret: what it reads, the sandbox repository it
|
|
16
|
+
pushes to when writable, and until when."""
|
|
17
|
+
|
|
18
|
+
id: str
|
|
19
|
+
url: str
|
|
20
|
+
sandbox: str
|
|
21
|
+
writable: bool
|
|
22
|
+
issued_at: datetime
|
|
23
|
+
expires_at: datetime
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_message(cls, info: Any) -> TokenInfo:
|
|
27
|
+
return cls(
|
|
28
|
+
id=info.id,
|
|
29
|
+
url=info.url,
|
|
30
|
+
sandbox=info.sandbox,
|
|
31
|
+
writable=info.writable,
|
|
32
|
+
issued_at=Timestamp.to_datetime(info.issued_at),
|
|
33
|
+
expires_at=Timestamp.to_datetime(info.expires_at),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class IssuedToken:
|
|
39
|
+
"""A token just issued: its secret, shown this once, and where the sandbox clones from —
|
|
40
|
+
git clone https://x:<secret>@… — never the git host's credential."""
|
|
41
|
+
|
|
42
|
+
secret: str
|
|
43
|
+
clone_url: str
|
|
44
|
+
info: TokenInfo
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_message(cls, response: Any) -> IssuedToken:
|
|
48
|
+
return cls(
|
|
49
|
+
secret=response.token, clone_url=response.clone_url, info=TokenInfo.from_message(response.info)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def authenticated_url(self) -> str:
|
|
53
|
+
"""The clone URL with the secret in it, for the sandbox's git."""
|
|
54
|
+
scheme, rest = self.clone_url.split("://", 1)
|
|
55
|
+
return f"{scheme}://x:{self.secret}@{rest}"
|
gitd/errors.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""A refusal from gitd."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import grpc
|
|
8
|
+
from grpc_status import rpc_status
|
|
9
|
+
|
|
10
|
+
from . import messages
|
|
11
|
+
from .models import Refusal
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GitdError(Exception):
|
|
15
|
+
"""A refusal from gitd: its reason (AUTH_REQUIRED, NOT_FOUND, PATH_REFUSED, BUSY, …) and
|
|
16
|
+
what git said. Tell users what happened from the reason, never by parsing the message."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, reason: str, said: str, code: grpc.StatusCode | None = None) -> None:
|
|
19
|
+
super().__init__(f"{reason}: {said}" if reason else said)
|
|
20
|
+
self.reason = reason
|
|
21
|
+
self.said = said
|
|
22
|
+
self.code = code
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_rpc_error(cls, error: grpc.RpcError) -> GitdError:
|
|
26
|
+
"""Reads the GitFailure gitd attaches to a refused call, if there is one."""
|
|
27
|
+
if not isinstance(error, grpc.Call):
|
|
28
|
+
return cls("", str(error))
|
|
29
|
+
status = rpc_status.from_call(error)
|
|
30
|
+
details = list(status.details) if status else []
|
|
31
|
+
for detail in details:
|
|
32
|
+
if detail.Is(messages.GitFailure.DESCRIPTOR):
|
|
33
|
+
failure: Any = messages.GitFailure()
|
|
34
|
+
detail.Unpack(failure)
|
|
35
|
+
return cls(Refusal.reason_of(failure), failure.git_said, error.code())
|
|
36
|
+
return cls("", error.details() or "", error.code())
|
gitd/kept_credentials.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""The credentials gitd keeps, and the steps of connecting GitHub, as plain dataclasses
|
|
2
|
+
built from the messages gitd answers. None of them ever holds a secret."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from enum import StrEnum
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from . import messages
|
|
12
|
+
from .timestamps import Timestamp
|
|
13
|
+
|
|
14
|
+
KIND_PREFIX = "KIND_"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CredentialKind(StrEnum):
|
|
18
|
+
"""What a credential is: a token, an SSH key, a GitHub App, or a person signed in."""
|
|
19
|
+
|
|
20
|
+
TOKEN = "token"
|
|
21
|
+
SSH_KEY = "ssh_key"
|
|
22
|
+
GITHUB_APP = "github_app"
|
|
23
|
+
GITHUB_LOGIN = "github_login"
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_message(cls, number: int) -> CredentialKind:
|
|
27
|
+
name = messages.CONNECTION_KIND.name(number).removeprefix(KIND_PREFIX).lower()
|
|
28
|
+
return cls(name) if name in {member.value for member in cls} else cls.TOKEN
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class KeptCredential:
|
|
33
|
+
"""One credential gitd keeps: its id to remove it by, what it is, the repositories it
|
|
34
|
+
opens, whom it acts as (an App's bot or a person), an App's id and where it is managed,
|
|
35
|
+
when a sign-in stops renewing, and whether gitd.toml declares it."""
|
|
36
|
+
|
|
37
|
+
id: str
|
|
38
|
+
kind: CredentialKind
|
|
39
|
+
url_prefix: str
|
|
40
|
+
acts_as: str
|
|
41
|
+
app_id: int
|
|
42
|
+
manage_url: str
|
|
43
|
+
expires: datetime | None
|
|
44
|
+
from_file: bool
|
|
45
|
+
created: datetime | None
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def from_message(cls, connection: Any) -> KeptCredential:
|
|
49
|
+
return cls(
|
|
50
|
+
id=connection.id,
|
|
51
|
+
kind=CredentialKind.from_message(connection.kind),
|
|
52
|
+
url_prefix=connection.url_prefix,
|
|
53
|
+
acts_as=connection.acts_as,
|
|
54
|
+
app_id=connection.app_id,
|
|
55
|
+
manage_url=connection.manage_url,
|
|
56
|
+
expires=Timestamp.to_datetime(connection.expires) if connection.HasField("expires") else None,
|
|
57
|
+
from_file=connection.from_file,
|
|
58
|
+
created=Timestamp.to_datetime(connection.created) if connection.HasField("created") else None,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True)
|
|
63
|
+
class Connected:
|
|
64
|
+
"""A GitHub App or sign-in gitd now keeps, and where it is installed on repositories."""
|
|
65
|
+
|
|
66
|
+
credential: KeptCredential
|
|
67
|
+
install_url: str
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def from_message(cls, response: Any) -> Connected:
|
|
71
|
+
return cls(
|
|
72
|
+
credential=KeptCredential.from_message(response.connection), install_url=response.install_url
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class AppToCreate:
|
|
78
|
+
"""What a browser posts to GitHub to create an App: where (form_action), the manifest,
|
|
79
|
+
as a form field named manifest, and the state GitHub sends back with the code."""
|
|
80
|
+
|
|
81
|
+
form_action: str
|
|
82
|
+
manifest: str
|
|
83
|
+
state: str
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def from_message(cls, response: Any) -> AppToCreate:
|
|
87
|
+
return cls(form_action=response.form_action, manifest=response.manifest, state=response.state)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(frozen=True)
|
|
91
|
+
class SignIn:
|
|
92
|
+
"""A sign-in waiting for a person: the code they enter at verification_url, for how
|
|
93
|
+
long, and the id to finish it by."""
|
|
94
|
+
|
|
95
|
+
user_code: str
|
|
96
|
+
verification_url: str
|
|
97
|
+
login_id: str
|
|
98
|
+
expires_in_seconds: int
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
def from_message(cls, response: Any) -> SignIn:
|
|
102
|
+
return cls(
|
|
103
|
+
user_code=response.user_code,
|
|
104
|
+
verification_url=response.verification_url,
|
|
105
|
+
login_id=response.login_id,
|
|
106
|
+
expires_in_seconds=response.expires_in_seconds,
|
|
107
|
+
)
|
gitd/messages.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""The messages and enumerations of gitd's contract that this client uses."""
|
|
2
|
+
|
|
3
|
+
from .contract import Contract
|
|
4
|
+
|
|
5
|
+
contract = Contract.load()
|
|
6
|
+
|
|
7
|
+
InfoRequest = contract.message("InfoRequest")
|
|
8
|
+
InfoResponse = contract.message("InfoResponse")
|
|
9
|
+
ProbeRequest = contract.message("ProbeRequest")
|
|
10
|
+
ProbeResponse = contract.message("ProbeResponse")
|
|
11
|
+
Revision = contract.message("Revision")
|
|
12
|
+
PrepareRequest = contract.message("PrepareRequest")
|
|
13
|
+
PrepareResponse = contract.message("PrepareResponse")
|
|
14
|
+
UpdateRequest = contract.message("UpdateRequest")
|
|
15
|
+
UpdateResponse = contract.message("UpdateResponse")
|
|
16
|
+
CheckoutRequest = contract.message("CheckoutRequest")
|
|
17
|
+
CheckoutResponse = contract.message("CheckoutResponse")
|
|
18
|
+
DescribeRequest = contract.message("DescribeRequest")
|
|
19
|
+
DescribeResponse = contract.message("DescribeResponse")
|
|
20
|
+
PublishRequest = contract.message("PublishRequest")
|
|
21
|
+
PublishResponse = contract.message("PublishResponse")
|
|
22
|
+
RemoveRequest = contract.message("RemoveRequest")
|
|
23
|
+
RemoveResponse = contract.message("RemoveResponse")
|
|
24
|
+
AuditRequest = contract.message("AuditRequest")
|
|
25
|
+
AuditResponse = contract.message("AuditResponse")
|
|
26
|
+
GitFailure = contract.message("GitFailure")
|
|
27
|
+
PullRequestOptions = contract.message("PullRequestOptions")
|
|
28
|
+
Provenance = contract.message("Provenance")
|
|
29
|
+
ChangesRequest = contract.message("ChangesRequest")
|
|
30
|
+
ChangesResponse = contract.message("ChangesResponse")
|
|
31
|
+
DiffRequest = contract.message("DiffRequest")
|
|
32
|
+
DiffResponse = contract.message("DiffResponse")
|
|
33
|
+
Side = contract.message("Side")
|
|
34
|
+
CompareRequest = contract.message("CompareRequest")
|
|
35
|
+
CompareResponse = contract.message("CompareResponse")
|
|
36
|
+
ConflictsRequest = contract.message("ConflictsRequest")
|
|
37
|
+
ConflictsResponse = contract.message("ConflictsResponse")
|
|
38
|
+
WatchRequest = contract.message("WatchRequest")
|
|
39
|
+
WatchResponse = contract.message("WatchResponse")
|
|
40
|
+
SealRequest = contract.message("SealRequest")
|
|
41
|
+
SealResponse = contract.message("SealResponse")
|
|
42
|
+
ListWarmRequest = contract.message("ListWarmRequest")
|
|
43
|
+
ListWarmResponse = contract.message("ListWarmResponse")
|
|
44
|
+
IssueTokenRequest = contract.message("IssueTokenRequest")
|
|
45
|
+
IssueTokenResponse = contract.message("IssueTokenResponse")
|
|
46
|
+
RevokeTokenRequest = contract.message("RevokeTokenRequest")
|
|
47
|
+
RevokeTokenResponse = contract.message("RevokeTokenResponse")
|
|
48
|
+
ListTokensRequest = contract.message("ListTokensRequest")
|
|
49
|
+
ListTokensResponse = contract.message("ListTokensResponse")
|
|
50
|
+
|
|
51
|
+
ListConnectionsRequest = contract.message("ListConnectionsRequest")
|
|
52
|
+
ListConnectionsResponse = contract.message("ListConnectionsResponse")
|
|
53
|
+
RemoveConnectionRequest = contract.message("RemoveConnectionRequest")
|
|
54
|
+
RemoveConnectionResponse = contract.message("RemoveConnectionResponse")
|
|
55
|
+
AddTokenRequest = contract.message("AddTokenRequest")
|
|
56
|
+
AddTokenResponse = contract.message("AddTokenResponse")
|
|
57
|
+
AddGitHubAppRequest = contract.message("AddGitHubAppRequest")
|
|
58
|
+
AddGitHubAppResponse = contract.message("AddGitHubAppResponse")
|
|
59
|
+
BeginGitHubAppRequest = contract.message("BeginGitHubAppRequest")
|
|
60
|
+
BeginGitHubAppResponse = contract.message("BeginGitHubAppResponse")
|
|
61
|
+
CompleteGitHubAppRequest = contract.message("CompleteGitHubAppRequest")
|
|
62
|
+
CompleteGitHubAppResponse = contract.message("CompleteGitHubAppResponse")
|
|
63
|
+
StartGitHubLoginRequest = contract.message("StartGitHubLoginRequest")
|
|
64
|
+
StartGitHubLoginResponse = contract.message("StartGitHubLoginResponse")
|
|
65
|
+
FinishGitHubLoginRequest = contract.message("FinishGitHubLoginRequest")
|
|
66
|
+
FinishGitHubLoginResponse = contract.message("FinishGitHubLoginResponse")
|
|
67
|
+
|
|
68
|
+
PublishSettings = contract.message("PublishSettings")
|
|
69
|
+
PullRequestSettings = contract.message("PullRequestSettings")
|
|
70
|
+
GetSettingsRequest = contract.message("GetSettingsRequest")
|
|
71
|
+
GetSettingsResponse = contract.message("GetSettingsResponse")
|
|
72
|
+
SetSettingsRequest = contract.message("SetSettingsRequest")
|
|
73
|
+
SetSettingsResponse = contract.message("SetSettingsResponse")
|
|
74
|
+
RemoveSettingsRequest = contract.message("RemoveSettingsRequest")
|
|
75
|
+
RemoveSettingsResponse = contract.message("RemoveSettingsResponse")
|
|
76
|
+
Preset = contract.message("Preset")
|
|
77
|
+
ListPresetsRequest = contract.message("ListPresetsRequest")
|
|
78
|
+
ListPresetsResponse = contract.message("ListPresetsResponse")
|
|
79
|
+
SetPresetRequest = contract.message("SetPresetRequest")
|
|
80
|
+
SetPresetResponse = contract.message("SetPresetResponse")
|
|
81
|
+
RemovePresetRequest = contract.message("RemovePresetRequest")
|
|
82
|
+
RemovePresetResponse = contract.message("RemovePresetResponse")
|
|
83
|
+
|
|
84
|
+
STRATEGY = contract.enumeration("Strategy")
|
|
85
|
+
ACCESS = contract.enumeration("ProbeResponse.Access")
|
|
86
|
+
REASON = contract.enumeration("GitFailure.Reason")
|
|
87
|
+
CONNECTION_KIND = contract.enumeration("Connection.Kind")
|
|
88
|
+
CHANGE_ACTION = contract.enumeration("ConfigurationChange.Action")
|
|
89
|
+
OPENING = contract.enumeration("PullRequestSettings.Open")
|
|
90
|
+
PRESET_ORIGIN = contract.enumeration("Preset.Origin")
|
|
91
|
+
CHANGE_KIND = contract.enumeration("ChangedFile.Kind")
|
|
92
|
+
EVENT_KIND = contract.enumeration("WatchResponse.Kind")
|
gitd/methods.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""The gitd methods this client calls, by their gRPC path and the message each answers with."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from google.protobuf.message import Message
|
|
8
|
+
|
|
9
|
+
from . import messages
|
|
10
|
+
from .contract import PACKAGE
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class Method:
|
|
15
|
+
service: str
|
|
16
|
+
name: str
|
|
17
|
+
response: type[Message]
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def path(self) -> str:
|
|
21
|
+
return f"/{PACKAGE}.{self.service}/{self.name}"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
INFO = Method("ServerService", "Info", messages.InfoResponse)
|
|
25
|
+
AUDIT = Method("ServerService", "Audit", messages.AuditResponse)
|
|
26
|
+
PROBE = Method("RepositoryService", "Probe", messages.ProbeResponse)
|
|
27
|
+
PREPARE = Method("WorkspaceService", "Prepare", messages.PrepareResponse)
|
|
28
|
+
UPDATE = Method("WorkspaceService", "Update", messages.UpdateResponse)
|
|
29
|
+
CHECKOUT = Method("WorkspaceService", "Checkout", messages.CheckoutResponse)
|
|
30
|
+
DESCRIBE = Method("WorkspaceService", "Describe", messages.DescribeResponse)
|
|
31
|
+
PUBLISH = Method("WorkspaceService", "Publish", messages.PublishResponse)
|
|
32
|
+
REMOVE = Method("WorkspaceService", "Remove", messages.RemoveResponse)
|
|
33
|
+
CHANGES = Method("WorkspaceService", "Changes", messages.ChangesResponse)
|
|
34
|
+
DIFF = Method("WorkspaceService", "Diff", messages.DiffResponse)
|
|
35
|
+
COMPARE = Method("WorkspaceService", "Compare", messages.CompareResponse)
|
|
36
|
+
CONFLICTS = Method("WorkspaceService", "Conflicts", messages.ConflictsResponse)
|
|
37
|
+
WATCH = Method("WorkspaceService", "Watch", messages.WatchResponse)
|
|
38
|
+
SEAL = Method("WorkspaceService", "Seal", messages.SealResponse)
|
|
39
|
+
LIST_WARM = Method("WorkspaceService", "ListWarm", messages.ListWarmResponse)
|
|
40
|
+
ISSUE_TOKEN = Method("EndpointService", "IssueToken", messages.IssueTokenResponse)
|
|
41
|
+
REVOKE_TOKEN = Method("EndpointService", "RevokeToken", messages.RevokeTokenResponse)
|
|
42
|
+
LIST_TOKENS = Method("EndpointService", "ListTokens", messages.ListTokensResponse)
|
|
43
|
+
|
|
44
|
+
LIST_CONNECTIONS = Method("ConnectionService", "ListConnections", messages.ListConnectionsResponse)
|
|
45
|
+
REMOVE_CONNECTION = Method("ConnectionService", "RemoveConnection", messages.RemoveConnectionResponse)
|
|
46
|
+
ADD_TOKEN = Method("ConnectionService", "AddToken", messages.AddTokenResponse)
|
|
47
|
+
ADD_GITHUB_APP = Method("ConnectionService", "AddGitHubApp", messages.AddGitHubAppResponse)
|
|
48
|
+
BEGIN_GITHUB_APP = Method("ConnectionService", "BeginGitHubApp", messages.BeginGitHubAppResponse)
|
|
49
|
+
COMPLETE_GITHUB_APP = Method("ConnectionService", "CompleteGitHubApp", messages.CompleteGitHubAppResponse)
|
|
50
|
+
START_GITHUB_LOGIN = Method("ConnectionService", "StartGitHubLogin", messages.StartGitHubLoginResponse)
|
|
51
|
+
FINISH_GITHUB_LOGIN = Method("ConnectionService", "FinishGitHubLogin", messages.FinishGitHubLoginResponse)
|
|
52
|
+
|
|
53
|
+
GET_SETTINGS = Method("PublishingService", "GetSettings", messages.GetSettingsResponse)
|
|
54
|
+
SET_SETTINGS = Method("PublishingService", "SetSettings", messages.SetSettingsResponse)
|
|
55
|
+
REMOVE_SETTINGS = Method("PublishingService", "RemoveSettings", messages.RemoveSettingsResponse)
|
|
56
|
+
LIST_PRESETS = Method("PublishingService", "ListPresets", messages.ListPresetsResponse)
|
|
57
|
+
SET_PRESET = Method("PublishingService", "SetPreset", messages.SetPresetResponse)
|
|
58
|
+
REMOVE_PRESET = Method("PublishingService", "RemovePreset", messages.RemovePresetResponse)
|