Added rngit client-side handling for direct ref updates
This commit is contained in:
parent
b60eab0fcf
commit
70f5126499
1 changed files with 55 additions and 11 deletions
|
|
@ -532,6 +532,17 @@ class ReticulumGitClient():
|
||||||
|
|
||||||
stderr_arg = sys.stderr if progress_enabled else subprocess.DEVNULL
|
stderr_arg = sys.stderr if progress_enabled else subprocess.DEVNULL
|
||||||
|
|
||||||
|
# Resolve the SHA that local_ref points to
|
||||||
|
sha_result = subprocess.run(["git", "rev-parse", local_ref], capture_output=True, text=True, check=False)
|
||||||
|
if sha_result.returncode != 0:
|
||||||
|
error_msg = f"Could not resolve local ref {local_ref}"
|
||||||
|
git_stdout.write(f"error {remote_ref} {self.escape_for_stdout(error_msg)}\n")
|
||||||
|
git_stdout.flush()
|
||||||
|
continue
|
||||||
|
|
||||||
|
local_sha = sha_result.stdout.strip()
|
||||||
|
|
||||||
|
bundle_empty = False
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
bundle_path = tmpdir + "/push.bundle"
|
bundle_path = tmpdir + "/push.bundle"
|
||||||
|
|
||||||
|
|
@ -542,7 +553,7 @@ class ReticulumGitClient():
|
||||||
exclude_count = 0
|
exclude_count = 0
|
||||||
for sha in self.remote_refs.values():
|
for sha in self.remote_refs.values():
|
||||||
try:
|
try:
|
||||||
# We need to verify Each SHA actually exists locally, since git
|
# We need to verify each SHA actually exists locally, since git
|
||||||
# bundle create will fail if a ^<sha> argument references an object
|
# bundle create will fail if a ^<sha> argument references an object
|
||||||
# not present in the local repository.
|
# not present in the local repository.
|
||||||
result = subprocess.run(["git", "cat-file", "-t", sha], capture_output=True, check=False)
|
result = subprocess.run(["git", "cat-file", "-t", sha], capture_output=True, check=False)
|
||||||
|
|
@ -556,19 +567,52 @@ class ReticulumGitClient():
|
||||||
|
|
||||||
if progress_enabled: create_cmd.insert(3, "--progress")
|
if progress_enabled: create_cmd.insert(3, "--progress")
|
||||||
|
|
||||||
create_result = subprocess.run(create_cmd, stderr=stderr_arg, stdout=subprocess.DEVNULL)
|
create_result = subprocess.run(create_cmd, capture_output=True, text=True, check=False)
|
||||||
|
|
||||||
if create_result.returncode != 0:
|
if create_result.returncode == 0:
|
||||||
error_msg = "Bundle creation failed"
|
if result.stderr: git_stderr.write(result.stderr.decode("utf-8"))
|
||||||
git_stdout.write(f"error {remote_ref} {self.escape_for_stdout(error_msg)}\n")
|
else:
|
||||||
git_stdout.flush()
|
if "empty bundle" in create_result.stderr.lower():
|
||||||
continue
|
# All objects reachable from local_ref already exist on
|
||||||
|
# the remote. In this case, no bundle is needed and we can
|
||||||
|
# update the ref directly via the operations path instead.
|
||||||
|
bundle_empty = True
|
||||||
|
RNS.log(f"Empty bundle for {local_ref}, all objects already on remote", RNS.LOG_DEBUG)
|
||||||
|
|
||||||
with open(bundle_path, "rb") as f: bundle_data = f.read()
|
else:
|
||||||
|
if progress_enabled and create_result.stderr: git_stderr.write(create_result.stderr)
|
||||||
|
error_msg = "Bundle creation failed"
|
||||||
|
git_stdout.write(f"error {remote_ref} {self.escape_for_stdout(error_msg)}\n")
|
||||||
|
git_stdout.flush()
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not bundle_empty:
|
||||||
|
with open(bundle_path, "rb") as f: bundle_data = f.read()
|
||||||
|
|
||||||
|
request_data = { self.IDX_REPOSITORY: self.repo_path, "local_ref": local_ref, "remote_ref": remote_ref,
|
||||||
|
"force": force, "bundle": bundle_data }
|
||||||
|
|
||||||
|
response, metadata = self.send_request(self.PATH_PUSH, request_data)
|
||||||
|
|
||||||
|
if not response or not isinstance(response, bytes):
|
||||||
|
git_stdout.write(f"error {remote_ref} {self.escape_for_stdout('No response from server')}\n")
|
||||||
|
git_stdout.flush()
|
||||||
|
continue
|
||||||
|
|
||||||
|
status_byte = response[0]
|
||||||
|
if status_byte != 0:
|
||||||
|
error_msg = response[1:].decode('utf-8', errors='ignore')
|
||||||
|
git_stdout.write(f"error {remote_ref} {self.escape_for_stdout(error_msg)}\n")
|
||||||
|
git_stdout.flush()
|
||||||
|
continue
|
||||||
|
|
||||||
|
# When all reachable objects already exist on the remote, send a
|
||||||
|
# direct ref update operation instead of a bundle.
|
||||||
|
if bundle_empty:
|
||||||
|
openration = {"action": "update_ref", "ref": remote_ref, "sha": local_sha, "force": force}
|
||||||
|
request_data = { self.IDX_REPOSITORY: self.repo_path,
|
||||||
|
"operations": [operation] }
|
||||||
|
|
||||||
request_data = { self.IDX_REPOSITORY: self.repo_path, "local_ref": local_ref, "remote_ref": remote_ref,
|
|
||||||
"force": force, "bundle": bundle_data }
|
|
||||||
|
|
||||||
response, metadata = self.send_request(self.PATH_PUSH, request_data)
|
response, metadata = self.send_request(self.PATH_PUSH, request_data)
|
||||||
|
|
||||||
if not response or not isinstance(response, bytes):
|
if not response or not isinstance(response, bytes):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue