Skip to content

Commit 8cd6f20

Browse files
committed
fix(gitlab[_warn_truncation]) Qualify truncation warning when client filters active
why: _warn_truncation shows "Showing N of M" where M comes from the x-total header (unfiltered server count). When --skip-group/--language/--topics are active, M includes excluded projects, misleading users about how many repos they actually care about. The GitLab API provides no server-side equivalent for skip_groups; client-side filtering is unavoidable. what: - Add has_client_filters kwarg to _warn_truncation - When True: warn "N total on server (note: server total includes filtered)" - When False: existing "Showing N of M" message unchanged - Pass has_client_filters=bool(options.skip_groups or options.language or options.topics) from both _fetch_search and _paginate_repos - Remove TODO comment - Add test_gitlab_truncation_warning_with_client_filter in test_gitlab.py
1 parent 9be48eb commit 8cd6f20

2 files changed

Lines changed: 73 additions & 15 deletions

File tree

src/vcspull/_internal/remotes/gitlab.py

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,15 @@ def _fetch_search(self, options: ImportOptions) -> t.Iterator[RemoteRepo]:
241241
page += 1
242242

243243
# Warn if results were truncated by --limit
244-
self._warn_truncation(count, options.limit, total_available, last_x_next_page)
244+
self._warn_truncation(
245+
count,
246+
options.limit,
247+
total_available,
248+
last_x_next_page,
249+
has_client_filters=bool(
250+
options.skip_groups or options.language or options.topics
251+
),
252+
)
245253

246254
def _paginate_repos(
247255
self,
@@ -325,43 +333,63 @@ def _paginate_repos(
325333
page += 1
326334

327335
# Warn if results were truncated by --limit
328-
self._warn_truncation(count, options.limit, total_available, last_x_next_page)
336+
self._warn_truncation(
337+
count,
338+
options.limit,
339+
total_available,
340+
last_x_next_page,
341+
has_client_filters=bool(
342+
options.skip_groups or options.language or options.topics
343+
),
344+
)
329345

330346
def _warn_truncation(
331347
self,
332348
count: int,
333349
limit: int,
334350
total_available: int | None,
335351
x_next_page: str | None,
352+
*,
353+
has_client_filters: bool = False,
336354
) -> None:
337355
"""Warn if results were truncated by the --limit option.
338356
339357
Parameters
340358
----------
341359
count : int
342-
Number of repositories actually returned
360+
Number of repositories returned after client-side filtering
343361
limit : int
344362
The configured limit
345363
total_available : int | None
346-
Value of x-total header (None if absent)
364+
Value of x-total header (None if absent). Reflects the unfiltered
365+
server-side total; may overstate the count of repos matching
366+
client-side filters (skip_groups, language, topics).
347367
x_next_page : str | None
348368
Value of x-next-page header (None if absent/empty)
369+
has_client_filters : bool
370+
True when any client-side filter (skip_groups, language, topics) is
371+
active; used to qualify the warning message so the server-side
372+
total is not presented as the filtered total.
349373
"""
350374
if count < limit:
351375
return
352376

353-
# TODO: total_available comes from the x-total header which reflects
354-
# the unfiltered server-side project count. After client-side
355-
# filter_repo filtering (e.g. skip_groups, language, topics), count
356-
# may be less than total_available for reasons unrelated to --limit.
357-
# A more accurate message would require tracking pre-filter vs
358-
# post-filter counts separately.
359377
if total_available is not None and total_available > count:
360-
log.warning(
361-
"Showing %d of %d repositories (use --limit 0 to fetch all)",
362-
count,
363-
total_available,
364-
)
378+
if has_client_filters:
379+
log.warning(
380+
"Showing %d repositories; %d total on server "
381+
"(note: server total includes projects excluded by "
382+
"--skip-group / --language / --topics; "
383+
"use --limit 0 to fetch all matching your filters)",
384+
count,
385+
total_available,
386+
)
387+
else:
388+
log.warning(
389+
"Showing %d of %d repositories (use --limit 0 to fetch all)",
390+
count,
391+
total_available,
392+
)
365393
elif x_next_page is not None:
366394
log.warning(
367395
"Showing %d repositories; more are available "

tests/_internal/remotes/test_gitlab.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,36 @@ def urlopen_side_effect(
858858
assert "--limit" not in caplog.text.lower()
859859

860860

861+
def test_gitlab_truncation_warning_with_client_filter(
862+
monkeypatch: pytest.MonkeyPatch,
863+
caplog: pytest.LogCaptureFixture,
864+
) -> None:
865+
"""Truncation warning with client filters active uses qualified message."""
866+
import logging
867+
868+
caplog.set_level(logging.WARNING)
869+
870+
repos = [_make_gitlab_project(i) for i in range(5)]
871+
headers = {"x-total": "5", "x-next-page": "2"}
872+
873+
def urlopen_side_effect(
874+
request: urllib.request.Request,
875+
timeout: int | None = None,
876+
) -> MockHTTPResponse:
877+
return MockHTTPResponse(json.dumps(repos).encode(), headers, 200)
878+
879+
# Mock urlopen: return all 5 repos with x-total=5 to trigger truncation path
880+
monkeypatch.setattr("urllib.request.urlopen", urlopen_side_effect)
881+
882+
importer = GitLabImporter()
883+
options = ImportOptions(
884+
mode=ImportMode.USER, target="user", limit=2, skip_groups=["bots"]
885+
)
886+
list(importer.fetch_repos(options))
887+
888+
assert "server total includes projects excluded" in caplog.text
889+
890+
861891
# ---------------------------------------------------------------------------
862892
# with_shared URL parameter tests
863893
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)