From: Frantisek Hrbata Date: Tue, 8 Dec 2020 16:56:11 +0000 (+0100) Subject: git-mr-update: add checks for mr ref X-Git-Tag: v0.2~56 X-Git-Url: http://www.hrbata.com/gitweb/?a=commitdiff_plain;h=0b4e62d9749504cda4367d20af0b91acee7b5254;p=gimrr.git git-mr-update: add checks for mr ref Also extend the current checks for other refs. Signed-off-by: Frantisek Hrbata --- diff --git a/git-mr-update b/git-mr-update index f2a0971..9b8a06d 100755 --- a/git-mr-update +++ b/git-mr-update @@ -41,7 +41,7 @@ if user in admins: if newrev == mrlib.rev_zero: sys.exit("You cannot delete ref '{}'.".format(refname)) -match = re.match("^refs/mrs/([0-9a-f]{40})/([^/]+)/(head|tags|mbox)$", refname) +match = re.match("^refs/mrs/([0-9a-f]{40})/([^/]+)/(head|tags|mbox|mr)$", refname) if not match: sys.exit("You cannot push ref '{}'.".format(refname)) @@ -52,8 +52,8 @@ ref_type = match.group(3) if ref_user != user: sys.exit("User '{}' in ref '{}' does not match user '{}' on server.".format(ref_user, refname, user)) -if ref_type not in ["head", "tags", "mbox"]: - sys.exit("Invalid ref type '{}' in '{}'. Allowed types are 'head', 'tags' or 'mbox'.".format(ref_type, refname)) +if ref_type not in ["head", "tags", "mbox", "mr"]: + sys.exit("Invalid ref type '{}' in '{}'. Allowed types are 'head', 'tags', 'mr' or 'mbox'.".format(ref_type, refname)) if oldrev != mrlib.rev_zero: rv, out, err = mrlib.run(["git", "merge-base", "--is-ancestor", oldrev, newrev], die=False) @@ -74,6 +74,59 @@ if ref_type == "head": if out: sys.exit("MR head '{}' already exists as '{}'.".format(ref_mr, out)) +elif ref_type == "mr": + if oldrev != mrlib.rev_zero: + sys.exit("You are not allowed to update 'mr' ref '{}'.".format(refname)) + + rv, out, err = mrlib.run(["git", "for-each-ref", "--format=%(refname)", + "refs/mrs/{}/*/head".format(ref_mr)]) + if not out: + sys.exit("No MR '{}' exists on server.".format(ref_mr)) + + match = re.match("^refs/mrs/{}/([^/]+)/head$".format(ref_mr), out) + mr_owner = match.group(1) + + if user != mr_owner: + sys.exit("Only MR owner '{}' can push 'mr' ref.".format(mr_owner)) + + rv, out, err = mrlib.run(["git", "show", "{}:tags".format(newrev)]) + tags = mrlib.load_user_tags(out, ref_mr, user) + mr_tags = mrlib.get_commit_tags(tags, ref_mr, mrlib.rev_zero) + if not mr_tags: + sys.exit("No MR tags found.") + + for t in ["M", "B", "A", "C", "CC", "AN", "AE", "AT"]: + if t not in mr_tags: + sys.exit("Tag '{}' is required.".format(t)) + + author = mrlib.get_tag_value(mr_tags, "A") + if author != user: + sys.exit("A tag '{}' does not match user '{}'.".format(author, user)) + + mr = mrlib.get_tag_value(mr_tags, "M") + if mr != ref_mr: + sys.exit("M tag '{}' does not MR '{}'.".format(mr, ref_mr)) + + base = mrlib.get_tag_value(mr_tags, "B") + rv, out, err = mrlib.run(["git", "merge-base", "--is-ancestor", base, mr], die=False) + if rv: + sys.exit("B '{}' is not ancestor of M '{}'.".format(base, mr)) + + fmt = "--format=format:%H" + rv, out, err = mrlib.run(["git", "log", fmt, "{}..{}".format(base, mr)]) + commits = list() + for commit in out.split("\n"): + commits.insert(0, commit) + + mrcommits = mrlib.get_tag_value(mr_tags, "C") + if not mrcommits: + sys.exit("No MR commits found.") + + mrcommits = mrcommits.split() + + if commits != mrcommits: + sys.exit("Commits in repo do not match commits in C tag.") + elif ref_type == "tags": rv, out, err = mrlib.run(["git", "for-each-ref", "--format=%(refname)", "refs/mrs/{}/*/head".format(ref_mr)]) @@ -84,16 +137,29 @@ elif ref_type == "tags": mr_owner = match.group(1) rv, out, err = mrlib.run(["git", "show", "{}:tags".format(newrev)]) - tags = mrlib.load_user_tags(out) + tags = mrlib.load_user_tags(out, ref_mr, user) mr_tags = mrlib.get_commit_tags(tags, ref_mr, mrlib.rev_zero) if not mr_tags: sys.exit() - if user != mr_owner: - sys.exit("MR tags can be set by owners and admins only.") + for t in ["M", "B", "A", "C", "CC", "AN", "AE", "AT"]: + if t in mr_tags: + sys.exit("Tag '{}' is reserved and cannot be set.".format(t)) + + if user == mr_owner: + sys.exit() + + for t in ["S", "D"]: + if t in mr_tags: + sys.exit("Tag '{}' can be set only by MR owner.".format(t)) elif ref_type == "mbox": + rv, out, err = mrlib.run(["git", "for-each-ref", "--format=%(refname)", + "refs/mrs/{}/*/head".format(ref_mr)]) + if not out: + sys.exit("No MR '{}' exists on server.".format(ref_mr)) + stdin = "{}\n".format(newrev) if oldrev != mrlib.rev_zero: stdin += "^{}\n".format(oldrev)