mirror of
https://github.com/openSUSE/osc.git
synced 2025-11-03 04:52:16 +01:00
Change 'git-obs' to use owner/repo[#pull] arguments consistently
This commit is contained in:
@@ -3,8 +3,8 @@ Feature: `git-obs pr` command
|
||||
|
||||
Background:
|
||||
Given I set working directory to "{context.osc.temp}"
|
||||
And I execute git-obs with args "repo fork pool test-GitPkgA"
|
||||
And I execute git-obs with args "repo clone Admin test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
And I execute git-obs with args "repo fork pool/test-GitPkgA"
|
||||
And I execute git-obs with args "repo clone Admin/test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
And I set working directory to "{context.osc.temp}/test-GitPkgA"
|
||||
And I execute "sed -i 's@^\(Version.*\)@\1.1@' *.spec"
|
||||
And I execute "git commit -m 'Change version' -a"
|
||||
@@ -14,7 +14,7 @@ Background:
|
||||
|
||||
@destructive
|
||||
Scenario: List pull requests
|
||||
When I execute git-obs with args "pr list pool test-GitPkgA"
|
||||
When I execute git-obs with args "pr list pool/test-GitPkgA"
|
||||
Then the exit code is 0
|
||||
And stdout matches
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,7 @@ Background:
|
||||
|
||||
@destructive
|
||||
Scenario: Clone a git repo
|
||||
When I execute git-obs with args "repo clone pool test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
When I execute git-obs with args "repo clone pool/test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -20,5 +20,8 @@ Scenario: Clone a git repo
|
||||
* URL: http://localhost:{context.podman.container.ports[gitea_http]}
|
||||
* User: Admin
|
||||
|
||||
Cloning git repo pool/test-GitPkgA ...
|
||||
Cloning into 'test-GitPkgA'...
|
||||
|
||||
Total cloned repos: 1
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,7 @@ Background:
|
||||
|
||||
@destructive
|
||||
Scenario: Fork a git repo
|
||||
When I execute git-obs with args "repo fork pool test-GitPkgA"
|
||||
When I execute git-obs with args "repo fork pool/test-GitPkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -22,12 +22,14 @@ Scenario: Fork a git repo
|
||||
|
||||
Forking git repo pool/test-GitPkgA ...
|
||||
* Fork created: Admin/test-GitPkgA
|
||||
|
||||
Total forked repos: 1
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Fork a git repo twice under different names
|
||||
When I execute git-obs with args "repo fork pool test-GitPkgA"
|
||||
When I execute git-obs with args "repo fork pool/test-GitPkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -42,8 +44,10 @@ Scenario: Fork a git repo twice under different names
|
||||
|
||||
Forking git repo pool/test-GitPkgA ...
|
||||
* Fork created: Admin/test-GitPkgA
|
||||
|
||||
Total forked repos: 1
|
||||
"""
|
||||
When I execute git-obs with args "repo fork pool test-GitPkgA --new-repo-name=new-package"
|
||||
When I execute git-obs with args "repo fork pool/test-GitPkgA --new-repo-name=new-package"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -59,12 +63,14 @@ Scenario: Fork a git repo twice under different names
|
||||
Forking git repo pool/test-GitPkgA ...
|
||||
* Fork already exists: Admin/test-GitPkgA
|
||||
* WARNING: Using an existing fork with a different name than requested
|
||||
|
||||
Total forked repos: 1
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Fork a git repo from pool and fork someone else's fork of the same repo
|
||||
When I execute git-obs with args "repo fork pool test-GitPkgA"
|
||||
When I execute git-obs with args "repo fork pool/test-GitPkgA"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -79,8 +85,10 @@ Scenario: Fork a git repo from pool and fork someone else's fork of the same rep
|
||||
|
||||
Forking git repo pool/test-GitPkgA ...
|
||||
* Fork created: Admin/test-GitPkgA
|
||||
|
||||
Total forked repos: 1
|
||||
"""
|
||||
When I execute git-obs with args "repo fork -G alice pool test-GitPkgA --new-repo-name=test-GitPkgA-alice"
|
||||
When I execute git-obs with args "repo fork -G alice pool/test-GitPkgA --new-repo-name=test-GitPkgA-alice"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -95,9 +103,11 @@ Scenario: Fork a git repo from pool and fork someone else's fork of the same rep
|
||||
|
||||
Forking git repo pool/test-GitPkgA ...
|
||||
* Fork created: Alice/test-GitPkgA-alice
|
||||
|
||||
Total forked repos: 1
|
||||
"""
|
||||
# this succeeds with 202 and the requested fork is NOT created
|
||||
When I execute git-obs with args "repo fork Alice test-GitPkgA-alice"
|
||||
When I execute git-obs with args "repo fork Alice/test-GitPkgA-alice"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
@@ -112,6 +122,8 @@ Scenario: Fork a git repo from pool and fork someone else's fork of the same rep
|
||||
|
||||
Forking git repo Alice/test-GitPkgA-alice ...
|
||||
* Fork created: Admin/test-GitPkgA-alice
|
||||
|
||||
Total forked repos: 1
|
||||
"""
|
||||
When I execute git-obs with args "repo clone Admin test-GitPkgA-alice --no-ssh-strict-host-key-checking"
|
||||
When I execute git-obs with args "repo clone Admin/test-GitPkgA-alice --no-ssh-strict-host-key-checking"
|
||||
Then the exit code is 0
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -8,6 +9,36 @@ from . import oscerr
|
||||
from .output import print_msg
|
||||
|
||||
|
||||
class OwnerRepoAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, value, option_string=None):
|
||||
from . import gitea_api
|
||||
|
||||
try:
|
||||
if isinstance(value, list):
|
||||
namespace_value = [gitea_api.Repo.split_id(i) for i in value]
|
||||
else:
|
||||
namespace_value = gitea_api.Repo.split_id(value)
|
||||
except ValueError as e:
|
||||
raise argparse.ArgumentError(self, str(e))
|
||||
|
||||
setattr(namespace, self.dest, namespace_value)
|
||||
|
||||
|
||||
class OwnerRepoPullAction(argparse.Action):
|
||||
def __call__(self, parser, namespace, value, option_string=None):
|
||||
from . import gitea_api
|
||||
|
||||
try:
|
||||
if isinstance(value, list):
|
||||
namespace_value = [gitea_api.PullRequest.split_id(i) for i in value]
|
||||
else:
|
||||
namespace_value = gitea_api.PullRequest.split_id(value)
|
||||
except ValueError as e:
|
||||
raise argparse.ArgumentError(self, str(e))
|
||||
|
||||
setattr(namespace, self.dest, namespace_value)
|
||||
|
||||
|
||||
class GitObsCommand(osc.commandline_common.Command):
|
||||
@property
|
||||
def gitea_conf(self):
|
||||
@@ -29,16 +60,20 @@ class GitObsCommand(osc.commandline_common.Command):
|
||||
print(f" * User: {self.gitea_login.user}", file=sys.stderr)
|
||||
print("", file=sys.stderr)
|
||||
|
||||
def add_argument_owner(self):
|
||||
def add_argument_owner_repo(self, **kwargs):
|
||||
self.add_argument(
|
||||
"owner",
|
||||
help="Name of the repository owner (login, org)",
|
||||
"owner_repo",
|
||||
action=OwnerRepoAction,
|
||||
help="Owner and repo: (format: <owner>/<repo>)",
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def add_argument_repo(self):
|
||||
def add_argument_owner_repo_pull(self, **kwargs):
|
||||
self.add_argument(
|
||||
"repo",
|
||||
help="Name of the repository",
|
||||
"owner_repo_pull",
|
||||
action=OwnerRepoPullAction,
|
||||
help="Owner, repo and pull request number (format: <owner>/<repo>#<pull-request-number>)",
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def add_argument_new_repo_name(self):
|
||||
|
||||
@@ -13,11 +13,7 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand):
|
||||
parent = "PullRequestCommand"
|
||||
|
||||
def init_arguments(self):
|
||||
self.add_argument(
|
||||
"id",
|
||||
nargs="+",
|
||||
help="Pull request ID in <owner>/<repo>#<number> format",
|
||||
)
|
||||
self.add_argument_owner_repo_pull(nargs="+")
|
||||
self.add_argument(
|
||||
"-p",
|
||||
"--patch",
|
||||
@@ -34,14 +30,13 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand):
|
||||
|
||||
num_entries = 0
|
||||
failed_entries = []
|
||||
for pr_id in args.id:
|
||||
owner, repo, number = gitea_api.PullRequest.split_id(pr_id)
|
||||
for owner, repo, pull in args.owner_repo_pull:
|
||||
try:
|
||||
pr = gitea_api.PullRequest.get(self.gitea_conn, owner, repo, number).json()
|
||||
pr = gitea_api.PullRequest.get(self.gitea_conn, owner, repo, pull).json()
|
||||
num_entries += 1
|
||||
except gitea_api.GiteaException as e:
|
||||
if e.status == 404:
|
||||
failed_entries.append(pr_id)
|
||||
failed_entries.append(f"{owner}/{repo}#{pull}")
|
||||
continue
|
||||
raise
|
||||
print(gitea_api.PullRequest.to_human_readable_string(pr))
|
||||
@@ -49,10 +44,12 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand):
|
||||
if args.patch:
|
||||
print("")
|
||||
print(tty.colorize("Patch:", "bold"))
|
||||
patch = gitea_api.PullRequest.get_patch(self.gitea_conn, owner, repo, number).data
|
||||
patch = gitea_api.PullRequest.get_patch(self.gitea_conn, owner, repo, pull).data
|
||||
patch = highlight_diff(patch)
|
||||
print(patch.decode("utf-8"))
|
||||
|
||||
print()
|
||||
|
||||
print(f"Total entries: {num_entries}", file=sys.stderr)
|
||||
if failed_entries:
|
||||
print(
|
||||
|
||||
@@ -12,8 +12,7 @@ class PullRequestListCommand(osc.commandline_git.GitObsCommand):
|
||||
parent = "PullRequestCommand"
|
||||
|
||||
def init_arguments(self):
|
||||
self.add_argument_owner()
|
||||
self.add_argument_repo()
|
||||
self.add_argument_owner_repo(nargs="+")
|
||||
self.add_argument(
|
||||
"--state",
|
||||
choices=["open", "closed", "all"],
|
||||
@@ -26,11 +25,14 @@ class PullRequestListCommand(osc.commandline_git.GitObsCommand):
|
||||
|
||||
self.print_gitea_settings()
|
||||
|
||||
data = gitea_api.PullRequest.list(self.gitea_conn, args.owner, args.repo, state=args.state).json()
|
||||
total_entries = 0
|
||||
for owner, repo in args.owner_repo:
|
||||
data = gitea_api.PullRequest.list(self.gitea_conn, owner, repo, state=args.state).json()
|
||||
total_entries += len(data)
|
||||
|
||||
text = gitea_api.PullRequest.list_to_human_readable_string(data, sort=True)
|
||||
if text:
|
||||
print(text)
|
||||
print("", file=sys.stderr)
|
||||
text = gitea_api.PullRequest.list_to_human_readable_string(data, sort=True)
|
||||
if text:
|
||||
print(text)
|
||||
print("", file=sys.stderr)
|
||||
|
||||
print(f"Total entries: {len(data)}", file=sys.stderr)
|
||||
print(f"Total entries: {total_entries}", file=sys.stderr)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import osc.commandline_git
|
||||
|
||||
|
||||
@@ -13,8 +16,7 @@ class RepoCloneCommand(osc.commandline_git.GitObsCommand):
|
||||
parent = "RepoCommand"
|
||||
|
||||
def init_arguments(self):
|
||||
self.add_argument_owner()
|
||||
self.add_argument_repo()
|
||||
self.add_argument_owner_repo(nargs="+")
|
||||
|
||||
self.add_argument(
|
||||
"-a",
|
||||
@@ -45,15 +47,42 @@ class RepoCloneCommand(osc.commandline_git.GitObsCommand):
|
||||
def run(self, args):
|
||||
from osc import gitea_api
|
||||
|
||||
from osc.output import tty
|
||||
|
||||
self.print_gitea_settings()
|
||||
|
||||
gitea_api.Repo.clone(
|
||||
self.gitea_conn,
|
||||
args.owner,
|
||||
args.repo,
|
||||
directory=args.directory,
|
||||
anonymous=args.anonymous,
|
||||
add_remotes=True,
|
||||
ssh_private_key_path=args.ssh_key or self.gitea_login.ssh_key,
|
||||
ssh_strict_host_key_checking=not(args.no_ssh_strict_host_key_checking),
|
||||
)
|
||||
if len(args.owner_repo) > 1 and args.directory:
|
||||
self.parser.error("The --directory option cannot be used with multiple repos")
|
||||
|
||||
num_entries = 0
|
||||
failed_entries = []
|
||||
for owner, repo in args.owner_repo:
|
||||
print(f"Cloning git repo {owner}/{repo} ...", file=sys.stderr)
|
||||
try:
|
||||
gitea_api.Repo.clone(
|
||||
self.gitea_conn,
|
||||
owner,
|
||||
repo,
|
||||
directory=args.directory,
|
||||
anonymous=args.anonymous,
|
||||
add_remotes=True,
|
||||
ssh_private_key_path=args.ssh_key or self.gitea_login.ssh_key,
|
||||
ssh_strict_host_key_checking=not(args.no_ssh_strict_host_key_checking),
|
||||
)
|
||||
num_entries += 1
|
||||
except gitea_api.GiteaException as e:
|
||||
if e.status == 404:
|
||||
print(f" * {tty.colorize('ERROR', 'red,bold')}: Repo doesn't exist: {owner}/{repo}", file=sys.stderr)
|
||||
failed_entries.append(f"{owner}/{repo}")
|
||||
continue
|
||||
raise
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f" * {tty.colorize('ERROR', 'red,bold')}: git clone failed", file=sys.stderr)
|
||||
failed_entries.append(f"{owner}/{repo}")
|
||||
continue
|
||||
|
||||
print("", file=sys.stderr)
|
||||
print(f"Total cloned repos: {num_entries}", file=sys.stderr)
|
||||
if failed_entries:
|
||||
print(f"{tty.colorize('ERROR', 'red,bold')}: Couldn't clone the following repos: {', '.join(failed_entries)}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -12,8 +12,7 @@ class RepoForkCommand(osc.commandline_git.GitObsCommand):
|
||||
parent = "RepoCommand"
|
||||
|
||||
def init_arguments(self):
|
||||
self.add_argument_owner()
|
||||
self.add_argument_repo()
|
||||
self.add_argument_owner_repo(nargs="+")
|
||||
self.add_argument_new_repo_name()
|
||||
|
||||
def run(self, args):
|
||||
@@ -22,15 +21,35 @@ class RepoForkCommand(osc.commandline_git.GitObsCommand):
|
||||
|
||||
self.print_gitea_settings()
|
||||
|
||||
print(f"Forking git repo {args.owner}/{args.repo} ...", file=sys.stderr)
|
||||
try:
|
||||
response = gitea_api.Fork.create(self.gitea_conn, args.owner, args.repo, new_repo_name=args.new_repo_name)
|
||||
repo = response.json()
|
||||
fork_owner = repo["owner"]["login"]
|
||||
fork_repo = repo["name"]
|
||||
print(f" * Fork created: {fork_owner}/{fork_repo}", file=sys.stderr)
|
||||
except gitea_api.ForkExists as e:
|
||||
fork_owner = e.fork_owner
|
||||
fork_repo = e.fork_repo
|
||||
print(f" * Fork already exists: {fork_owner}/{fork_repo}", file=sys.stderr)
|
||||
print(f" * {tty.colorize('WARNING', 'yellow,bold')}: Using an existing fork with a different name than requested", file=sys.stderr)
|
||||
if len(args.owner_repo) > 1 and args.new_repo_name:
|
||||
self.parser.error("The --new-repo-name option cannot be used with multiple repos")
|
||||
|
||||
num_entries = 0
|
||||
failed_entries = []
|
||||
for owner, repo in args.owner_repo:
|
||||
print(f"Forking git repo {owner}/{repo} ...", file=sys.stderr)
|
||||
try:
|
||||
response = gitea_api.Fork.create(self.gitea_conn, owner, repo, new_repo_name=args.new_repo_name)
|
||||
repo = response.json()
|
||||
fork_owner = repo["owner"]["login"]
|
||||
fork_repo = repo["name"]
|
||||
print(f" * Fork created: {fork_owner}/{fork_repo}", file=sys.stderr)
|
||||
num_entries += 1
|
||||
except gitea_api.ForkExists as e:
|
||||
fork_owner = e.fork_owner
|
||||
fork_repo = e.fork_repo
|
||||
print(f" * Fork already exists: {fork_owner}/{fork_repo}", file=sys.stderr)
|
||||
print(f" * {tty.colorize('WARNING', 'yellow,bold')}: Using an existing fork with a different name than requested", file=sys.stderr)
|
||||
num_entries += 1
|
||||
except gitea_api.GiteaException as e:
|
||||
if e.status == 404:
|
||||
print(f" * {tty.colorize('ERROR', 'red,bold')}: Repo doesn't exist: {owner}/{repo}", file=sys.stderr)
|
||||
failed_entries.append(f"{owner}/{repo}")
|
||||
continue
|
||||
raise
|
||||
|
||||
print("", file=sys.stderr)
|
||||
print(f"Total forked repos: {num_entries}", file=sys.stderr)
|
||||
if failed_entries:
|
||||
print(f"{tty.colorize('ERROR', 'red,bold')}: Couldn't fork the following repos: {', '.join(failed_entries)}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -56,8 +56,8 @@ class Fork:
|
||||
return conn.request("POST", url, json_data=json_data)
|
||||
except GiteaException as e:
|
||||
# use ForkExists exception to parse fork_owner and fork_repo from the response
|
||||
fork_exists_exception = ForkExists(e.response, owner, repo)
|
||||
if e.status == 409:
|
||||
fork_exists_exception = ForkExists(e.response, owner, repo)
|
||||
if exist_ok:
|
||||
from . import Repo
|
||||
return Repo.get(conn, fork_exists_exception.fork_owner, fork_exists_exception.fork_repo)
|
||||
|
||||
@@ -22,7 +22,7 @@ class PullRequest:
|
||||
"""
|
||||
Split <owner>/<repo>#<number> into individual components and return them in a tuple.
|
||||
"""
|
||||
match = re.match(r"(.+)/(.+)#(.+)", pr_id)
|
||||
match = re.match(r"^([^/]+)/([^/]+)#([0-9]+)$", pr_id)
|
||||
if not match:
|
||||
raise ValueError(f"Invalid pull request id: {pr_id}")
|
||||
return match.groups()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
|
||||
from .connection import Connection
|
||||
from .connection import GiteaHTTPResponse
|
||||
@@ -8,6 +10,16 @@ from .user import User
|
||||
|
||||
|
||||
class Repo:
|
||||
@classmethod
|
||||
def split_id(cls, repo_id: str) -> Tuple[str, str]:
|
||||
"""
|
||||
Split <owner>/<repo> into individual components and return them in a tuple.
|
||||
"""
|
||||
match = re.match(r"^([^/]+)/([^/]+)$", repo_id)
|
||||
if not match:
|
||||
raise ValueError(f"Invalid repo id: {repo_id}")
|
||||
return match.groups()
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls,
|
||||
|
||||
Reference in New Issue
Block a user