Last active
February 8, 2023 19:47
-
-
Save jkbjh/7c2fdf66a38113946cccca908207cb70 to your computer and use it in GitHub Desktop.
push to a remote checked out repository (by pushing into a temporary branch and then ssh-ing to the repository and performing the merge)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import argparse | |
import re | |
import subprocess | |
import sys | |
import uuid | |
url_rex = re.compile( | |
"^(?P<user>.*?)@(?P<host>.*?):(?:(?P<port>[0-9]*?))?(?P<path>.*?/.*?)$" | |
) | |
refspec_match = re.compile("^(?P<noff>[+]?)(?P<src>[^:]+):(?P<dst>[^:]+)$").match | |
def build_ssh_url(urldict): | |
port_str = ":" + str(urldict["port"]) if urldict["port"] else "" | |
return "{username}@{host}{port_str}".format( | |
username=urldict["user"], host=urldict["host"], port_str=port_str | |
) | |
def get_url(url_or_origin): | |
print((">%r<" % (url_or_origin,))) | |
match = url_rex.match(url_or_origin) | |
if match: | |
return None, url_or_origin, match.groupdict() | |
return (url_or_origin,) + get_url( | |
subprocess.check_output(["git", "remote", "get-url", url_or_origin]).decode("utf-8").strip() | |
)[1:] | |
if __name__ == "__main__": | |
TMP_BRANCH = "COPUSH_TMP_" + uuid.uuid4().hex | |
print((repr(sys.argv))) | |
parser = argparse.ArgumentParser( | |
epilog=f"{sys.argv[0]} REMOTE local_branch:remote_branch" | |
) | |
parser.add_argument("remote", help="remote.") | |
parser.add_argument("refspec", help="refspec") | |
try: | |
args = parser.parse_args(sys.argv[1:]) | |
except SystemExit as e: | |
if e.code != 0: | |
parser.print_help() | |
raise | |
remote, url, urldict = get_url(args.remote) | |
print(("remote:", remote)) | |
refspecdict = refspec_match(args.refspec).groupdict() | |
print(f"Remote branch: {TMP_BRANCH}") | |
print(("urldict", urldict)) | |
print(("refspecdict", refspecdict)) | |
print("-------------------") | |
assert not refspecdict["noff"] # non-fast-forward not yet supported | |
cmd = ["git", "push", url, "%s:%s" % (refspecdict["src"], TMP_BRANCH)] | |
print((repr(cmd))) | |
result = subprocess.check_call(cmd) | |
sshcmd = ("cd {path}; " | |
"if [ $(git symbolic-ref -q HEAD --short) = '{dst}' ]; then " # test whether the branch {dst} is currently checked out (HEAD) | |
"git merge {tmp_branch} --ff-only --no-commit; " # if it is checked out, perform a non-merging merge (fast-forward) without merge-commits (--no-commit) | |
"else " | |
"git fetch . {tmp_branch}:{dst}; " # if it isn't checked out, we don't need to merge but just fetch. | |
"fi; " | |
"git branch -D {tmp_branch}" # delete the temporary COPUSH branch. | |
).format( | |
path=urldict["path"], tmp_branch=TMP_BRANCH, dst=refspecdict["dst"] | |
) | |
cmd = ["ssh", build_ssh_url(urldict), sshcmd] | |
result = subprocess.check_call(cmd) | |
if remote is not None: | |
subprocess.check_call(["git", "fetch", remote]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment