Scope mobile Search by repository
CI / lint (pull_request) Successful in 1m37s
CI / build-release (pull_request) Successful in 5s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-14 03:11:40 +00:00
1 parent 7636e30482
commit ec86bf55a8
15 files changed
+234 -25

No files matched your search

+4
View File
@@ -469,6 +469,7 @@ async def global_search(
page: int = 1,
kind: str = "all",
state: str = "all",
repository: str | None = None,
) -> dict:
"""Search accessible issues and pulls concurrently with balanced pagination."""
item_types = ("issues", "pulls") if kind == "all" else (
@@ -480,6 +481,9 @@ async def global_search(
"q": query, "type": item_type, "state": state,
"limit": stream_limit, "page": page,
}
if repository:
owner, repo = repository.split("/", 1)
params.update({"owner": owner, "repo": repo})
response = await _get_client().get(
"/api/v1/repos/issues/search",
headers=_auth(),
+19 -3
View File
@@ -1006,15 +1006,17 @@ def _share_target_login_redirect(request: Request) -> str:
search_values = request.query_params.getlist("search")
preview_values = request.query_params.getlist("preview")
if search_values or preview_values:
allowed = {"search", "preview", "search_kind", "search_state"}
allowed = {"search", "preview", "search_kind", "search_state", "search_repository"}
kind_values = request.query_params.getlist("search_kind")
state_values = request.query_params.getlist("search_state")
repository_values = request.query_params.getlist("search_repository")
if (
set(request.query_params.keys()) - allowed
or len(search_values) != 1
or len(preview_values) != 1
or len(kind_values) > 1
or len(state_values) > 1
or len(repository_values) > 1
or len(search_values[0]) > 200
or len(preview_values[0]) > 200
or not re.fullmatch(
@@ -1030,6 +1032,10 @@ def _share_target_login_redirect(request: Request) -> str:
continuation_values.append(("search_kind", kind_values[0]))
if state_values and state_values[0] in {"all", "open", "closed"}:
continuation_values.append(("search_state", state_values[0]))
if repository_values and re.fullmatch(
r"[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+", repository_values[0]
):
continuation_values.append(("search_repository", repository_values[0]))
continuation = urlencode(continuation_values)
return f"login?{urlencode({'continue': f'./?{continuation}'})}"
limits = {"title": 200, "text": 8000, "url": 2048}
@@ -2723,13 +2729,20 @@ async def global_search(
page: int = Query(default=1, ge=1, le=100),
kind: Literal["all", "issue", "pull"] = Query(default="all"),
state: Literal["all", "open", "closed"] = Query(default="all"),
repository: str | None = Query(
default=None, pattern=r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$", max_length=161
),
) -> JSONResponse:
query = q.strip()
if len(query) < 2:
raise HTTPException(status_code=422, detail="Search query must contain at least 2 characters")
try:
arguments = (query, limit, page, kind, state)
operation = gitea_proxy.global_search(*arguments, repository) if repository else (
gitea_proxy.global_search(*arguments)
)
result = await asyncio.wait_for(
gitea_proxy.global_search(query, limit, page, kind, state),
operation,
timeout=GLOBAL_SEARCH_TIMEOUT_SECONDS,
)
except Exception:
@@ -2738,7 +2751,10 @@ async def global_search(
status_code=503,
headers={"Retry-After": "1"},
)
return JSONResponse({"query": query, "scope": {"kind": kind, "state": state}, **result})
scope = {"kind": kind, "state": state}
if repository:
scope["repository"] = repository
return JSONResponse({"query": query, "scope": scope, **result})
@app.get("/api/v1/repos/{owner}/{repo}/issues/{number}/preview")