mirror of
https://forgejo.stefka.eu/jiriks74/create-pull-request.git
synced 2025-01-18 16:01:06 +01:00
Add v2 alpha
This commit is contained in:
parent
ec6352b0a0
commit
b7565b81a7
16 changed files with 2564 additions and 57 deletions
147
src/create_or_update_branch.py
Normal file
147
src/create_or_update_branch.py
Normal file
|
@ -0,0 +1,147 @@
|
|||
#!/usr/bin/env python3
|
||||
""" Create or Update Branch """
|
||||
import common as cmn
|
||||
from git import Repo, GitCommandError
|
||||
import os
|
||||
|
||||
|
||||
CHERRYPICK_EMPTY = (
|
||||
"The previous cherry-pick is now empty, possibly due to conflict resolution."
|
||||
)
|
||||
|
||||
|
||||
def fetch_successful(repo, repo_url, branch):
|
||||
try:
|
||||
repo.git.fetch(repo_url, f"{branch}:refs/remotes/origin/{branch}")
|
||||
except GitCommandError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def is_ahead(repo, branch_1, branch_2):
|
||||
# Return true if branch_2 is ahead of branch_1
|
||||
return (
|
||||
int(repo.git.rev_list("--right-only", "--count", f"{branch_1}...{branch_2}"))
|
||||
> 0
|
||||
)
|
||||
|
||||
|
||||
def is_behind(repo, branch_1, branch_2):
|
||||
# Return true if branch_2 is behind branch_1
|
||||
return (
|
||||
int(repo.git.rev_list("--left-only", "--count", f"{branch_1}...{branch_2}")) > 0
|
||||
)
|
||||
|
||||
|
||||
def is_even(repo, branch_1, branch_2):
|
||||
# Return true if branch_2 is even with branch_1
|
||||
return not is_ahead(repo, branch_1, branch_2) and not is_behind(
|
||||
repo, branch_1, branch_2
|
||||
)
|
||||
|
||||
|
||||
def has_diff(repo, branch_1, branch_2):
|
||||
diff = repo.git.diff(f"{branch_1}..{branch_2}")
|
||||
return len(diff) > 0
|
||||
|
||||
|
||||
def create_or_update_branch(repo, repo_url, commit_message, base, branch):
|
||||
# Set the default return values
|
||||
action = "none"
|
||||
diff = False
|
||||
|
||||
# Get the working base. This may or may not be the actual base.
|
||||
working_base = repo.git.symbolic_ref("HEAD", "--short")
|
||||
# If the base is not specified it is assumed to be the working base
|
||||
if base is None:
|
||||
base = working_base
|
||||
|
||||
# Save the working base changes to a temporary branch
|
||||
temp_branch = cmn.get_random_string(length=20)
|
||||
repo.git.checkout("HEAD", b=temp_branch)
|
||||
# Commit any uncomitted changes
|
||||
if repo.is_dirty(untracked_files=True):
|
||||
print(f"Uncommitted changes found. Adding a commit.")
|
||||
repo.git.add("-A")
|
||||
repo.git.commit(m=commit_message)
|
||||
|
||||
# Perform fetch and reset the working base
|
||||
# Commits made during the workflow will be removed
|
||||
repo.git.fetch("--force", repo_url, f"{working_base}:{working_base}")
|
||||
|
||||
# If the working base is not the base, rebase the temp branch commits
|
||||
if working_base != base:
|
||||
print(
|
||||
f"Rebasing commits made to branch '{working_base}' on to base branch '{base}'"
|
||||
)
|
||||
# Checkout the actual base
|
||||
repo.git.fetch("--force", repo_url, f"{base}:{base}")
|
||||
repo.git.checkout(base)
|
||||
# Cherrypick commits from the temporary branch starting from the working base
|
||||
commits = repo.git.rev_list("--reverse", f"{working_base}..{temp_branch}", ".")
|
||||
for commit in commits.splitlines():
|
||||
try:
|
||||
repo.git.cherry_pick(
|
||||
"--strategy",
|
||||
"recursive",
|
||||
"--strategy-option",
|
||||
"theirs",
|
||||
f"{commit}",
|
||||
)
|
||||
except GitCommandError as e:
|
||||
if CHERRYPICK_EMPTY not in e.stderr:
|
||||
print("Unexpected error: ", e)
|
||||
raise
|
||||
# Reset the temp branch to the working index
|
||||
repo.git.checkout("-B", temp_branch, "HEAD")
|
||||
# Reset the base
|
||||
repo.git.fetch("--force", repo_url, f"{base}:{base}")
|
||||
|
||||
# Try to fetch the pull request branch
|
||||
if not fetch_successful(repo, repo_url, branch):
|
||||
# The pull request branch does not exist
|
||||
print(f"Pull request branch '{branch}' does not exist yet")
|
||||
# Create the pull request branch
|
||||
repo.git.checkout("HEAD", b=branch)
|
||||
# Check if the pull request branch is ahead of the base
|
||||
diff = is_ahead(repo, base, branch)
|
||||
if diff:
|
||||
action = "created"
|
||||
print(f"Created branch '{branch}'")
|
||||
else:
|
||||
print(
|
||||
f"Branch '{branch}' is not ahead of base '{base}' and will not be created"
|
||||
)
|
||||
else:
|
||||
# The pull request branch exists
|
||||
print(
|
||||
f"Pull request branch '{branch}' already exists as remote branch 'origin/{branch}'"
|
||||
)
|
||||
# Checkout the pull request branch
|
||||
repo.git.checkout(branch)
|
||||
|
||||
if has_diff(repo, branch, temp_branch):
|
||||
# If the branch differs from the recreated temp version then the branch is reset
|
||||
# For changes on base this action is similar to a rebase of the pull request branch
|
||||
print(f"Resetting '{branch}'")
|
||||
repo.git.checkout("-B", branch, temp_branch)
|
||||
# repo.git.switch("-C", branch, temp_branch)
|
||||
|
||||
# Check if the pull request branch has been updated
|
||||
# If the branch was reset or updated it will be ahead
|
||||
# It may be behind if a reset now results in no diff with the base
|
||||
if not is_even(repo, f"origin/{branch}", branch):
|
||||
action = "updated"
|
||||
print(f"Updated branch '{branch}'")
|
||||
else:
|
||||
print(
|
||||
f"Branch '{branch}' is even with its remote and will not be updated"
|
||||
)
|
||||
|
||||
# Check if the pull request branch is ahead of the base
|
||||
diff = is_ahead(repo, base, branch)
|
||||
|
||||
# Delete the temporary branch
|
||||
repo.git.branch("--delete", "--force", temp_branch)
|
||||
|
||||
return {"action": action, "diff": diff, "base": base}
|
Loading…
Add table
Add a link
Reference in a new issue