mirror of
https://github.com/markqvist/Reticulum.git
synced 2026-07-24 16:58:11 -07:00
Cleanup. Prepared artifact fetch.
This commit is contained in:
@@ -86,6 +86,7 @@ def program_setup(configdir, rnsconfigdir=None, verbosity=0, quietness=0, servic
|
|||||||
git_client = ReticulumGitClient(configdir=configdir, verbosity=targetverbosity, identitypath=identity)
|
git_client = ReticulumGitClient(configdir=configdir, verbosity=targetverbosity, identitypath=identity)
|
||||||
if operation == "list": git_client.list_releases(remote=task["remote"])
|
if operation == "list": git_client.list_releases(remote=task["remote"])
|
||||||
elif operation == "view": git_client.view_release(remote=task["remote"], target=task["target"])
|
elif operation == "view": git_client.view_release(remote=task["remote"], target=task["target"])
|
||||||
|
elif operation == "fetch": git_client.fetch_release(remote=task["remote"], target=task["target"])
|
||||||
elif operation == "create": git_client.create_release(remote=task["remote"], target=task["target"], signer=task["signer"], name=task["name"])
|
elif operation == "create": git_client.create_release(remote=task["remote"], target=task["target"], signer=task["signer"], name=task["name"])
|
||||||
elif operation == "delete": git_client.delete_release(remote=task["remote"], target=task["target"])
|
elif operation == "delete": git_client.delete_release(remote=task["remote"], target=task["target"])
|
||||||
elif operation == "latest": git_client.latest_release(remote=task["remote"], target=task["target"])
|
elif operation == "latest": git_client.latest_release(remote=task["remote"], target=task["target"])
|
||||||
@@ -161,7 +162,7 @@ def main():
|
|||||||
parser.add_argument("-s", "--signer", action="store", metavar="PATH", default=None, help="path to signing identity, if different from release identity", type=str)
|
parser.add_argument("-s", "--signer", action="store", metavar="PATH", default=None, help="path to signing identity, if different from release identity", type=str)
|
||||||
parser.add_argument("-n", "--name", action="store", metavar="name", default=None, help="package name if different from repo name", type=str)
|
parser.add_argument("-n", "--name", action="store", metavar="name", default=None, help="package name if different from repo name", type=str)
|
||||||
parser.add_argument("repository", nargs="?", default=None, help="URL of remote repository", type=str)
|
parser.add_argument("repository", nargs="?", default=None, help="URL of remote repository", type=str)
|
||||||
parser.add_argument("operation", nargs="?", default=None, help="list, view, create, latest or delete", type=str)
|
parser.add_argument("operation", nargs="?", default=None, help="list, view, fetch, create, latest or delete", type=str)
|
||||||
parser.add_argument("target", nargs="?", default=None, help="tag and path to release artifacts directory", type=str)
|
parser.add_argument("target", nargs="?", default=None, help="tag and path to release artifacts directory", type=str)
|
||||||
|
|
||||||
elif subcommand == "perms":
|
elif subcommand == "perms":
|
||||||
@@ -524,7 +525,7 @@ class ReticulumGitClient():
|
|||||||
#########################
|
#########################
|
||||||
|
|
||||||
def create_repository(self, remote=None):
|
def create_repository(self, remote=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -565,13 +566,13 @@ class ReticulumGitClient():
|
|||||||
####################
|
####################
|
||||||
|
|
||||||
def fork_repository(self, source=None, target=None):
|
def fork_repository(self, source=None, target=None):
|
||||||
if not source: print(f"No source specified"); exit(1)
|
if not source: self.abort(f"No source specified")
|
||||||
if not target: print(f"No target specified"); exit(1)
|
if not target: self.abort(f"No target specified")
|
||||||
self._remote_clone_operation(source, target, self.PATH_FORK, "fork")
|
self._remote_clone_operation(source, target, self.PATH_FORK, "fork")
|
||||||
|
|
||||||
def mirror_repository(self, source=None, target=None):
|
def mirror_repository(self, source=None, target=None):
|
||||||
if not source: print(f"No source specified"); exit(1)
|
if not source: self.abort(f"No source specified")
|
||||||
if not target: print(f"No target specified"); exit(1)
|
if not target: self.abort(f"No target specified")
|
||||||
self._remote_clone_operation(source, target, self.PATH_MIRROR, "mirror")
|
self._remote_clone_operation(source, target, self.PATH_MIRROR, "mirror")
|
||||||
|
|
||||||
def _resolve_aliased_url(self, url):
|
def _resolve_aliased_url(self, url):
|
||||||
@@ -627,7 +628,7 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def sync_repository(self, remote=None):
|
def sync_repository(self, remote=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -717,7 +718,7 @@ class ReticulumGitClient():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def list_releases(self, remote=None):
|
def list_releases(self, remote=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -775,8 +776,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def view_release(self, remote=None, target=None):
|
def view_release(self, remote=None, target=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if not target: print(f"No target specified"); exit(1)
|
if not target: self.abort(f"No target specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -833,17 +834,56 @@ class ReticulumGitClient():
|
|||||||
finally:
|
finally:
|
||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
|
def fetch_release(self, remote=None, target=None):
|
||||||
|
if not remote: self.abort(f"No remote specified")
|
||||||
|
if not target: self.abort(f"No target specified")
|
||||||
|
self.connect_remote(remote)
|
||||||
|
|
||||||
|
timeout = self.link_timeout
|
||||||
|
while not self.link_ready and not self.link_failed and timeout > 0:
|
||||||
|
time.sleep(self.wait_sleep)
|
||||||
|
timeout -= self.wait_sleep
|
||||||
|
|
||||||
|
if not self.link_ready: self.abort("Link establishment failed")
|
||||||
|
|
||||||
|
try:
|
||||||
|
destination_hash, group, repo = self.parse_remote_url(remote)
|
||||||
|
repo_path = f"{group}/{repo}"
|
||||||
|
|
||||||
|
parts = target.split(":")
|
||||||
|
if len(parts) < 2: self.abort("Invalid release specification")
|
||||||
|
tag = parts[0]
|
||||||
|
artifact = parts[1]
|
||||||
|
|
||||||
|
def fetch(name):
|
||||||
|
request_data = {self.IDX_REPOSITORY: repo_path, "operation": "fetch", "tag": tag, "artifact": name}
|
||||||
|
response, metadata = self.send_request(self.PATH_RELEASE, request_data, timeout=30)
|
||||||
|
print("\r \r", end="")
|
||||||
|
if not response or not isinstance(response, bytes): self.abort("No response from remote")
|
||||||
|
status_byte = response[0]
|
||||||
|
if status_byte != 0:
|
||||||
|
error_msg = response[1:].decode("utf-8", errors="ignore")
|
||||||
|
self.abort(f"Remote error: {error_msg}")
|
||||||
|
if len(response) <= 1: self.abort("Empty response from remote")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# TODO: Implement
|
||||||
|
|
||||||
|
except Exception as e: self.abort(f"Error viewing release: {e}")
|
||||||
|
finally:
|
||||||
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def create_release(self, remote=None, target=None, signer=None, name=None):
|
def create_release(self, remote=None, target=None, signer=None, name=None):
|
||||||
if signer:
|
if signer:
|
||||||
try:
|
try:
|
||||||
identity_path = os.path.expanduser(signer)
|
identity_path = os.path.expanduser(signer)
|
||||||
if not os.path.isfile(identity_path): print(f"Signer identity {identity_path} does not exist"); exit(1)
|
if not os.path.isfile(identity_path): self.abort(f"Signer identity {identity_path} does not exist")
|
||||||
else: signer = RNS.Identity.from_file(signer)
|
else: signer = RNS.Identity.from_file(signer)
|
||||||
if not signer: print(f"Could not load signer identity from {identity_path}"); exit(1)
|
if not signer: self.abort(f"Could not load signer identity from {identity_path}")
|
||||||
except Exception as e: print(f"Could not load signer identity from {identity_path}: {e}"); exit(1)
|
except Exception as e: self.abort(f"Could not load signer identity from {identity_path}: {e}")
|
||||||
|
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if not target: print(f"No target specified"); exit(1)
|
if not target: self.abort(f"No target specified")
|
||||||
if not signer: signer = self.identity
|
if not signer: signer = self.identity
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
@@ -861,15 +901,11 @@ class ReticulumGitClient():
|
|||||||
release_time = int(time.time())
|
release_time = int(time.time())
|
||||||
release_time_iso = datetime.fromtimestamp(release_time, tz=timezone.utc).isoformat().replace("+00:00", "Z")
|
release_time_iso = datetime.fromtimestamp(release_time, tz=timezone.utc).isoformat().replace("+00:00", "Z")
|
||||||
|
|
||||||
# Parse target - can be:
|
|
||||||
# 1. Just a tag name: "v1.0.0"
|
|
||||||
# 3. Tag with path to artifacts directory: "v1.0.0:/path/to/artifacts"
|
|
||||||
|
|
||||||
parts = target.split(":")
|
parts = target.split(":")
|
||||||
if len(parts) < 2: self.abort("Invalid release specification\nDid you provide both a tag and artifacts path such as \"1.0.0:./dist\"?")
|
if len(parts) < 2: self.abort("Invalid release specification\nDid you provide both a tag and artifacts path such as \"1.0.0:./dist\"?")
|
||||||
tag = parts[0]
|
tag = parts[0]
|
||||||
artifacts_path = os.path.expanduser(parts[1])
|
artifacts_path = os.path.expanduser(parts[1])
|
||||||
commit_hash = ""
|
commit_hash = None # TODO: Get commit hash from tag
|
||||||
|
|
||||||
if not os.path.isdir(artifacts_path): self.abort("Specified artifacts directory does not exist")
|
if not os.path.isdir(artifacts_path): self.abort("Specified artifacts directory does not exist")
|
||||||
artifacts = [f for f in os.listdir(artifacts_path) if os.path.isfile(os.path.join(artifacts_path, f))]
|
artifacts = [f for f in os.listdir(artifacts_path) if os.path.isfile(os.path.join(artifacts_path, f))]
|
||||||
@@ -882,8 +918,8 @@ class ReticulumGitClient():
|
|||||||
|
|
||||||
# Generate manifest
|
# Generate manifest
|
||||||
package_name = name or repo
|
package_name = name or repo
|
||||||
manifest_meta = {"name": package_name ,"version": tag, "released": release_time_iso,
|
manifest_meta = {"name": package_name ,"version": tag, "released": release_time_iso, "timestamp": release_time,
|
||||||
"timestamp": release_time, "artifacts": []}
|
"origin": destination_hash, "commit": commit_hash, "artifacts": []}
|
||||||
try:
|
try:
|
||||||
manifest_path = artifacts_path+f"/manifest.{self.MSG_EXT}"
|
manifest_path = artifacts_path+f"/manifest.{self.MSG_EXT}"
|
||||||
for artifact in artifacts:
|
for artifact in artifacts:
|
||||||
@@ -902,7 +938,7 @@ class ReticulumGitClient():
|
|||||||
manifest = create_rsg(signer, notes, embed=True, meta=manifest_meta)
|
manifest = create_rsg(signer, notes, embed=True, meta=manifest_meta)
|
||||||
with open(manifest_path, "wb") as fh: fh.write(manifest)
|
with open(manifest_path, "wb") as fh: fh.write(manifest)
|
||||||
|
|
||||||
except Exception as e: print(f"Release manifest generation failed: {e}"); exit(1)
|
except Exception as e: self.abort(f"Release manifest generation failed: {e}")
|
||||||
|
|
||||||
# Step 1: Initialize release
|
# Step 1: Initialize release
|
||||||
print("Initializing release on remote...")
|
print("Initializing release on remote...")
|
||||||
@@ -967,8 +1003,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def delete_release(self, remote=None, target=None):
|
def delete_release(self, remote=None, target=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if not target: print(f"No target specified"); exit(1)
|
if not target: self.abort(f"No target specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1010,8 +1046,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def latest_release(self, remote=None, target=None):
|
def latest_release(self, remote=None, target=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if not target: print(f"No target specified"); exit(1)
|
if not target: self.abort(f"No target specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1057,7 +1093,7 @@ class ReticulumGitClient():
|
|||||||
##########################
|
##########################
|
||||||
|
|
||||||
def group_permissions(self, remote=None):
|
def group_permissions(self, remote=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1107,7 +1143,7 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def repository_permissions(self, remote=None):
|
def repository_permissions(self, remote=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1163,7 +1199,7 @@ class ReticulumGitClient():
|
|||||||
########################
|
########################
|
||||||
|
|
||||||
def work_list(self, remote=None, scope="active"):
|
def work_list(self, remote=None, scope="active"):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1220,8 +1256,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_view(self, remote=None, doc_id=None, scope="active"):
|
def work_view(self, remote=None, doc_id=None, scope="active"):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1295,8 +1331,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_create(self, remote=None, title=None):
|
def work_create(self, remote=None, title=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if not title: print(f"No title specified"); exit(1)
|
if not title: self.abort(f"No title specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1340,8 +1376,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_propose(self, remote=None, title=None):
|
def work_propose(self, remote=None, title=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if not title: print(f"No title specified"); exit(1)
|
if not title: self.abort(f"No title specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1385,8 +1421,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_edit(self, remote=None, doc_id=None, title=None, scope="active"):
|
def work_edit(self, remote=None, doc_id=None, title=None, scope="active"):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1439,8 +1475,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_delete(self, remote=None, doc_id=None, scope="active"):
|
def work_delete(self, remote=None, doc_id=None, scope="active"):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1479,8 +1515,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_comment(self, remote=None, doc_id=None, scope="active"):
|
def work_comment(self, remote=None, doc_id=None, scope="active"):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1522,8 +1558,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_complete(self, remote=None, doc_id=None):
|
def work_complete(self, remote=None, doc_id=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1561,8 +1597,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_activate(self, remote=None, doc_id=None):
|
def work_activate(self, remote=None, doc_id=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
@@ -1600,8 +1636,8 @@ class ReticulumGitClient():
|
|||||||
if self.link: self.link.teardown()
|
if self.link: self.link.teardown()
|
||||||
|
|
||||||
def work_permissions(self, remote=None, doc_id=None):
|
def work_permissions(self, remote=None, doc_id=None):
|
||||||
if not remote: print(f"No remote specified"); exit(1)
|
if not remote: self.abort(f"No remote specified")
|
||||||
if doc_id is None: print(f"No document ID specified"); exit(1)
|
if doc_id is None: self.abort(f"No document ID specified")
|
||||||
self.connect_remote(remote)
|
self.connect_remote(remote)
|
||||||
|
|
||||||
timeout = self.link_timeout
|
timeout = self.link_timeout
|
||||||
|
|||||||
Reference in New Issue
Block a user