Skip to content

Commit 8a305f0

Browse files
authored
Merge pull request openSUSE#1963 from dmach/git-obs-improve-meta
Improve handling meta in git-obs
2 parents 6b05fff + 07acc06 commit 8a305f0

File tree

6 files changed

+207
-66
lines changed

6 files changed

+207
-66
lines changed

osc/commands_git/meta_info.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import osc.commandline_git
2+
3+
4+
class MetaInfoCommand(osc.commandline_git.GitObsCommand):
5+
"""
6+
Resolve and print metadata about the current checkout
7+
"""
8+
9+
name = "info"
10+
parent = "MetaCommand"
11+
12+
def init_arguments(self):
13+
group = self.parser.add_mutually_exclusive_group()
14+
group.add_argument(
15+
"--type",
16+
action="store_true",
17+
help="Print type",
18+
)
19+
group.add_argument(
20+
"--apiurl",
21+
action="store_true",
22+
help="Print apiurl",
23+
)
24+
group.add_argument(
25+
"--project",
26+
action="store_true",
27+
help="Print project",
28+
)
29+
group.add_argument(
30+
"--package",
31+
action="store_true",
32+
help="Print package",
33+
)
34+
group.add_argument(
35+
"--branch",
36+
action="store_true",
37+
help="Print branch",
38+
)
39+
group.add_argument(
40+
"--commit",
41+
action="store_true",
42+
help="Print commit",
43+
)
44+
group.add_argument(
45+
"--remote",
46+
action="store_true",
47+
help="Print remote",
48+
)
49+
group.add_argument(
50+
"--remote-url",
51+
action="store_true",
52+
help="Print remote_url",
53+
)
54+
group.add_argument(
55+
"--export",
56+
action="store_true",
57+
help="Show json objects instead of human readable text",
58+
)
59+
60+
def run(self, args):
61+
from osc.git_scm.store import GitStore
62+
63+
store = GitStore(".")
64+
result = {
65+
"type": store.type,
66+
"apiurl": store.apiurl,
67+
"project": store.project,
68+
"package": store.package,
69+
"branch": store._git.current_branch,
70+
"commit": store._git.get_branch_head(),
71+
"remote": store._git.get_current_remote(),
72+
"remote_url": store._git.get_remote_url(),
73+
}
74+
if args.export:
75+
import json
76+
77+
print(json.dumps(result, indent=4))
78+
elif args.type:
79+
print(result["type"] or "")
80+
elif args.apiurl:
81+
print(result["apiurl"] or "")
82+
elif args.project:
83+
print(result["project"] or "")
84+
elif args.package:
85+
print(result["package"] or "")
86+
elif args.branch:
87+
print(result["branch"] or "")
88+
elif args.commit:
89+
print(result["commit"] or "")
90+
elif args.remote:
91+
print(result["remote"] or "")
92+
elif args.remote_url:
93+
print(result["remote_url"] or "")
94+
else:
95+
from osc.output import KeyValueTable
96+
97+
table = KeyValueTable(min_key_length=10)
98+
for key, value in result.items():
99+
table.add(key, value)
100+
print(str(table))

osc/commands_git/meta_pull.py

Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,64 +13,17 @@ def init_arguments(self):
1313
pass
1414

1515
def run(self, args):
16-
from osc import gitea_api
17-
from osc.git_scm.configuration import Configuration
18-
from osc.git_scm.manifest import Manifest
19-
from osc.git_scm.store import LocalGitStore
16+
from osc.git_scm.store import GitStore
2017
from osc.output import KeyValueTable
2118

2219
self.print_gitea_settings()
2320

24-
store = LocalGitStore(".")
25-
26-
apiurl = None
27-
project = None
28-
29-
# read apiurl and project from _manifest that lives in <owner>/_ObsPrj, matching <branch>
30-
# XXX: when the target branch doesn't exist, file from the default branch is returned
31-
if store.is_package:
32-
try:
33-
owner, _ = store._git.get_owner_repo()
34-
repo = "_ObsPrj"
35-
branch = store._git.current_branch
36-
37-
url = self.gitea_conn.makeurl("repos", owner, repo, "raw", "_manifest", query={"ref": branch})
38-
response = self.gitea_conn.request("GET", url)
39-
if response.data:
40-
manifest = Manifest.from_string(response.data.decode("utf-8"))
41-
if manifest.obs_apiurl:
42-
apiurl = manifest.obs_apiurl
43-
if manifest.obs_project:
44-
project = manifest.obs_project
45-
except gitea_api.GiteaException as e:
46-
if e.status != 404:
47-
raise
48-
49-
# read apiurl from the global configuration in obs/configuration. branch
50-
if not apiurl:
51-
try:
52-
url = self.gitea_conn.makeurl("repos", "obs", "configuration", "raw", "configuration.yaml", query={"ref": "main"})
53-
response = self.gitea_conn.request("GET", url)
54-
if response.data:
55-
configuration = Configuration.from_string(response.data.decode("utf-8"))
56-
if configuration.obs_apiurl:
57-
apiurl = configuration.obs_apiurl
58-
except gitea_api.GiteaException as e:
59-
if e.status != 404:
60-
raise
61-
62-
if apiurl:
63-
store.apiurl = apiurl
64-
65-
if project:
66-
store.project = project
67-
21+
store = GitStore(".", check=False)
6822
branch = store._git.current_branch
69-
meta = store._read_meta(branch=branch).dict()
70-
meta.pop("header", None)
23+
changed = store.pull(self.gitea_conn)
7124

7225
table = KeyValueTable(min_key_length=10)
7326
table.add("Branch", branch, color="bold")
74-
for key, value in meta.items():
27+
for key, value in changed.items():
7528
table.add(key, value)
7629
print(str(table))

osc/commands_git/repo_clone.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ class RepoCloneCommand(osc.commandline_git.GitObsCommand):
1818
def init_arguments(self):
1919
self.add_argument_owner_repo(nargs="+")
2020

21+
self.add_argument(
22+
"-b",
23+
"--branch",
24+
help="Checkout the specified branch",
25+
)
26+
2127
self.add_argument(
2228
"-a",
2329
"--anonymous",
@@ -46,7 +52,7 @@ def init_arguments(self):
4652

4753
def run(self, args):
4854
from osc import gitea_api
49-
55+
from osc.git_scm.store import GitStore
5056
from osc.output import tty
5157

5258
self.print_gitea_settings()
@@ -59,16 +65,19 @@ def run(self, args):
5965
for owner, repo in args.owner_repo:
6066
print(f"Cloning git repo {owner}/{repo} ...", file=sys.stderr)
6167
try:
62-
gitea_api.Repo.clone(
68+
repo_path = gitea_api.Repo.clone(
6369
self.gitea_conn,
6470
owner,
6571
repo,
72+
branch=args.branch,
6673
directory=args.directory,
6774
use_http=args.anonymous or self.gitea_login.git_uses_http,
6875
add_remotes=True,
6976
ssh_private_key_path=args.ssh_key or self.gitea_login.ssh_key,
7077
ssh_strict_host_key_checking=not(args.no_ssh_strict_host_key_checking),
7178
)
79+
store = GitStore(repo_path, check=False)
80+
store.pull(self.gitea_conn)
7281
num_entries += 1
7382
except gitea_api.GiteaException as e:
7483
if e.status == 404:

osc/git_scm/store.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pathlib import Path
66
import typing
77
import urllib.parse
8+
from typing import Dict
89
from typing import List
910
from typing import Optional
1011
from typing import Tuple
@@ -16,7 +17,8 @@
1617

1718

1819
if typing.TYPE_CHECKING:
19-
from .core import Repo
20+
from ..core import Repo
21+
from ..obs_api import GiteaConnection
2022

2123

2224
class Header(BaseModel):
@@ -539,6 +541,10 @@ def _resolve_meta(self, field_name: str, *, allow_none: bool = False):
539541
with open(path, "r", encoding="utf-8") as f:
540542
result = f.read().strip() or None
541543

544+
# package = directory name; package must be part of a project checkout
545+
if result is None and self.is_package and self.project_store is not None and field_name == "package":
546+
result = os.path.basename(self.topdir)
547+
542548
# package = repo name from the current remote url
543549
if result is None and self.is_package and field_name == "package":
544550
remote_url = self._git.get_remote_url()
@@ -570,3 +576,69 @@ def package(self) -> Optional[str]:
570576
@property
571577
def scmurl(self) -> Optional[str]:
572578
return self._git.get_remote_url()
579+
580+
def pull(self, gitea_conn) -> Dict[str, Optional[str]]:
581+
from osc.git_scm.configuration import Configuration
582+
from osc.git_scm.manifest import Manifest
583+
from .. import gitea_api
584+
585+
apiurl = None
586+
project = None
587+
588+
# read apiurl and project from _manifest that lives in <owner>/_ObsPrj, matching <branch>
589+
# XXX: when the target branch doesn't exist, file from the default branch is returned
590+
if self.is_package:
591+
owner, _ = self._git.get_owner_repo()
592+
repo = "_ObsPrj"
593+
branch = self._git.current_branch
594+
595+
try:
596+
url = gitea_conn.makeurl("repos", owner, repo, "raw", "_manifest", query={"ref": branch})
597+
response = gitea_conn.request("GET", url)
598+
if response.data:
599+
manifest = Manifest.from_string(response.data.decode("utf-8"))
600+
if manifest.obs_apiurl:
601+
apiurl = manifest.obs_apiurl
602+
if manifest.obs_project:
603+
project = manifest.obs_project
604+
except gitea_api.GiteaException as e:
605+
if e.status != 404:
606+
raise
607+
608+
if not project:
609+
try:
610+
url = gitea_conn.makeurl("repos", owner, repo, "raw", "project.build", query={"ref": branch})
611+
response = gitea_conn.request("GET", url)
612+
if response.data:
613+
value = response.data.decode("utf-8").strip()
614+
if value:
615+
project = value
616+
except gitea_api.GiteaException as e:
617+
if e.status != 404:
618+
raise
619+
620+
# read apiurl from the global configuration in obs/configuration, 'main' branch, 'configuration.yaml' file
621+
if not apiurl:
622+
try:
623+
url = gitea_conn.makeurl("repos", "obs", "configuration", "raw", "configuration.yaml", query={"ref": "main"})
624+
response = gitea_conn.request("GET", url)
625+
if response.data:
626+
configuration = Configuration.from_string(response.data.decode("utf-8"))
627+
if configuration.obs_apiurl:
628+
apiurl = configuration.obs_apiurl
629+
except gitea_api.GiteaException as e:
630+
if e.status != 404:
631+
raise
632+
633+
if apiurl:
634+
self.set_apiurl(apiurl)
635+
636+
if project:
637+
self.set_project(project)
638+
639+
# return the values we've set
640+
result = {
641+
"apiurl": apiurl,
642+
"project": project,
643+
}
644+
return result

osc/gitea_api/git.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from typing import Optional
99
from typing import Tuple
1010

11+
from . import exceptions
12+
1113

1214
class SshParseResult(urllib.parse.ParseResult):
1315
"""
@@ -154,7 +156,10 @@ def get_branch_head(self, branch: Optional[str] = None) -> str:
154156
if not branch:
155157
branch = self.current_branch
156158

157-
return self._run_git(["rev-parse", f"refs/heads/{branch}"])
159+
try:
160+
return self._run_git(["rev-parse", f"refs/heads/{branch}"], mute_stderr=True)
161+
except subprocess.CalledProcessError:
162+
raise exceptions.GitObsRuntimeError(f"Unable to retrieve HEAD from branch '{branch}'. Does the branch exist?")
158163

159164
def branch_exists(self, branch: str) -> bool:
160165
try:
@@ -262,6 +267,8 @@ def fetch(self, name: Optional[str] = None):
262267

263268
def get_owner_repo(self, remote: Optional[str] = None) -> Tuple[str, str]:
264269
remote_url = self.get_remote_url(name=remote)
270+
if not remote_url:
271+
raise exceptions.GitObsRuntimeError("Couldn't determine owner and repo due to a missing remote")
265272
return self.get_owner_repo_from_url(remote_url)
266273

267274
@staticmethod

0 commit comments

Comments
 (0)