1
0
mirror of https://github.com/openSUSE/osc.git synced 2025-11-04 13:28:54 +01:00

Change 'git-obs' to use owner/repo[#pull] arguments consistently

This commit is contained in:
2025-01-15 17:01:47 +01:00
parent 99dcb4e10a
commit e23c566b0d
11 changed files with 172 additions and 63 deletions

View File

@@ -3,8 +3,8 @@ Feature: `git-obs pr` command
Background: Background:
Given I set working directory to "{context.osc.temp}" 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 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 clone Admin/test-GitPkgA --no-ssh-strict-host-key-checking"
And I set working directory to "{context.osc.temp}/test-GitPkgA" And I set working directory to "{context.osc.temp}/test-GitPkgA"
And I execute "sed -i 's@^\(Version.*\)@\1.1@' *.spec" And I execute "sed -i 's@^\(Version.*\)@\1.1@' *.spec"
And I execute "git commit -m 'Change version' -a" And I execute "git commit -m 'Change version' -a"
@@ -14,7 +14,7 @@ Background:
@destructive @destructive
Scenario: List pull requests 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 Then the exit code is 0
And stdout matches And stdout matches
""" """

View File

@@ -7,7 +7,7 @@ Background:
@destructive @destructive
Scenario: Clone a git repo 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 Then the exit code is 0
And stdout is And stdout is
""" """
@@ -20,5 +20,8 @@ Scenario: Clone a git repo
* URL: http://localhost:{context.podman.container.ports[gitea_http]} * URL: http://localhost:{context.podman.container.ports[gitea_http]}
* User: Admin * User: Admin
Cloning git repo pool/test-GitPkgA ...
Cloning into 'test-GitPkgA'... Cloning into 'test-GitPkgA'...
Total cloned repos: 1
""" """

View File

@@ -7,7 +7,7 @@ Background:
@destructive @destructive
Scenario: Fork a git repo 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 Then the exit code is 0
And stdout is And stdout is
""" """
@@ -22,12 +22,14 @@ Scenario: Fork a git repo
Forking git repo pool/test-GitPkgA ... Forking git repo pool/test-GitPkgA ...
* Fork created: Admin/test-GitPkgA * Fork created: Admin/test-GitPkgA
Total forked repos: 1
""" """
@destructive @destructive
Scenario: Fork a git repo twice under different names 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 Then the exit code is 0
And stdout is And stdout is
""" """
@@ -42,8 +44,10 @@ Scenario: Fork a git repo twice under different names
Forking git repo pool/test-GitPkgA ... Forking git repo pool/test-GitPkgA ...
* Fork created: Admin/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 Then the exit code is 0
And stdout is And stdout is
""" """
@@ -59,12 +63,14 @@ Scenario: Fork a git repo twice under different names
Forking git repo pool/test-GitPkgA ... Forking git repo pool/test-GitPkgA ...
* Fork already exists: Admin/test-GitPkgA * Fork already exists: Admin/test-GitPkgA
* WARNING: Using an existing fork with a different name than requested * WARNING: Using an existing fork with a different name than requested
Total forked repos: 1
""" """
@destructive @destructive
Scenario: Fork a git repo from pool and fork someone else's fork of the same repo 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 Then the exit code is 0
And stdout is 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 ... Forking git repo pool/test-GitPkgA ...
* Fork created: Admin/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 Then the exit code is 0
And stdout is 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 ... Forking git repo pool/test-GitPkgA ...
* Fork created: Alice/test-GitPkgA-alice * Fork created: Alice/test-GitPkgA-alice
Total forked repos: 1
""" """
# this succeeds with 202 and the requested fork is NOT created # 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 Then the exit code is 0
And stdout is 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 ... Forking git repo Alice/test-GitPkgA-alice ...
* Fork created: Admin/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 Then the exit code is 0

View File

@@ -1,3 +1,4 @@
import argparse
import os import os
import subprocess import subprocess
import sys import sys
@@ -8,6 +9,36 @@ from . import oscerr
from .output import print_msg 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): class GitObsCommand(osc.commandline_common.Command):
@property @property
def gitea_conf(self): 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(f" * User: {self.gitea_login.user}", file=sys.stderr)
print("", file=sys.stderr) print("", file=sys.stderr)
def add_argument_owner(self): def add_argument_owner_repo(self, **kwargs):
self.add_argument( self.add_argument(
"owner", "owner_repo",
help="Name of the repository owner (login, org)", 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( self.add_argument(
"repo", "owner_repo_pull",
help="Name of the repository", action=OwnerRepoPullAction,
help="Owner, repo and pull request number (format: <owner>/<repo>#<pull-request-number>)",
**kwargs,
) )
def add_argument_new_repo_name(self): def add_argument_new_repo_name(self):

View File

@@ -13,11 +13,7 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand):
parent = "PullRequestCommand" parent = "PullRequestCommand"
def init_arguments(self): def init_arguments(self):
self.add_argument( self.add_argument_owner_repo_pull(nargs="+")
"id",
nargs="+",
help="Pull request ID in <owner>/<repo>#<number> format",
)
self.add_argument( self.add_argument(
"-p", "-p",
"--patch", "--patch",
@@ -34,14 +30,13 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand):
num_entries = 0 num_entries = 0
failed_entries = [] failed_entries = []
for pr_id in args.id: for owner, repo, pull in args.owner_repo_pull:
owner, repo, number = gitea_api.PullRequest.split_id(pr_id)
try: 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 num_entries += 1
except gitea_api.GiteaException as e: except gitea_api.GiteaException as e:
if e.status == 404: if e.status == 404:
failed_entries.append(pr_id) failed_entries.append(f"{owner}/{repo}#{pull}")
continue continue
raise raise
print(gitea_api.PullRequest.to_human_readable_string(pr)) print(gitea_api.PullRequest.to_human_readable_string(pr))
@@ -49,10 +44,12 @@ class PullRequestGetCommand(osc.commandline_git.GitObsCommand):
if args.patch: if args.patch:
print("") print("")
print(tty.colorize("Patch:", "bold")) 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) patch = highlight_diff(patch)
print(patch.decode("utf-8")) print(patch.decode("utf-8"))
print()
print(f"Total entries: {num_entries}", file=sys.stderr) print(f"Total entries: {num_entries}", file=sys.stderr)
if failed_entries: if failed_entries:
print( print(

View File

@@ -12,8 +12,7 @@ class PullRequestListCommand(osc.commandline_git.GitObsCommand):
parent = "PullRequestCommand" parent = "PullRequestCommand"
def init_arguments(self): def init_arguments(self):
self.add_argument_owner() self.add_argument_owner_repo(nargs="+")
self.add_argument_repo()
self.add_argument( self.add_argument(
"--state", "--state",
choices=["open", "closed", "all"], choices=["open", "closed", "all"],
@@ -26,11 +25,14 @@ class PullRequestListCommand(osc.commandline_git.GitObsCommand):
self.print_gitea_settings() 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) text = gitea_api.PullRequest.list_to_human_readable_string(data, sort=True)
if text: if text:
print(text) print(text)
print("", file=sys.stderr) print("", file=sys.stderr)
print(f"Total entries: {len(data)}", file=sys.stderr) print(f"Total entries: {total_entries}", file=sys.stderr)

View File

@@ -1,3 +1,6 @@
import subprocess
import sys
import osc.commandline_git import osc.commandline_git
@@ -13,8 +16,7 @@ class RepoCloneCommand(osc.commandline_git.GitObsCommand):
parent = "RepoCommand" parent = "RepoCommand"
def init_arguments(self): def init_arguments(self):
self.add_argument_owner() self.add_argument_owner_repo(nargs="+")
self.add_argument_repo()
self.add_argument( self.add_argument(
"-a", "-a",
@@ -45,15 +47,42 @@ class RepoCloneCommand(osc.commandline_git.GitObsCommand):
def run(self, args): def run(self, args):
from osc import gitea_api from osc import gitea_api
from osc.output import tty
self.print_gitea_settings() self.print_gitea_settings()
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( gitea_api.Repo.clone(
self.gitea_conn, self.gitea_conn,
args.owner, owner,
args.repo, repo,
directory=args.directory, directory=args.directory,
anonymous=args.anonymous, anonymous=args.anonymous,
add_remotes=True, add_remotes=True,
ssh_private_key_path=args.ssh_key or self.gitea_login.ssh_key, 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), 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)

View File

@@ -12,8 +12,7 @@ class RepoForkCommand(osc.commandline_git.GitObsCommand):
parent = "RepoCommand" parent = "RepoCommand"
def init_arguments(self): def init_arguments(self):
self.add_argument_owner() self.add_argument_owner_repo(nargs="+")
self.add_argument_repo()
self.add_argument_new_repo_name() self.add_argument_new_repo_name()
def run(self, args): def run(self, args):
@@ -22,15 +21,35 @@ class RepoForkCommand(osc.commandline_git.GitObsCommand):
self.print_gitea_settings() self.print_gitea_settings()
print(f"Forking git repo {args.owner}/{args.repo} ...", 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: try:
response = gitea_api.Fork.create(self.gitea_conn, args.owner, args.repo, new_repo_name=args.new_repo_name) response = gitea_api.Fork.create(self.gitea_conn, owner, repo, new_repo_name=args.new_repo_name)
repo = response.json() repo = response.json()
fork_owner = repo["owner"]["login"] fork_owner = repo["owner"]["login"]
fork_repo = repo["name"] fork_repo = repo["name"]
print(f" * Fork created: {fork_owner}/{fork_repo}", file=sys.stderr) print(f" * Fork created: {fork_owner}/{fork_repo}", file=sys.stderr)
num_entries += 1
except gitea_api.ForkExists as e: except gitea_api.ForkExists as e:
fork_owner = e.fork_owner fork_owner = e.fork_owner
fork_repo = e.fork_repo fork_repo = e.fork_repo
print(f" * Fork already exists: {fork_owner}/{fork_repo}", file=sys.stderr) 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) 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)

View File

@@ -56,8 +56,8 @@ class Fork:
return conn.request("POST", url, json_data=json_data) return conn.request("POST", url, json_data=json_data)
except GiteaException as e: except GiteaException as e:
# use ForkExists exception to parse fork_owner and fork_repo from the response # 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: if e.status == 409:
fork_exists_exception = ForkExists(e.response, owner, repo)
if exist_ok: if exist_ok:
from . import Repo from . import Repo
return Repo.get(conn, fork_exists_exception.fork_owner, fork_exists_exception.fork_repo) return Repo.get(conn, fork_exists_exception.fork_owner, fork_exists_exception.fork_repo)

View File

@@ -22,7 +22,7 @@ class PullRequest:
""" """
Split <owner>/<repo>#<number> into individual components and return them in a tuple. 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: if not match:
raise ValueError(f"Invalid pull request id: {pr_id}") raise ValueError(f"Invalid pull request id: {pr_id}")
return match.groups() return match.groups()

View File

@@ -1,6 +1,8 @@
import os import os
import re
import subprocess import subprocess
from typing import Optional from typing import Optional
from typing import Tuple
from .connection import Connection from .connection import Connection
from .connection import GiteaHTTPResponse from .connection import GiteaHTTPResponse
@@ -8,6 +10,16 @@ from .user import User
class Repo: 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 @classmethod
def get( def get(
cls, cls,