1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
"""
"make update" for all platforms, git repository
"""
import argparse
import os
import sys
import make_utils
from pathlib import Path
from make_utils import call, check_output
from typing import (
List,
)
class Submodule:
path: str
branch: str
branch_fallback: str
def __init__(self, path: str, branch: str, branch_fallback: str) -> None:
self.path = path
self.branch = branch
self.branch_fallback = branch_fallback
def print_stage(text: str) -> None:
print("")
print(text)
print("")
def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--no-manual", action="store_true")
parser.add_argument("--no-locale", action="store_true")
parser.add_argument("--git-command", default="git")
return parser.parse_args()
def run_git(path: Path, commands: List, exit_on_error: bool = True) -> str:
args = parse_arguments()
return check_output([args.git_command, "-C", path] + commands, exit_on_error)
def get_manual_git_root() -> str:
return check_output([args.git_command, "rev-parse", "--show-toplevel"])
def git_update_skip(args: argparse.Namespace, path: Path, check_remote_exists: bool = True) -> str:
"""Tests if git repo can be updated"""
if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update manual\n")
sys.exit(1)
if make_utils.command_missing(args.git_command + "-lfs"):
sys.stderr.write("git LFS not found, can't update manual\n")
sys.exit(1)
# Abort if a rebase is still progress.
rebase_merge = run_git(
path, ['rev-parse', '--git-path', 'rebase-merge'], exit_on_error=False)
rebase_apply = run_git(
path, ['rev-parse', '--git-path', 'rebase-apply'], exit_on_error=False)
merge_head = run_git(
path, ['rev-parse', '--git-path', 'MERGE_HEAD'], exit_on_error=False)
if (
os.path.exists(rebase_merge) or
os.path.exists(rebase_apply) or
os.path.exists(merge_head)
):
return "rebase or merge in progress, complete it first"
# Abort if uncommitted changes.
changes = run_git(path, ['status', '--porcelain',
'--untracked-files=no', '--ignore-submodules'])
if len(changes) != 0:
return "you have unstaged changes"
# Test if there is an upstream branch configured
if check_remote_exists:
branch = run_git(path, ["rev-parse", "--abbrev-ref", "HEAD"])
remote = run_git(path, ["config", "branch." +
branch + ".remote"], exit_on_error=False)
if len(remote) == 0:
return "no remote branch to pull from"
return ""
def use_upstream_workflow(args: argparse.Namespace, path: Path) -> bool:
return make_utils.git_remote_exist([args.git_command, "-C", path], "upstream")
def work_tree_update_upstream_workflow(args: argparse.Namespace, path: Path, use_fetch: bool = True) -> str:
"""
Update the repository using the Github style of fork organization
Returns true if the current local branch has been updated to the upstream state.
Otherwise false is returned.
"""
branch_name = make_utils.git_branch([args.git_command, "-C"], path)
if use_fetch:
run_git(path, ["fetch", "upstream"])
upstream_branch = f"upstream/{branch_name}"
if not make_utils.git_branch_exists([args.git_command, "-C", path], upstream_branch):
return "no_branch"
retcode = call((args.git_command, "-C", path, "merge",
"--ff-only", upstream_branch), exit_on_error=False)
if retcode != 0:
return "Unable to fast forward\n"
return ""
def work_tree_update(args: argparse.Namespace, path: Path, use_fetch: bool = True) -> str:
"""
Update the Git working tree using the best strategy
This function detects whether it is a github style of fork remote organization is used, or
is it a repository which origin is an upstream.
"""
if use_upstream_workflow(args, path):
message = work_tree_update_upstream_workflow(args, path, use_fetch)
if message != "no_branch":
return message
# If there is upstream configured but the local branch is not in the upstream, try to
# update the branch from the fork.
run_git(path, ["pull", "--rebase"])
return ""
def manual_update(args: argparse.Namespace) -> str:
"""Update the root manual directory"""
print_stage("Updating Manual Git Repository")
return work_tree_update(args, Path(get_manual_git_root()))
def locale_exists() -> bool:
locale_dir = os.path.join(get_manual_git_root(), "locale")
if os.path.exists(locale_dir):
return True
return False
def locale_update(args: argparse.Namespace) -> str:
"""Update the translations directory"""
if not locale_exists():
return "locale directory not found skipping"
print_stage("Updating manual translations Git Repository")
locale_dir = os.path.join(get_manual_git_root(), "locale")
return work_tree_update(args, locale_dir)
if __name__ == "__main__":
args = parse_arguments()
manual_skip_msg = ""
locale_skip_msg = ""
manual_dir = get_manual_git_root()
locale_dir = os.path.join(get_manual_git_root(), "locale")
if not args.no_manual:
manual_skip_msg = git_update_skip(args, manual_dir)
if not manual_skip_msg:
manual_skip_msg = manual_update(args)
if manual_skip_msg:
manual_skip_msg = "Manual repository skipped: " + manual_skip_msg + "\n"
if not args.no_locale and os.path.exists(locale_dir):
locale_skip_msg = git_update_skip(args, locale_dir)
if not locale_skip_msg:
locale_skip_msg = locale_update(args)
if locale_skip_msg:
locale_skip_msg = "locale repository skipped: " + locale_skip_msg + "\n"
# Report any skipped repositories at the end, so it's not as easy to miss.
skip_msg = manual_skip_msg + locale_skip_msg
if skip_msg:
print_stage(skip_msg.strip())
|