1010from typing import TYPE_CHECKING , Final , Iterable
1111from urllib .parse import urlparse
1212
13- import httpx
14- from starlette .status import HTTP_200_OK , HTTP_401_UNAUTHORIZED , HTTP_403_FORBIDDEN , HTTP_404_NOT_FOUND
13+
1514
1615from gitingest .utils .compat_func import removesuffix
1716from gitingest .utils .exceptions import InvalidGitHubTokenError
@@ -112,7 +111,7 @@ async def ensure_git_installed() -> None:
112111
113112
114113async def check_repo_exists (url : str , token : str | None = None ) -> bool :
115- """Check whether a remote Git repository is reachable.
114+ """Check whether a remote Git repository is reachable using git ls-remote .
116115
117116 Parameters
118117 ----------
@@ -126,35 +125,30 @@ async def check_repo_exists(url: str, token: str | None = None) -> bool:
126125 bool
127126 ``True`` if the repository exists, ``False`` otherwise.
128127
129- Raises
130- ------
131- RuntimeError
132- If the host returns an unrecognised status code.
133-
134128 """
135- headers = {}
136-
129+ cmd = ["git" , "ls-remote" ]
130+
131+ # Add authentication header if token is provided for GitHub repositories
137132 if token and is_github_host (url ):
138- host , owner , repo = _parse_github_url (url )
139- # Public GitHub vs. GitHub Enterprise
140- base_api = "https://api.github.com" if host == "github.com" else f"https://{ host } /api/v3"
141- url = f"{ base_api } /repos/{ owner } /{ repo } "
142- headers ["Authorization" ] = f"Bearer { token } "
143-
144- async with httpx .AsyncClient (follow_redirects = True ) as client :
145- try :
146- response = await client .head (url , headers = headers )
147- except httpx .RequestError :
148- return False
149-
150- status_code = response .status_code
151-
152- if status_code == HTTP_200_OK :
153- return True
154- if status_code in {HTTP_401_UNAUTHORIZED , HTTP_403_FORBIDDEN , HTTP_404_NOT_FOUND }:
133+ cmd .extend (["-c" , create_git_auth_header (token , url = url )])
134+
135+ cmd .extend (["--exit-code" , url , "HEAD" ])
136+
137+ try :
138+ proc = await asyncio .create_subprocess_exec (
139+ * cmd ,
140+ stdout = asyncio .subprocess .PIPE ,
141+ stderr = asyncio .subprocess .PIPE ,
142+ )
143+ stdout , stderr = await proc .communicate ()
144+
145+ # git ls-remote returns 0 if repository exists and is accessible
146+ # returns non-zero if repository doesn't exist or is not accessible
147+ return proc .returncode == 0
148+
149+ except Exception :
150+ # If any exception occurs (e.g., git not available), assume repo doesn't exist
155151 return False
156- msg = f"Unexpected HTTP status { status_code } for { url } "
157- raise RuntimeError (msg )
158152
159153
160154def _parse_github_url (url : str ) -> tuple [str , str , str ]:
0 commit comments