Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/code-storage-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,23 @@ for _, commit := range commits.Commits {
}
```

### Get an applicable commit diff

```go
diff, err := repo.GetCommitDiff(context.Background(), storage.GetCommitDiffOptions{
SHA: "head-commit-sha",
BaseSHA: "base-commit-sha",
GitApplyCompatible: true,
})
if err != nil {
log.Fatal(err)
}
```

`GitApplyCompatible` generates raw diffs for use with `git apply`. When no files are filtered and every
changed file has non-empty `Raw`, concatenate each `diff.Files[i].Raw` in response order to produce
a patch for the exact base tree.

TTL fields use `time.Duration` values (for example `time.Hour`).

### Hydrate a repo without an API request
Expand Down
3 changes: 3 additions & 0 deletions packages/code-storage-go/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,9 @@ func (r *Repo) GetCommitDiff(ctx context.Context, options GetCommitDiffOptions)
if strings.TrimSpace(options.BaseSHA) != "" {
params.Set("baseSha", options.BaseSHA)
}
if options.GitApplyCompatible {
params.Set("gitApplyCompatible", "true")
}
for _, path := range options.Paths {
if strings.TrimSpace(path) != "" {
params.Add("path", path)
Expand Down
4 changes: 2 additions & 2 deletions packages/code-storage-go/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ func TestCommitDiffQuery(t *testing.T) {
t.Fatalf("unexpected path: %s", r.URL.Path)
}
q := r.URL.Query()
if q.Get("sha") != "abc" || q.Get("baseSha") != "base" {
if q.Get("sha") != "abc" || q.Get("baseSha") != "base" || q.Get("gitApplyCompatible") != "true" {
t.Fatalf("unexpected query: %s", r.URL.RawQuery)
}
w.Header().Set("Content-Type", "application/json")
Expand All @@ -1197,7 +1197,7 @@ func TestCommitDiffQuery(t *testing.T) {
}
repo := &Repo{ID: "repo", DefaultBranch: "main", client: client}

result, err := repo.GetCommitDiff(nil, GetCommitDiffOptions{SHA: "abc", BaseSHA: "base"})
result, err := repo.GetCommitDiff(nil, GetCommitDiffOptions{SHA: "abc", BaseSHA: "base", GitApplyCompatible: true})
if err != nil {
t.Fatalf("commit diff error: %v", err)
}
Expand Down
11 changes: 6 additions & 5 deletions packages/code-storage-go/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (
// Options configure the Git storage client.
type Options struct {
Name string
Key string // required unless Token is set
Token string // pre-minted JWT, used verbatim if set
Key string // required unless Token is set
Token string // pre-minted JWT, used verbatim if set
APIBaseURL string
StorageBaseURL string
APIVersion int
Expand Down Expand Up @@ -866,9 +866,10 @@ type GetBranchDiffResult struct {
// GetCommitDiffOptions configures commit diff.
type GetCommitDiffOptions struct {
InvocationOptions
SHA string
BaseSHA string
Paths []string
SHA string
BaseSHA string
GitApplyCompatible bool // Generate raw diffs that can be applied to the base tree.
Paths []string
}

// GetCommitDiffResult describes commit diff.
Expand Down
2 changes: 1 addition & 1 deletion packages/code-storage-go/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package storage

const (
PackageName = "code-storage-go-sdk"
PackageVersion = "1.16.0"
PackageVersion = "1.16.1"
)

func userAgent() string {
Expand Down
3 changes: 3 additions & 0 deletions packages/code-storage-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ print(branch_diff["files"])
# Get commit diff
commit_diff = await repo.get_commit_diff(
sha="abc123...",
base_sha="def456...", # optional base commit
git_apply_compatible=True, # generate raw diffs for use with git apply
)
print(commit_diff["stats"])
print(commit_diff["files"])
Expand Down Expand Up @@ -971,6 +973,7 @@ class Repo:
*,
sha: str,
base_sha: Optional[str] = None,
git_apply_compatible: Optional[bool] = None,
paths: Optional[List[str]] = None,
ttl: Optional[int] = None,
) -> GetCommitDiffResult: ...
Expand Down
5 changes: 5 additions & 0 deletions packages/code-storage-python/pierre_storage/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,7 @@ async def get_commit_diff(
*,
sha: str,
base_sha: Optional[str] = None,
git_apply_compatible: Optional[bool] = None,
paths: Optional[list[str]] = None,
ttl: Optional[int] = None,
) -> GetCommitDiffResult:
Expand All @@ -1901,6 +1902,8 @@ async def get_commit_diff(
Args:
sha: Commit SHA
base_sha: Optional base commit SHA to compare against
git_apply_compatible: Generate raw diffs that can be applied to the base tree. Defaults to
False.
paths: Optional paths to filter the diff to specific files
ttl: Token TTL in seconds

Expand All @@ -1913,6 +1916,8 @@ async def get_commit_diff(
params: list[tuple[str, str]] = [("sha", sha)]
if base_sha:
params.append(("baseSha", base_sha))
if git_apply_compatible is not None:
params.append(("gitApplyCompatible", str(git_apply_compatible).lower()))
if paths:
for p in paths:
params.append(("path", p))
Expand Down
1 change: 1 addition & 0 deletions packages/code-storage-python/pierre_storage/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,7 @@ async def get_commit_diff(
*,
sha: str,
base_sha: Optional[str] = None,
git_apply_compatible: Optional[bool] = None,
paths: Optional[list[str]] = None,
ttl: Optional[int] = None,
) -> GetCommitDiffResult:
Expand Down
2 changes: 1 addition & 1 deletion packages/code-storage-python/pierre_storage/version.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Version information for Pierre Storage SDK."""

PACKAGE_NAME = "code-storage-py-sdk"
PACKAGE_VERSION = "1.16.1"
PACKAGE_VERSION = "1.16.2"


def get_user_agent() -> str:
Expand Down
2 changes: 1 addition & 1 deletion packages/code-storage-python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pierre-storage"
version = "1.16.1"
version = "1.16.2"
description = "Pierre Git Storage SDK for Python"
readme = "README.md"
license = "MIT"
Expand Down
5 changes: 4 additions & 1 deletion packages/code-storage-python/tests/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3055,7 +3055,9 @@ async def test_get_commit_diff_with_base_sha(self, git_storage_options: dict) ->
mock_client.return_value.__aenter__.return_value.get = mock_get

repo = await storage.create_repo(id="test-repo")
result = await repo.get_commit_diff(sha="abc123", base_sha="def456")
result = await repo.get_commit_diff(
sha="abc123", base_sha="def456", git_apply_compatible=True
)

assert result is not None
assert result["stats"]["additions"] == 5
Expand All @@ -3068,6 +3070,7 @@ async def test_get_commit_diff_with_base_sha(self, git_storage_options: dict) ->
params = parse_qs(parsed.query)
assert params["sha"] == ["abc123"]
assert params["baseSha"] == ["def456"]
assert params["gitApplyCompatible"] == ["true"]


class TestRepoUpstreamOperations:
Expand Down
2 changes: 1 addition & 1 deletion packages/code-storage-python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/code-storage-typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ console.log(branchDiff.files);
// Get commit diff
const commitDiff = await repo.getCommitDiff({
sha: 'abc123...',
baseSha: 'def456...', // optional base commit
gitApplyCompatible: true, // generate raw diffs for use with git apply
});
console.log(commitDiff.stats);
console.log(commitDiff.files);
Expand Down Expand Up @@ -934,6 +936,7 @@ interface GetBranchDiffOptions {
interface GetCommitDiffOptions {
sha: string;
baseSha?: string;
gitApplyCompatible?: boolean; // default false; generate raw diffs for use with git apply
paths?: string[];
ttl?: number;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/code-storage-typescript/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pierre/storage",
"version": "1.15.0",
"version": "1.15.1",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please can we keep the versions in lock-step across the language packages?

I matched the versions in ecebcf7 but it has since drifted, e.g., e79e3a4

(Might want tooling / agent skill to enforce this going forward.)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yes interesting i think that's good idea

maybe we can keep it as one root version file? in that way we can enforce prevention of version drifting

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea. i added a task for this to the backlog

"description": "Pierre Git Storage SDK",
"repository": {
"type": "git",
Expand Down
3 changes: 3 additions & 0 deletions packages/code-storage-typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,9 @@ class RepoImpl implements Repo {
if (options.baseSha) {
params.baseSha = options.baseSha;
}
if (typeof options.gitApplyCompatible === 'boolean') {
params.gitApplyCompatible = String(options.gitApplyCompatible);
}
if (options.paths && options.paths.length > 0) {
params.path = options.paths;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/code-storage-typescript/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,8 @@ export interface GetBranchDiffResult {
export interface GetCommitDiffOptions extends GitStorageInvocationOptions {
sha: string;
baseSha?: string;
/** Generate raw diffs that can be applied to the exact base tree. Defaults to false. */
gitApplyCompatible?: boolean;
/** Optional paths to filter the diff to specific files */
paths?: string[];
}
Expand Down
32 changes: 32 additions & 0 deletions packages/code-storage-typescript/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2938,6 +2938,38 @@ describe('GitStorage', () => {
});
});

describe('Repo getCommitDiff', () => {
it('forwards gitApplyCompatible to the API params', async () => {
const store = new GitStorage({ name: 'v0', key });
const repo = await store.createRepo({ id: 'repo-commit-diff' });

mockFetch.mockImplementationOnce((url) => {
const requestUrl = new URL(url as string);
expect(requestUrl.searchParams.get('sha')).toBe('head');
expect(requestUrl.searchParams.get('baseSha')).toBe('base');
expect(requestUrl.searchParams.get('gitApplyCompatible')).toBe('true');

return Promise.resolve({
ok: true,
status: 200,
statusText: 'OK',
json: async () => ({
sha: 'head',
stats: { files: 0, additions: 0, deletions: 0, changes: 0 },
files: [],
filtered_files: [],
}),
} as any);
});

await repo.getCommitDiff({
sha: 'head',
baseSha: 'base',
gitApplyCompatible: true,
});
});
});

describe('Repo restoreCommit', () => {
it('should post metadata to the restore endpoint and return the response', async () => {
const store = new GitStorage({ name: 'v0', key });
Expand Down
9 changes: 7 additions & 2 deletions skills/code-storage/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -476,11 +476,16 @@ Errors: `400` missing/blank `sha`, `404` commit not found.
## GET /repos/diff — Get Commit Diff

```bash
curl "$CODE_STORAGE_BASE_URL/repos/diff?sha=COMMIT_SHA&baseSha=OPTIONAL_BASE&path=src/foo.go" \
curl "$CODE_STORAGE_BASE_URL/repos/diff?sha=COMMIT_SHA&baseSha=OPTIONAL_BASE&gitApplyCompatible=true&path=src/foo.go" \
-H "Authorization: Bearer $CODE_STORAGE_TOKEN"
```

Params: `sha`(required), `baseSha`, `path` (repeatable)
Params: `sha` (required), `baseSha`, `gitApplyCompatible` (boolean), `path` (repeatable).
The default suppresses changes in the amount of whitespace for review readability. Set
`gitApplyCompatible=true` when the raw output will be passed to `git apply`; it includes whitespace
changes consistently in file discovery, raw diffs, and stats. When `filtered_files` is empty and
every changed file has non-empty `raw`, concatenating `files[].raw` in response order produces a
patch for the exact base tree.
Response: `{ "sha", "stats", "files": [...], "filtered_files": [...] }`
Large files (>500KB) or binary files appear in `filtered_files` without diff content.

Expand Down
Loading