github2gerrit 0.1.4__py3-none-any.whl → 0.1.6__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.
- github2gerrit/cli.py +196 -108
- github2gerrit/config.py +207 -5
- github2gerrit/core.py +542 -398
- github2gerrit/duplicate_detection.py +375 -193
- github2gerrit/gerrit_urls.py +256 -0
- github2gerrit/github_api.py +15 -20
- github2gerrit/gitutils.py +49 -13
- github2gerrit/models.py +1 -0
- github2gerrit/similarity.py +458 -0
- github2gerrit/ssh_discovery.py +365 -0
- {github2gerrit-0.1.4.dist-info → github2gerrit-0.1.6.dist-info}/METADATA +24 -25
- github2gerrit-0.1.6.dist-info/RECORD +17 -0
- github2gerrit-0.1.4.dist-info/RECORD +0 -14
- {github2gerrit-0.1.4.dist-info → github2gerrit-0.1.6.dist-info}/WHEEL +0 -0
- {github2gerrit-0.1.4.dist-info → github2gerrit-0.1.6.dist-info}/entry_points.txt +0 -0
- {github2gerrit-0.1.4.dist-info → github2gerrit-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {github2gerrit-0.1.4.dist-info → github2gerrit-0.1.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,365 @@
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
2
|
+
# SPDX-FileCopyrightText: 2025 The Linux Foundation
|
3
|
+
|
4
|
+
"""
|
5
|
+
SSH host key auto-discovery for github2gerrit.
|
6
|
+
|
7
|
+
This module provides functionality to automatically discover and fetch SSH
|
8
|
+
host keys for Gerrit servers, eliminating the need for manual
|
9
|
+
GERRIT_KNOWN_HOSTS configuration.
|
10
|
+
"""
|
11
|
+
|
12
|
+
from __future__ import annotations
|
13
|
+
|
14
|
+
import logging
|
15
|
+
import os
|
16
|
+
import socket
|
17
|
+
from pathlib import Path
|
18
|
+
|
19
|
+
from .gitutils import CommandError
|
20
|
+
from .gitutils import run_cmd
|
21
|
+
|
22
|
+
|
23
|
+
log = logging.getLogger(__name__)
|
24
|
+
|
25
|
+
|
26
|
+
class SSHDiscoveryError(Exception):
|
27
|
+
"""Raised when SSH host key discovery fails."""
|
28
|
+
|
29
|
+
|
30
|
+
# Error message constants to comply with TRY003
|
31
|
+
_MSG_HOST_UNREACHABLE = "Host {hostname}:{port} is not reachable. Check network connectivity and server availability."
|
32
|
+
_MSG_NO_KEYS_FOUND = (
|
33
|
+
"No SSH host keys found for {hostname}:{port}. The server may not be running SSH or may be blocking connections."
|
34
|
+
)
|
35
|
+
_MSG_NO_VALID_KEYS = (
|
36
|
+
"No valid SSH host keys found for {hostname}:{port}. The ssh-keyscan output was empty or malformed."
|
37
|
+
)
|
38
|
+
_MSG_CONNECTION_FAILED = "Failed to connect to {hostname}:{port} for SSH key discovery. Error: {error}"
|
39
|
+
_MSG_KEYSCAN_FAILED = "ssh-keyscan failed with return code {returncode}: {error}"
|
40
|
+
_MSG_UNEXPECTED_ERROR = "Unexpected error during SSH key discovery for {hostname}:{port}: {error}"
|
41
|
+
_MSG_SAVE_FAILED = "Failed to save host keys to configuration file {config_file}: {error}"
|
42
|
+
|
43
|
+
|
44
|
+
def is_host_reachable(hostname: str, port: int, timeout: int = 5) -> bool:
|
45
|
+
"""Check if a host and port are reachable via TCP."""
|
46
|
+
try:
|
47
|
+
with socket.create_connection((hostname, port), timeout=timeout):
|
48
|
+
return True
|
49
|
+
except OSError:
|
50
|
+
return False
|
51
|
+
|
52
|
+
|
53
|
+
def fetch_ssh_host_keys(hostname: str, port: int = 22, timeout: int = 10) -> str:
|
54
|
+
"""
|
55
|
+
Fetch SSH host keys for a given hostname and port using ssh-keyscan.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
hostname: The hostname to scan
|
59
|
+
port: The SSH port (default: 22)
|
60
|
+
timeout: Connection timeout in seconds (default: 10)
|
61
|
+
|
62
|
+
Returns:
|
63
|
+
A string containing the host keys in known_hosts format
|
64
|
+
|
65
|
+
Raises:
|
66
|
+
SSHDiscoveryError: If the host keys cannot be fetched
|
67
|
+
"""
|
68
|
+
log.debug("Fetching SSH host keys for %s:%d", hostname, port)
|
69
|
+
|
70
|
+
# First check if the host is reachable
|
71
|
+
if not is_host_reachable(hostname, port, timeout=5):
|
72
|
+
raise SSHDiscoveryError(_MSG_HOST_UNREACHABLE.format(hostname=hostname, port=port))
|
73
|
+
|
74
|
+
try:
|
75
|
+
# Use ssh-keyscan to fetch all available key types
|
76
|
+
cmd = [
|
77
|
+
"ssh-keyscan",
|
78
|
+
"-p",
|
79
|
+
str(port),
|
80
|
+
"-T",
|
81
|
+
str(timeout),
|
82
|
+
"-t",
|
83
|
+
"rsa,ecdsa,ed25519",
|
84
|
+
hostname,
|
85
|
+
]
|
86
|
+
|
87
|
+
result = run_cmd(cmd, timeout=timeout + 5)
|
88
|
+
|
89
|
+
if not result.stdout or not result.stdout.strip():
|
90
|
+
raise SSHDiscoveryError( # noqa: TRY301
|
91
|
+
_MSG_NO_KEYS_FOUND.format(hostname=hostname, port=port)
|
92
|
+
)
|
93
|
+
|
94
|
+
# Validate that we got proper known_hosts format
|
95
|
+
lines = result.stdout.strip().split("\n")
|
96
|
+
valid_lines = []
|
97
|
+
|
98
|
+
for line in lines:
|
99
|
+
stripped_line = line.strip()
|
100
|
+
if not stripped_line or stripped_line.startswith("#"):
|
101
|
+
continue
|
102
|
+
|
103
|
+
# Basic validation: should have hostname, key type, and key
|
104
|
+
parts = stripped_line.split()
|
105
|
+
if len(parts) >= 3:
|
106
|
+
valid_lines.append(stripped_line)
|
107
|
+
|
108
|
+
if not valid_lines:
|
109
|
+
raise SSHDiscoveryError( # noqa: TRY301
|
110
|
+
_MSG_NO_VALID_KEYS.format(hostname=hostname, port=port)
|
111
|
+
)
|
112
|
+
|
113
|
+
discovered_keys = "\n".join(valid_lines)
|
114
|
+
log.info(
|
115
|
+
"Successfully discovered %d SSH host key(s) for %s:%d",
|
116
|
+
len(valid_lines),
|
117
|
+
hostname,
|
118
|
+
port,
|
119
|
+
)
|
120
|
+
log.debug("Discovered keys:\n%s", discovered_keys)
|
121
|
+
|
122
|
+
except CommandError as exc:
|
123
|
+
if exc.returncode == 1:
|
124
|
+
# ssh-keyscan returns 1 when it can't connect
|
125
|
+
error_msg = exc.stderr or exc.stdout or "Connection failed"
|
126
|
+
raise SSHDiscoveryError(
|
127
|
+
_MSG_CONNECTION_FAILED.format(hostname=hostname, port=port, error=error_msg)
|
128
|
+
) from exc
|
129
|
+
else:
|
130
|
+
error_msg = exc.stderr or exc.stdout or "Unknown error"
|
131
|
+
raise SSHDiscoveryError(_MSG_KEYSCAN_FAILED.format(returncode=exc.returncode, error=error_msg)) from exc
|
132
|
+
except Exception as exc:
|
133
|
+
raise SSHDiscoveryError(_MSG_UNEXPECTED_ERROR.format(hostname=hostname, port=port, error=exc)) from exc
|
134
|
+
else:
|
135
|
+
return discovered_keys
|
136
|
+
|
137
|
+
|
138
|
+
def extract_gerrit_info_from_gitreview(content: str) -> tuple[str, int] | None:
|
139
|
+
"""
|
140
|
+
Extract Gerrit hostname and port from .gitreview file content.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
content: The content of a .gitreview file
|
144
|
+
|
145
|
+
Returns:
|
146
|
+
A tuple of (hostname, port) or None if not found
|
147
|
+
"""
|
148
|
+
hostname = None
|
149
|
+
port = 29418 # Default Gerrit SSH port
|
150
|
+
|
151
|
+
for line in content.split("\n"):
|
152
|
+
stripped_line = line.strip()
|
153
|
+
if "=" not in stripped_line:
|
154
|
+
continue
|
155
|
+
|
156
|
+
key, value = stripped_line.split("=", 1)
|
157
|
+
key = key.strip().lower()
|
158
|
+
value = value.strip()
|
159
|
+
|
160
|
+
if key == "host":
|
161
|
+
hostname = value
|
162
|
+
elif key == "port":
|
163
|
+
try:
|
164
|
+
port = int(value)
|
165
|
+
except ValueError:
|
166
|
+
log.warning("Invalid port in .gitreview: %s", value)
|
167
|
+
|
168
|
+
return (hostname, port) if hostname else None
|
169
|
+
|
170
|
+
|
171
|
+
def discover_and_save_host_keys(hostname: str, port: int, organization: str, config_path: str | None = None) -> str:
|
172
|
+
"""
|
173
|
+
Discover SSH host keys and save them to the organization's configuration.
|
174
|
+
|
175
|
+
Args:
|
176
|
+
hostname: Gerrit hostname
|
177
|
+
port: Gerrit SSH port
|
178
|
+
organization: GitHub organization name for config section
|
179
|
+
config_path: Path to config file (optional, uses default if not
|
180
|
+
provided)
|
181
|
+
|
182
|
+
Returns:
|
183
|
+
The discovered host keys string
|
184
|
+
|
185
|
+
Raises:
|
186
|
+
SSHDiscoveryError: If discovery or saving fails
|
187
|
+
"""
|
188
|
+
# Discover the host keys
|
189
|
+
host_keys = fetch_ssh_host_keys(hostname, port)
|
190
|
+
|
191
|
+
# Save to configuration file
|
192
|
+
save_host_keys_to_config(host_keys, organization, config_path)
|
193
|
+
|
194
|
+
return host_keys
|
195
|
+
|
196
|
+
|
197
|
+
def save_host_keys_to_config(host_keys: str, organization: str, config_path: str | None = None) -> None:
|
198
|
+
"""
|
199
|
+
Save SSH host keys to the organization's configuration file.
|
200
|
+
|
201
|
+
Args:
|
202
|
+
host_keys: The host keys in known_hosts format
|
203
|
+
organization: GitHub organization name for config section
|
204
|
+
config_path: Path to config file (optional, uses default if not
|
205
|
+
provided)
|
206
|
+
|
207
|
+
Raises:
|
208
|
+
SSHDiscoveryError: If saving fails
|
209
|
+
"""
|
210
|
+
from .config import DEFAULT_CONFIG_PATH
|
211
|
+
|
212
|
+
if config_path is None:
|
213
|
+
config_path = os.getenv("G2G_CONFIG_PATH", "").strip() or DEFAULT_CONFIG_PATH
|
214
|
+
|
215
|
+
config_file = Path(config_path).expanduser()
|
216
|
+
|
217
|
+
try:
|
218
|
+
# Ensure the directory exists
|
219
|
+
config_file.parent.mkdir(parents=True, exist_ok=True)
|
220
|
+
|
221
|
+
# Read existing configuration
|
222
|
+
existing_content = ""
|
223
|
+
if config_file.exists():
|
224
|
+
existing_content = config_file.read_text(encoding="utf-8")
|
225
|
+
|
226
|
+
# Parse existing content to find the organization section
|
227
|
+
lines = existing_content.split("\n")
|
228
|
+
new_lines = []
|
229
|
+
in_org_section = False
|
230
|
+
org_section_found = False
|
231
|
+
gerrit_known_hosts_updated = False
|
232
|
+
|
233
|
+
for line in lines:
|
234
|
+
stripped = line.strip()
|
235
|
+
|
236
|
+
# Check for section headers
|
237
|
+
if stripped.startswith("[") and stripped.endswith("]"):
|
238
|
+
section_name = stripped[1:-1].strip().lower()
|
239
|
+
in_org_section = section_name == organization.lower()
|
240
|
+
if in_org_section:
|
241
|
+
org_section_found = True
|
242
|
+
|
243
|
+
# If we're in the org section and find GERRIT_KNOWN_HOSTS, replace
|
244
|
+
elif in_org_section and "=" in line:
|
245
|
+
key = line.split("=", 1)[0].strip().upper()
|
246
|
+
if key == "GERRIT_KNOWN_HOSTS":
|
247
|
+
# Replace with new host keys (properly escaped for INI)
|
248
|
+
escaped_keys = host_keys.replace("\n", "\\n")
|
249
|
+
new_lines.append(f'GERRIT_KNOWN_HOSTS = "{escaped_keys}"')
|
250
|
+
gerrit_known_hosts_updated = True
|
251
|
+
continue
|
252
|
+
|
253
|
+
new_lines.append(line)
|
254
|
+
|
255
|
+
# If organization section wasn't found, add it
|
256
|
+
if not org_section_found:
|
257
|
+
if new_lines and new_lines[-1].strip():
|
258
|
+
new_lines.append("") # Add blank line before new section
|
259
|
+
new_lines.append(f"[{organization}]")
|
260
|
+
escaped_keys = host_keys.replace("\n", "\\n")
|
261
|
+
new_lines.append(f'GERRIT_KNOWN_HOSTS = "{escaped_keys}"')
|
262
|
+
gerrit_known_hosts_updated = True
|
263
|
+
|
264
|
+
# If section existed but didn't have GERRIT_KNOWN_HOSTS, add it
|
265
|
+
elif not gerrit_known_hosts_updated:
|
266
|
+
# Find the end of the organization section and add the key there
|
267
|
+
section_end = len(new_lines)
|
268
|
+
for i, line in enumerate(new_lines):
|
269
|
+
stripped = line.strip()
|
270
|
+
if stripped.startswith("[") and stripped.endswith("]"):
|
271
|
+
section_name = stripped[1:-1].strip().lower()
|
272
|
+
if section_name == organization.lower():
|
273
|
+
# Find the end of this section
|
274
|
+
for j in range(i + 1, len(new_lines)):
|
275
|
+
if new_lines[j].strip().startswith("["):
|
276
|
+
section_end = j
|
277
|
+
break
|
278
|
+
break
|
279
|
+
|
280
|
+
# Insert the GERRIT_KNOWN_HOSTS entry
|
281
|
+
escaped_keys = host_keys.replace("\n", "\\n")
|
282
|
+
new_lines.insert(section_end, f'GERRIT_KNOWN_HOSTS = "{escaped_keys}"')
|
283
|
+
|
284
|
+
# Write the updated configuration
|
285
|
+
config_file.write_text("\n".join(new_lines), encoding="utf-8")
|
286
|
+
|
287
|
+
log.info(
|
288
|
+
"Successfully saved SSH host keys to configuration file: %s [%s]",
|
289
|
+
config_file,
|
290
|
+
organization,
|
291
|
+
)
|
292
|
+
|
293
|
+
except Exception as exc:
|
294
|
+
raise SSHDiscoveryError(_MSG_SAVE_FAILED.format(config_file=config_file, error=exc)) from exc
|
295
|
+
|
296
|
+
|
297
|
+
def auto_discover_gerrit_host_keys(
|
298
|
+
gerrit_hostname: str | None = None,
|
299
|
+
gerrit_port: int | None = None,
|
300
|
+
organization: str | None = None,
|
301
|
+
save_to_config: bool = True,
|
302
|
+
) -> str | None:
|
303
|
+
"""
|
304
|
+
Automatically discover Gerrit SSH host keys and optionally save to config.
|
305
|
+
|
306
|
+
This is the main entry point for auto-discovery functionality.
|
307
|
+
|
308
|
+
Args:
|
309
|
+
gerrit_hostname: Gerrit hostname (if not provided, tries to detect
|
310
|
+
from context)
|
311
|
+
gerrit_port: Gerrit SSH port (defaults to 29418)
|
312
|
+
organization: GitHub organization (if not provided, tries to detect
|
313
|
+
from env)
|
314
|
+
save_to_config: Whether to save discovered keys to config file
|
315
|
+
|
316
|
+
Returns:
|
317
|
+
The discovered host keys string, or None if discovery failed
|
318
|
+
"""
|
319
|
+
try:
|
320
|
+
# Set defaults
|
321
|
+
if gerrit_port is None:
|
322
|
+
gerrit_port = 29418
|
323
|
+
|
324
|
+
if organization is None:
|
325
|
+
organization = (os.getenv("ORGANIZATION") or os.getenv("GITHUB_REPOSITORY_OWNER") or "").strip()
|
326
|
+
|
327
|
+
if not gerrit_hostname:
|
328
|
+
log.debug("No Gerrit hostname provided for auto-discovery")
|
329
|
+
return None
|
330
|
+
|
331
|
+
if not organization:
|
332
|
+
log.warning("No organization specified for SSH host key auto-discovery. Cannot save to configuration file.")
|
333
|
+
save_to_config = False
|
334
|
+
|
335
|
+
log.info(
|
336
|
+
"Attempting to auto-discover SSH host keys for %s:%d",
|
337
|
+
gerrit_hostname,
|
338
|
+
gerrit_port,
|
339
|
+
)
|
340
|
+
|
341
|
+
# Discover the host keys
|
342
|
+
host_keys = fetch_ssh_host_keys(gerrit_hostname, gerrit_port)
|
343
|
+
|
344
|
+
# Save to configuration if requested and possible
|
345
|
+
if save_to_config and organization:
|
346
|
+
save_host_keys_to_config(host_keys, organization)
|
347
|
+
log.info(
|
348
|
+
"SSH host keys automatically discovered and saved to config "
|
349
|
+
"for organization '%s'. Future runs will use the cached keys.",
|
350
|
+
organization,
|
351
|
+
)
|
352
|
+
else:
|
353
|
+
log.info(
|
354
|
+
"SSH host keys discovered but not saved to configuration. "
|
355
|
+
"Set ORGANIZATION environment variable to enable auto-saving."
|
356
|
+
)
|
357
|
+
|
358
|
+
except SSHDiscoveryError as exc:
|
359
|
+
log.warning("SSH host key auto-discovery failed: %s", exc)
|
360
|
+
return None
|
361
|
+
except Exception as exc:
|
362
|
+
log.warning("Unexpected error during SSH host key auto-discovery: %s", exc)
|
363
|
+
return None
|
364
|
+
else:
|
365
|
+
return host_keys
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: github2gerrit
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.6
|
4
4
|
Summary: Submit a GitHub pull request to a Gerrit repository.
|
5
5
|
Author-email: Matthew Watkins <mwatkins@linuxfoundation.org>
|
6
6
|
License-Expression: Apache-2.0
|
@@ -34,6 +34,8 @@ Requires-Dist: ruff>=0.6.3; extra == "dev"
|
|
34
34
|
Requires-Dist: black>=24.8.0; extra == "dev"
|
35
35
|
Requires-Dist: mypy>=1.11.2; extra == "dev"
|
36
36
|
Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
|
37
|
+
Requires-Dist: types-requests>=2.31.0; extra == "dev"
|
38
|
+
Requires-Dist: types-click>=7.1.8; extra == "dev"
|
37
39
|
Dynamic: license-file
|
38
40
|
|
39
41
|
<!--
|
@@ -103,16 +105,25 @@ stabilize coverage reporting for parallel/xdist runs.
|
|
103
105
|
|
104
106
|
## Duplicate detection
|
105
107
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
108
|
+
Duplicate detection uses a scoring-based approach. Instead of relying on a hash
|
109
|
+
added by this action, the detector compares the first line of the commit message
|
110
|
+
(subject/PR title), analyzes the body text and the set of files changed, and
|
111
|
+
computes a similarity score. When the score meets or exceeds a configurable
|
112
|
+
threshold (default 0.8), the tool treats the change as a duplicate and blocks
|
113
|
+
submission. This approach aims to remain robust even when similar changes
|
114
|
+
appeared outside this pipeline.
|
110
115
|
|
111
116
|
### Examples of detected duplicates
|
112
117
|
|
113
|
-
-
|
114
|
-
|
115
|
-
|
118
|
+
- Dependency bumps for the same package across close versions
|
119
|
+
(e.g., "Bump foo from 1.0 to 1.1" vs "Bump foo from 1.1 to 1.2")
|
120
|
+
with overlapping files — high score
|
121
|
+
- Pre-commit autoupdates that change .pre-commit-config.yaml and hook versions —
|
122
|
+
high score
|
123
|
+
- GitHub Actions version bumps that update .github/workflows/* uses lines —
|
124
|
+
medium to high score
|
125
|
+
- Similar bug fixes with the same subject and significant file overlap —
|
126
|
+
strong match
|
116
127
|
|
117
128
|
### Allowing duplicates
|
118
129
|
|
@@ -288,19 +299,7 @@ jobs:
|
|
288
299
|
submit-to-gerrit:
|
289
300
|
runs-on: ubuntu-latest
|
290
301
|
steps:
|
291
|
-
|
292
|
-
<!-- markdownlint-disable-next-line MD013 -->
|
293
|
-
uses: shimataro/ssh-key-action@d4fffb50872869abe2d9a9098a6d9c5aa7d16be4 # v2.7.0
|
294
|
-
with:
|
295
|
-
key: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
|
296
|
-
name: "id_rsa"
|
297
|
-
known_hosts: ${{ vars.GERRIT_KNOWN_HOSTS }}
|
298
|
-
config: |
|
299
|
-
Host ${{ vars.GERRIT_SERVER }}
|
300
|
-
User ${{ vars.GERRIT_SSH_USER_G2G }}
|
301
|
-
Port ${{ vars.GERRIT_SERVER_PORT }}
|
302
|
-
PubkeyAcceptedKeyTypes +ssh-rsa
|
303
|
-
IdentityFile ~/.ssh/id_rsa
|
302
|
+
|
304
303
|
|
305
304
|
- name: Submit PR to Gerrit (with explicit overrides)
|
306
305
|
id: g2g
|
@@ -334,10 +333,10 @@ jobs:
|
|
334
333
|
|
335
334
|
Notes:
|
336
335
|
|
337
|
-
-
|
338
|
-
|
339
|
-
-
|
340
|
-
|
336
|
+
- The action configures SSH internally using the provided inputs (key,
|
337
|
+
known_hosts) and does not use the runner’s SSH agent or ~/.ssh/config.
|
338
|
+
- Do not add external steps to install SSH keys or edit SSH config; they’re
|
339
|
+
unnecessary and may conflict with the action.
|
341
340
|
|
342
341
|
## GitHub Enterprise support
|
343
342
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
github2gerrit/__init__.py,sha256=N1Vj1HJ28LKCJLAynQdm5jFGQQAz9YSMzZhEfvbBgow,886
|
2
|
+
github2gerrit/cli.py,sha256=86Xvjk9xsSN76ewXjBbA0yWIncnkyIy3VFb2pUN7HAM,34637
|
3
|
+
github2gerrit/config.py,sha256=sTiujlOjCsJbaA-Ftr5XR--9nxs7XH8uEWD-IbGqLYk,17370
|
4
|
+
github2gerrit/core.py,sha256=Tg1Qxg7tvGCxAfC0cSFnkexeN2JVIVkv0zqvov1S-RY,79296
|
5
|
+
github2gerrit/duplicate_detection.py,sha256=ODPzCm6Gv5NZsxkPm1vy4CBsWQ7hIhD7U95TiXWwcts,29986
|
6
|
+
github2gerrit/gerrit_urls.py,sha256=A-bi6JbicnqR5WAg-cLpWzDQczkWMoahCVqNl21wARo,8395
|
7
|
+
github2gerrit/github_api.py,sha256=nteSZjMiFP64pUJc9tqtvUgiaGlKtaH62zJWfGbR19I,10528
|
8
|
+
github2gerrit/gitutils.py,sha256=4-UXLX3L_nUJbXbcYx1FvpikUdsr5BwnnlI-GwbeXu0,19410
|
9
|
+
github2gerrit/models.py,sha256=-iBFJXyWEW1mFNn_wkkHjMenxoKB5SNNzJHhZ2IkxFA,1827
|
10
|
+
github2gerrit/similarity.py,sha256=gcz9wSK6xZjff0MD_VNHLpxJUWH7Z0ZAYT25t46qpgY,15228
|
11
|
+
github2gerrit/ssh_discovery.py,sha256=XSV01p2nMMKBbTWAAmrWr-VMDdBZMxcMt5Nu04pDdH4,12825
|
12
|
+
github2gerrit-0.1.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
13
|
+
github2gerrit-0.1.6.dist-info/METADATA,sha256=QNKgaz_XAC42GVQuNaHoZYTOia2ncvlDaOHatXaarsY,21471
|
14
|
+
github2gerrit-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
github2gerrit-0.1.6.dist-info/entry_points.txt,sha256=MxN2_liIKo3-xJwtAulAeS5GcOS6JS96nvwOQIkP3W8,56
|
16
|
+
github2gerrit-0.1.6.dist-info/top_level.txt,sha256=bWTYXjvuu4sSU90KLT1JlnjD7xV_iXZ-vKoulpjLTy8,14
|
17
|
+
github2gerrit-0.1.6.dist-info/RECORD,,
|
@@ -1,14 +0,0 @@
|
|
1
|
-
github2gerrit/__init__.py,sha256=N1Vj1HJ28LKCJLAynQdm5jFGQQAz9YSMzZhEfvbBgow,886
|
2
|
-
github2gerrit/cli.py,sha256=gvgyoKvNzOdh5H_BaBAkAFXvJEQLsSa4ACqYg_9QdyA,29768
|
3
|
-
github2gerrit/config.py,sha256=_r5BAowI3x5vRKSGcZsJn6NGJqkiPF8hAmfqT1id3I8,10282
|
4
|
-
github2gerrit/core.py,sha256=qatoJ_M6I8kiQeAA9kFT32uuw5Xo7pnUUWht0RL24io,69593
|
5
|
-
github2gerrit/duplicate_detection.py,sha256=J6a8t3ih-ebr6FEhWsaKnXYPQCzwcnFEWhdstmtjnMo,19475
|
6
|
-
github2gerrit/github_api.py,sha256=mgiz55GrTgAVozmoOKSLrnUcX59YxV3p2Llch2COmyE,10523
|
7
|
-
github2gerrit/gitutils.py,sha256=1KmBACvvVDIte0WiuR-AlgswbWEm69G0J2OpmAgPn7Y,18058
|
8
|
-
github2gerrit/models.py,sha256=DAm0pEWvAexOInnxTVrvTnKWhLMd86TfSqT78UohOCo,1791
|
9
|
-
github2gerrit-0.1.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
10
|
-
github2gerrit-0.1.4.dist-info/METADATA,sha256=jJml8yKtMJgtQSfZ1F-UE5dhQmtdEQeo1kyGoBjf17w,21441
|
11
|
-
github2gerrit-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
12
|
-
github2gerrit-0.1.4.dist-info/entry_points.txt,sha256=MxN2_liIKo3-xJwtAulAeS5GcOS6JS96nvwOQIkP3W8,56
|
13
|
-
github2gerrit-0.1.4.dist-info/top_level.txt,sha256=bWTYXjvuu4sSU90KLT1JlnjD7xV_iXZ-vKoulpjLTy8,14
|
14
|
-
github2gerrit-0.1.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|