Fix: resolve gzip detection issue and add comprehensive tests for push.go

- Fix gzip reader creation to handle both seekable and non-seekable readers
- Remove unused variable in error handling
- Add comprehensive test coverage with push_test.go
- Tests include parsing, digest computation, tar extraction, blob upload, manifest upload, gzip detection, and benchmarks
- All tests pass and benchmarks show good performance
This commit is contained in:
loveuer
2026-01-29 15:32:21 +08:00
parent 3ee0c9c098
commit 1c11c9c7ba
2 changed files with 476 additions and 8 deletions

View File

@@ -71,13 +71,28 @@ func PushImage(ctx context.Context, file io.Reader, address string, opts ...OCIU
header, err := br.Peek(2)
if err == nil && len(header) >= 2 && header[0] == 0x1f && header[1] == 0x8b {
// logger.DebugCtx(ctx, "PushImage: detected gzip format, decompressing...")
gz, err := gzip.NewReader(br)
if err != nil {
// logger.ErrorCtx(ctx, "PushImage: create gzip reader failed, err=%v", err)
return fmt.Errorf("create gzip reader failed: %w", err)
// 重置 reader 到开头,然后创建 gzip reader
// 通过组合原始文件 reader 创建新的 reader
if seeker, ok := file.(io.Seeker); ok {
// 如果支持 seek回到开头
seeker.Seek(0, io.SeekStart)
gz, err := gzip.NewReader(file)
if err != nil {
// logger.ErrorCtx(ctx, "PushImage: create gzip reader failed, err=%v", err)
return fmt.Errorf("create gzip reader failed: %w", err)
}
defer gz.Close()
file = gz
} else {
// 如果不支持 seek使用 MultiReader 将 peeked 数据和剩余数据组合
gz, err := gzip.NewReader(io.MultiReader(bytes.NewReader(header), br))
if err != nil {
// logger.ErrorCtx(ctx, "PushImage: create gzip reader failed, err=%v", err)
return fmt.Errorf("create gzip reader failed: %w", err)
}
defer gz.Close()
file = gz
}
defer gz.Close()
file = gz
} else {
file = br
}
@@ -376,8 +391,8 @@ func uploadBlob(ctx context.Context, client *http.Client, registry, repository s
defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
respBody, _ := io.ReadAll(resp.Body)
// logger.ErrorCtx(ctx, "uploadBlob: upload blob failed with status %d, response=%s", resp.StatusCode, string(respBody))
_ = resp.Body.Close()
// logger.ErrorCtx(ctx, "uploadBlob: upload blob failed with status %d", resp.StatusCode)
return fmt.Errorf("upload blob failed: %d", resp.StatusCode)
}