• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SwissDataScienceCenter / renku-data-services / 19267889034

11 Nov 2025 01:56PM UTC coverage: 86.481% (+0.1%) from 86.352%
19267889034

Pull #1095

github

web-flow
Merge 1da835101 into ffc3f8457
Pull Request #1095: Feat: Improve repository response

265 of 298 new or added lines in 7 files covered. (88.93%)

4 existing lines in 3 files now uncovered.

23022 of 26621 relevant lines covered (86.48%)

1.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.68
/components/renku_data_services/repositories/git_url.py
1
"""An url referring to a git repository."""
2

3
from __future__ import annotations
2✔
4

5
from dataclasses import dataclass
2✔
6
from enum import StrEnum
2✔
7
from urllib.parse import ParseResult, urlparse
2✔
8

9
import httpx
2✔
10

11
from renku_data_services.app_config import logging
2✔
12

13
logger = logging.getLogger(__file__)
2✔
14

15

16
class GitUrlError(StrEnum):
2✔
17
    """Possible errors for testing an url string."""
18

19
    no_url_scheme = "no_url_scheme"
2✔
20
    no_url_host = "no_url_host"
2✔
21
    no_git_repo = "no_git_repo"
2✔
22
    no_url_path = "no_url_path"
2✔
23
    invalid_url_scheme = "invalid_url_scheme"
2✔
24

25

26
@dataclass(frozen=True, eq=True, kw_only=True)
2✔
27
class GitUrl:
2✔
28
    """A url referring to a git repository."""
29

30
    parsed_url: ParseResult
2✔
31

32
    @classmethod
2✔
33
    def parse(cls, url: str) -> GitUrlError | GitUrl:
2✔
34
        """Parse a string into a GitUrl."""
35
        return cls.from_parsed(urlparse(url))
2✔
36

37
    @classmethod
2✔
38
    def from_parsed(cls, url: ParseResult) -> GitUrlError | GitUrl:
2✔
39
        """Tests a parsed url if it is a valid GitUrl."""
40

41
        if url.scheme == "":
2✔
42
            return GitUrlError.no_url_scheme
2✔
43
        if url.scheme not in ["http", "https"]:
1✔
44
            return GitUrlError.invalid_url_scheme
1✔
45
        if url.netloc == "":
1✔
46
            return GitUrlError.no_url_host
1✔
47
        # An url without a path is not referring to a repository
48
        if url.path == "":
1✔
49
            return GitUrlError.no_url_path
1✔
50

51
        # fix trailing slashes
52
        if url.path.endswith("/"):
1✔
NEW
53
            url = url._replace(path=url.path[:-1])
×
54

55
        return GitUrl(parsed_url=url)
1✔
56

57
    @classmethod
2✔
58
    def unsafe(cls, url: str) -> GitUrl:
2✔
59
        """Parses the url and raises errors."""
60
        match cls.parse(url):
1✔
61
            case GitUrl() as gu:
1✔
62
                return gu
1✔
NEW
63
            case GitUrlError() as err:
×
NEW
64
                raise Exception(f"Invalid git url ({err}): {url}")
×
65

66
    def render(self) -> str:
2✔
67
        """Return the url as a string."""
68
        return self.parsed_url.geturl()
1✔
69

70
    async def check_http_git_repository(self, client: httpx.AsyncClient) -> GitUrlError | None:
2✔
71
        """Whether this url is a http/https url to a git repository."""
72
        service_url = self.render() + "/info/refs?service=git-upload-pack"
1✔
73
        try:
1✔
74
            async with client.stream("GET", service_url) as r:
1✔
75
                if r.status_code == 200:
1✔
76
                    return None
1✔
77
                else:
78
                    return GitUrlError.no_git_repo
1✔
NEW
79
        except httpx.TransportError as err:
×
NEW
80
            logger.debug(f"Error accessing url for git repo check ({err}): {self}")
×
NEW
81
            return GitUrlError.no_git_repo
×
82

83
    def __str__(self) -> str:
2✔
84
        return self.render()
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc