fix(gitea): tolerate binary file payloads (#2380)#2440
Conversation
Code Review by Qodo
Context used 1. get_file_content() decodes skipped binaries
|
PR Summary by QodoGitea provider: tolerate non-UTF-8 binary payloads in diffs and raw files WalkthroughsUser DescriptionSummaryFixes #2380. Gitea PRs that contain binary media changes can currently crash the provider when raw bytes are decoded as UTF-8. This affects both raw file fetches and This PR makes the Gitea provider tolerate those binary payloads:
TestingRan focused local verification against the changed Also ran syntax checks: The full pytest test module could not be run in this minimal environment without installing PR-Agent's full pinned dependency set; the added tests follow the existing AI Description• Decode Gitea PR .diff payloads with replacement to avoid UTF-8 decode crashes. • Skip non-UTF-8 raw file contents and return empty content with a warning. • Add regression tests covering both binary diff and binary raw file paths. Diagramgraph TD
A["PR-Agent (Gitea)" ] --> B["RepoApi" ] --> C{{"Gitea HTTP API"}} --> D[("Bytes payload")]
D --> E["Diff decode" ] --> F["Text diff parse" ]
D --> G["File decode" ] --> H["Empty content" ]
subgraph Legend
direction LR
_svc["Component" ] ~~~ _ext{{"External"}} ~~~ _db[("Data")]
end
High-Level AssessmentThe following are alternative approaches to this PR: 1. Detect binary via Content-Type/headers before decoding
2. Decode diffs as latin-1 (lossless byte mapping)
3. Pre-scan bytes and strip/skip binary hunks
Recommendation: The PR’s approach is the best tradeoff: it preserves provider stability with minimal, targeted changes. Using errors='replace' for .diff keeps the textual headers/context parseable, while skipping non-UTF-8 raw file content prevents crashes on binary assets. Header-based binary detection or binary-hunk filtering could be considered later if replacement characters materially affect downstream behavior, but they add complexity and rely on less reliable signals. File ChangesBug fix (1)
Tests (1)
|
This comment was marked as spam.
This comment was marked as spam.
2 similar comments
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
Addresses Qodo review on The-PR-Agent#2440: get_file_content returned '' on any UnicodeDecodeError, so legitimate non-UTF-8 text (e.g. UTF-16) was indistinguishable from an empty file and lost downstream. Decode via the shared decode_if_bytes fallback chain instead, which preserves such text and still tolerates binary payloads (filtered downstream by extension). Update tests to assert text preservation and non-crashing binary handling.
# Conflicts: # tests/unittest/test_gitea_provider.py
|
Finalized this based on Qodo's review — pushed two commits to the branch: 1. Addressed Qodo's finding (non-UTF-8 text lost). 2. Resolved the merge conflict with Verified locally: Thanks @raywcm for the fix — the binary-crash handling and the diff-replacement decoding were spot on. 🙌 |
| # Decode via the shared fallback chain (utf-8, then iso-8859-1/latin-1/ | ||
| # ascii/utf-16) so legitimate non-UTF-8 *text* (e.g. UTF-16) is preserved | ||
| # rather than dropped, while binary payloads no longer crash the provider. | ||
| # decode_if_bytes returns "" only if every encoding fails; binary files are | ||
| # filtered downstream by extension (should_skip_patch). | ||
| if hasattr(response, 'data'): | ||
| raw_data = response.data.read() | ||
| return raw_data.decode('utf-8') | ||
| return decode_if_bytes(raw_data) | ||
| elif isinstance(response, tuple): | ||
| raw_data = response[0].read() | ||
| return raw_data.decode('utf-8') | ||
| return decode_if_bytes(raw_data) |
There was a problem hiding this comment.
1. get_file_content() decodes skipped binaries 📎 Requirement gap ☼ Reliability
RepoApi.get_file_content() always retrieves raw file bytes and decodes them via decode_if_bytes() before applying patch_extension_skip_types-based skipping, violating the requirement to skip ignored/binary extensions prior to any raw content retrieval/decoding. Because decode_if_bytes will convert arbitrary binary payloads to full-length strings (latin-1/iso-8859-1) and GiteaProvider.__add_file_content eagerly fetches content for files that pass is_valid_file (which may not exclude .webp by default), large binary assets can be unnecessarily loaded, decoded, and stored, increasing overhead and risk of downstream mis-handling.
Agent Prompt
## Issue description
Ensure ignored/binary extensions (configured via `patch_extension_skip_types`, and/or other extension skip lists) are skipped *before* any raw-content API fetch and before `decode_if_bytes()` runs, so the Gitea provider does not eagerly retrieve, decode, and store large binary files (e.g., `.webp`) as full-length strings.
## Issue Context
The repo already has `should_skip_patch(filename)` driven by `get_settings().config.patch_extension_skip_types`, but the Gitea provider’s raw-content path currently calls the raw-file API and then decodes bytes via `decode_if_bytes()` without consulting this skip logic first (binary filtering is deferred “downstream”). In addition, `GiteaProvider.__add_file_content` fetches/stores content for every file that passes `is_valid_file`, and because `decode_if_bytes` falls back to latin-1/iso-8859-1 it will successfully decode arbitrary binary bytes into a non-empty, full-length Python string—so large binary assets not excluded by default extension lists (like `.webp`) can be unnecessarily loaded into memory.
## Fix Focus Areas
- pr_agent/git_providers/gitea_provider.py[105-124]
- pr_agent/git_providers/gitea_provider.py[924-964]
- pr_agent/algo/git_patch_processing.py[54-58]
- pr_agent/settings/language_extensions.toml[1-59]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
Code review by qodo was updated up to the latest commit 93687f2 |
Summary
Fixes #2380.
Gitea PRs that contain binary media changes can currently crash the provider when raw bytes are decoded as UTF-8. This affects both raw file fetches and
.diffretrieval before ignored binary extensions can be filtered out cleanly.This PR makes the Gitea provider tolerate those binary payloads:
Testing
Ran focused local verification against the changed
RepoApimethods with invalid UTF-8 bytes:Also ran syntax checks:
The full pytest test module could not be run in this minimal environment without installing PR-Agent's full pinned dependency set; the added tests follow the existing
RepoApimock style intests/unittest/test_gitea_provider.py.