diff options
Diffstat (limited to 'internal/storage/git_cmd_adapter.go')
| -rw-r--r-- | internal/storage/git_cmd_adapter.go | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/internal/storage/git_cmd_adapter.go b/internal/storage/git_cmd_adapter.go index e27fa5f..2710cb1 100644 --- a/internal/storage/git_cmd_adapter.go +++ b/internal/storage/git_cmd_adapter.go @@ -1,6 +1,7 @@ package storage import ( + "compress/zlib" "context" "fmt" "io" @@ -36,31 +37,54 @@ func (g *GitCmdAdapter) Cleanup() { os.RemoveAll(g.tempDir) } -// GetObject gets a Git object using git cat-file +// GetObject gets a Git object using git cat-file consistently func (g *GitCmdAdapter) GetObject(ctx context.Context, repo, objectID string) ([]byte, error) { + log.Printf("GitCmdAdapter: Getting object %s from repo %s", objectID, repo) repoPath, err := g.ensureRepository(ctx, repo) if err != nil { + log.Printf("GitCmdAdapter: Failed to ensure repository %s: %v", repo, err) return nil, err } - // Get object type first + // Use git cat-file to get the raw object content consistently + // This works for both loose objects and pack files + contentCmd := exec.CommandContext(ctx, "git", "--git-dir", repoPath, "cat-file", "-p", objectID) + content, err := contentCmd.Output() + if err != nil { + log.Printf("GitCmdAdapter: git cat-file -p failed for %s: %v", objectID, err) + return nil, fmt.Errorf("git cat-file -p failed for %s: %w", objectID, err) + } + + // Get object type typeCmd := exec.CommandContext(ctx, "git", "--git-dir", repoPath, "cat-file", "-t", objectID) typeOutput, err := typeCmd.Output() if err != nil { + log.Printf("GitCmdAdapter: git cat-file -t failed for %s: %v", objectID, err) return nil, fmt.Errorf("git cat-file -t failed for %s: %w", objectID, err) } objType := strings.TrimSpace(string(typeOutput)) - // Get raw object content using type and objectID - contentCmd := exec.CommandContext(ctx, "git", "--git-dir", repoPath, "cat-file", objType, objectID) - content, err := contentCmd.Output() + // Format as Git internal object: "type size\0content" + header := fmt.Sprintf("%s %d\x00", objType, len(content)) + result := append([]byte(header), content...) + log.Printf("GitCmdAdapter: Successfully retrieved object %s, type %s, size %d", objectID, objType, len(result)) + return result, nil +} + +// decompressObject decompresses a zlib-compressed Git object +func (g *GitCmdAdapter) decompressObject(compressed []byte) ([]byte, error) { + reader, err := zlib.NewReader(strings.NewReader(string(compressed))) + if err != nil { + return nil, fmt.Errorf("failed to create zlib reader: %w", err) + } + defer reader.Close() + + decompressed, err := io.ReadAll(reader) if err != nil { - return nil, fmt.Errorf("git cat-file failed for %s: %w", objectID, err) + return nil, fmt.Errorf("failed to decompress object: %w", err) } - // Format as Git object: "type size\0content" - result := fmt.Sprintf("%s %d\x00", objType, len(content)) - return append([]byte(result), content...), nil + return decompressed, nil } // GetReachableObjects returns all objects reachable from the given commits |
