Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5d5352d

Browse files
committedFeb 13, 2025··
enhance: add ability to get revision ID when opening file in a workspace
Signed-off-by: Donnie Adams <[email protected]>
1 parent 834896a commit 5d5352d

File tree

5 files changed

+178
-87
lines changed

5 files changed

+178
-87
lines changed
 

‎go.mod

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ module github.com/gptscript-ai/go-gptscript
33
go 1.23.0
44

55
require (
6-
github.com/getkin/kin-openapi v0.124.0
7-
github.com/stretchr/testify v1.8.4
6+
github.com/getkin/kin-openapi v0.129.0
7+
github.com/stretchr/testify v1.10.0
88
)
99

1010
require (
1111
github.com/davecgh/go-spew v1.1.1 // indirect
12-
github.com/go-openapi/jsonpointer v0.20.2 // indirect
13-
github.com/go-openapi/swag v0.22.8 // indirect
14-
github.com/invopop/yaml v0.2.0 // indirect
12+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
13+
github.com/go-openapi/swag v0.23.0 // indirect
1514
github.com/josharian/intern v1.0.0 // indirect
16-
github.com/mailru/easyjson v0.7.7 // indirect
15+
github.com/mailru/easyjson v0.9.0 // indirect
1716
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
17+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect
18+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect
1819
github.com/perimeterx/marshmallow v1.1.5 // indirect
1920
github.com/pmezard/go-difflib v1.0.0 // indirect
2021
gopkg.in/yaml.v3 v3.0.1 // indirect

‎go.sum

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,39 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
4-
github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
5-
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
6-
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
7-
github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
8-
github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
3+
github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30=
4+
github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI=
5+
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
6+
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
7+
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
8+
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
99
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
1010
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
11-
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
12-
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
1311
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
1412
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1513
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
1614
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
1715
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1816
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
19-
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
20-
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
17+
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
18+
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
2119
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
2220
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
21+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU=
22+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8=
23+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc=
24+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
2325
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
2426
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
2527
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2628
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2729
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
2830
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
29-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
30-
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
31+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
32+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
3133
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
3234
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
3335
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3436
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
3537
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
36-
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3738
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3839
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

‎gptscript_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestMain(m *testing.M) {
3030
panic(fmt.Sprintf("error creating gptscript: %s", err))
3131
}
3232

33-
g, err = NewGPTScript(GlobalOptions{OpenAIAPIKey: os.Getenv("OPENAI_API_KEY")})
33+
g, err = NewGPTScript(GlobalOptions{OpenAIAPIKey: os.Getenv("OPENAI_API_KEY"), WorkspaceTool: "/Users/thedadams/code/workspace-provider"})
3434
if err != nil {
3535
gFirst.Close()
3636
panic(fmt.Sprintf("error creating gptscript: %s", err))

‎workspace.go

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ func (g *GPTScript) RemoveAll(ctx context.Context, opts ...RemoveAllOptions) err
147147
}
148148

149149
type WriteFileInWorkspaceOptions struct {
150-
WorkspaceID string
151-
CreateRevision *bool
152-
LatestRevision string
150+
WorkspaceID string
151+
CreateRevision *bool
152+
LatestRevisionID string
153153
}
154154

155155
func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, filePath string, contents []byte, opts ...WriteFileInWorkspaceOptions) error {
@@ -161,8 +161,8 @@ func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, filePath string, c
161161
if o.CreateRevision != nil {
162162
opt.CreateRevision = o.CreateRevision
163163
}
164-
if o.LatestRevision != "" {
165-
opt.LatestRevision = o.LatestRevision
164+
if o.LatestRevisionID != "" {
165+
opt.LatestRevisionID = o.LatestRevisionID
166166
}
167167
}
168168

@@ -171,13 +171,13 @@ func (g *GPTScript) WriteFileInWorkspace(ctx context.Context, filePath string, c
171171
}
172172

173173
_, err := g.runBasicCommand(ctx, "workspaces/write-file", map[string]any{
174-
"id": opt.WorkspaceID,
175-
"contents": base64.StdEncoding.EncodeToString(contents),
176-
"filePath": filePath,
177-
"createRevision": opt.CreateRevision,
178-
"latestRevision": opt.LatestRevision,
179-
"workspaceTool": g.globalOpts.WorkspaceTool,
180-
"env": g.globalOpts.Env,
174+
"id": opt.WorkspaceID,
175+
"contents": base64.StdEncoding.EncodeToString(contents),
176+
"filePath": filePath,
177+
"createRevision": opt.CreateRevision,
178+
"latestRevisionID": opt.LatestRevisionID,
179+
"workspaceTool": g.globalOpts.WorkspaceTool,
180+
"env": g.globalOpts.Env,
181181
})
182182

183183
return parsePossibleConflictInWorkspaceError(err)
@@ -214,26 +214,34 @@ func (g *GPTScript) DeleteFileInWorkspace(ctx context.Context, filePath string,
214214
}
215215

216216
type ReadFileInWorkspaceOptions struct {
217-
WorkspaceID string
217+
WorkspaceID string
218+
WithLatestRevisionID bool
218219
}
219220

220-
func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, filePath string, opts ...ReadFileInWorkspaceOptions) ([]byte, error) {
221+
type ReadFileInWorkspaceResponse struct {
222+
Content []byte `json:"content"`
223+
RevisionID string `json:"revisionID"`
224+
}
225+
226+
func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, filePath string, opts ...ReadFileInWorkspaceOptions) (*ReadFileInWorkspaceResponse, error) {
221227
var opt ReadFileInWorkspaceOptions
222228
for _, o := range opts {
223229
if o.WorkspaceID != "" {
224230
opt.WorkspaceID = o.WorkspaceID
225231
}
232+
opt.WithLatestRevisionID = opt.WithLatestRevisionID || o.WithLatestRevisionID
226233
}
227234

228235
if opt.WorkspaceID == "" {
229236
opt.WorkspaceID = os.Getenv("GPTSCRIPT_WORKSPACE_ID")
230237
}
231238

232239
out, err := g.runBasicCommand(ctx, "workspaces/read-file", map[string]any{
233-
"id": opt.WorkspaceID,
234-
"filePath": filePath,
235-
"workspaceTool": g.globalOpts.WorkspaceTool,
236-
"env": g.globalOpts.Env,
240+
"id": opt.WorkspaceID,
241+
"filePath": filePath,
242+
"withLatestRevisionID": opt.WithLatestRevisionID,
243+
"workspaceTool": g.globalOpts.WorkspaceTool,
244+
"env": g.globalOpts.Env,
237245
})
238246
if err != nil {
239247
if strings.HasSuffix(err.Error(), fmt.Sprintf("not found: %s/%s", opt.WorkspaceID, filePath)) {
@@ -242,7 +250,13 @@ func (g *GPTScript) ReadFileInWorkspace(ctx context.Context, filePath string, op
242250
return nil, err
243251
}
244252

245-
return base64.StdEncoding.DecodeString(out)
253+
var resp ReadFileInWorkspaceResponse
254+
err = json.Unmarshal([]byte(out), &resp)
255+
if err != nil {
256+
return nil, err
257+
}
258+
259+
return &resp, nil
246260
}
247261

248262
type FileInfo struct {
@@ -251,10 +265,12 @@ type FileInfo struct {
251265
Size int64
252266
ModTime time.Time
253267
MimeType string
268+
RevisionID string
254269
}
255270

256271
type StatFileInWorkspaceOptions struct {
257-
WorkspaceID string
272+
WorkspaceID string
273+
WithLatestRevisionID bool
258274
}
259275

260276
func (g *GPTScript) StatFileInWorkspace(ctx context.Context, filePath string, opts ...StatFileInWorkspaceOptions) (FileInfo, error) {
@@ -263,17 +279,19 @@ func (g *GPTScript) StatFileInWorkspace(ctx context.Context, filePath string, op
263279
if o.WorkspaceID != "" {
264280
opt.WorkspaceID = o.WorkspaceID
265281
}
282+
opt.WithLatestRevisionID = opt.WithLatestRevisionID || o.WithLatestRevisionID
266283
}
267284

268285
if opt.WorkspaceID == "" {
269286
opt.WorkspaceID = os.Getenv("GPTSCRIPT_WORKSPACE_ID")
270287
}
271288

272289
out, err := g.runBasicCommand(ctx, "workspaces/stat-file", map[string]any{
273-
"id": opt.WorkspaceID,
274-
"filePath": filePath,
275-
"workspaceTool": g.globalOpts.WorkspaceTool,
276-
"env": g.globalOpts.Env,
290+
"id": opt.WorkspaceID,
291+
"filePath": filePath,
292+
"withLatestRevisionID": opt.WithLatestRevisionID,
293+
"workspaceTool": g.globalOpts.WorkspaceTool,
294+
"env": g.globalOpts.Env,
277295
})
278296
if err != nil {
279297
if strings.HasSuffix(err.Error(), fmt.Sprintf("not found: %s/%s", opt.WorkspaceID, filePath)) {
@@ -291,16 +309,11 @@ func (g *GPTScript) StatFileInWorkspace(ctx context.Context, filePath string, op
291309
return info, nil
292310
}
293311

294-
type RevisionInfo struct {
295-
FileInfo
296-
RevisionID string
297-
}
298-
299312
type ListRevisionsForFileInWorkspaceOptions struct {
300313
WorkspaceID string
301314
}
302315

303-
func (g *GPTScript) ListRevisionsForFileInWorkspace(ctx context.Context, filePath string, opts ...ListRevisionsForFileInWorkspaceOptions) ([]RevisionInfo, error) {
316+
func (g *GPTScript) ListRevisionsForFileInWorkspace(ctx context.Context, filePath string, opts ...ListRevisionsForFileInWorkspaceOptions) ([]FileInfo, error) {
304317
var opt ListRevisionsForFileInWorkspaceOptions
305318
for _, o := range opts {
306319
if o.WorkspaceID != "" {
@@ -325,7 +338,7 @@ func (g *GPTScript) ListRevisionsForFileInWorkspace(ctx context.Context, filePat
325338
return nil, err
326339
}
327340

328-
var info []RevisionInfo
341+
var info []FileInfo
329342
err = json.Unmarshal([]byte(out), &info)
330343
if err != nil {
331344
return nil, err

‎workspace_test.go

Lines changed: 112 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ func TestCreateAndDeleteWorkspaceFromWorkspace(t *testing.T) {
3333
t.Fatalf("Error creating workspace: %v", err)
3434
}
3535

36+
t.Cleanup(func() {
37+
err = g.DeleteWorkspace(context.Background(), id)
38+
if err != nil {
39+
t.Errorf("Error deleting workspace: %v", err)
40+
}
41+
})
42+
3643
err = g.WriteFileInWorkspace(context.Background(), "file.txt", []byte("hello world"), WriteFileInWorkspaceOptions{
3744
WorkspaceID: id,
3845
})
@@ -45,26 +52,21 @@ func TestCreateAndDeleteWorkspaceFromWorkspace(t *testing.T) {
4552
t.Errorf("Error creating workspace from workspace: %v", err)
4653
}
4754

48-
data, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
55+
content, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
4956
WorkspaceID: newID,
5057
})
5158
if err != nil {
52-
t.Errorf("Error reading file: %v", err)
59+
t.Fatalf("Error reading file: %v", err)
5360
}
5461

55-
if !bytes.Equal(data, []byte("hello world")) {
56-
t.Errorf("Unexpected content: %s", data)
62+
if !bytes.Equal(content.Content, []byte("hello world")) {
63+
t.Errorf("Unexpected content: %s", content.Content)
5764
}
5865

5966
err = g.DeleteWorkspace(context.Background(), id)
6067
if err != nil {
6168
t.Errorf("Error deleting workspace: %v", err)
6269
}
63-
64-
err = g.DeleteWorkspace(context.Background(), newID)
65-
if err != nil {
66-
t.Errorf("Error deleting new workspace: %v", err)
67-
}
6870
}
6971

7072
func TestWriteReadAndDeleteFileFromWorkspace(t *testing.T) {
@@ -90,8 +92,26 @@ func TestWriteReadAndDeleteFileFromWorkspace(t *testing.T) {
9092
t.Errorf("Error reading file: %v", err)
9193
}
9294

93-
if !bytes.Equal(content, []byte("test")) {
94-
t.Errorf("Unexpected content: %s", content)
95+
if !bytes.Equal(content.Content, []byte("test")) {
96+
t.Errorf("Unexpected content: %s", content.Content)
97+
}
98+
99+
if content.RevisionID != "" {
100+
t.Errorf("Unexpected file revision ID when not requesting it: %s", content.RevisionID)
101+
}
102+
103+
// Read the file and request the revision ID
104+
content, err = g.ReadFileInWorkspace(context.Background(), "test.txt", ReadFileInWorkspaceOptions{WorkspaceID: id, WithLatestRevisionID: true})
105+
if err != nil {
106+
t.Errorf("Error reading file: %v", err)
107+
}
108+
109+
if !bytes.Equal(content.Content, []byte("test")) {
110+
t.Errorf("Unexpected content: %s", content.Content)
111+
}
112+
113+
if content.RevisionID == "" {
114+
t.Errorf("Expected file revision ID when requesting it: %s", content.RevisionID)
95115
}
96116

97117
// Stat the file to ensure it exists
@@ -120,6 +140,24 @@ func TestWriteReadAndDeleteFileFromWorkspace(t *testing.T) {
120140
t.Errorf("Unexpected file mime type: %s", fileInfo.MimeType)
121141
}
122142

143+
if fileInfo.RevisionID != "" {
144+
t.Errorf("Unexpected file revision ID when not requesting it: %s", fileInfo.RevisionID)
145+
}
146+
147+
// Stat file and request the revision ID
148+
fileInfo, err = g.StatFileInWorkspace(context.Background(), "test.txt", StatFileInWorkspaceOptions{WorkspaceID: id, WithLatestRevisionID: true})
149+
if err != nil {
150+
t.Errorf("Error statting file: %v", err)
151+
}
152+
153+
if fileInfo.WorkspaceID != id {
154+
t.Errorf("Unexpected file workspace ID: %v", fileInfo.WorkspaceID)
155+
}
156+
157+
if fileInfo.RevisionID == "" {
158+
t.Errorf("Expected file revision ID when requesting it: %s", fileInfo.RevisionID)
159+
}
160+
123161
// Ensure we get the error we expect when trying to read a non-existent file
124162
_, err = g.ReadFileInWorkspace(context.Background(), "test1.txt", ReadFileInWorkspaceOptions{WorkspaceID: id})
125163
if nf := (*NotFoundInWorkspaceError)(nil); !errors.As(err, &nf) {
@@ -322,7 +360,7 @@ func TestConflictsForFileInWorkspace(t *testing.T) {
322360

323361
ce := (*ConflictInWorkspaceError)(nil)
324362
// Writing a new file with a non-zero latest revision should fail
325-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test0"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: "1"})
363+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test0"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: "1"})
326364
if err == nil || !errors.As(err, &ce) {
327365
t.Errorf("Expected error writing file with non-zero latest revision: %v", err)
328366
}
@@ -347,7 +385,7 @@ func TestConflictsForFileInWorkspace(t *testing.T) {
347385
}
348386

349387
// Writing to the file with the latest revision should succeed
350-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test2"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: revisions[0].RevisionID})
388+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test2"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: revisions[0].RevisionID})
351389
if err != nil {
352390
t.Fatalf("Error creating file: %v", err)
353391
}
@@ -362,7 +400,7 @@ func TestConflictsForFileInWorkspace(t *testing.T) {
362400
}
363401

364402
// Writing to the file with the same revision should fail
365-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test3"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: revisions[0].RevisionID})
403+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test3"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: revisions[0].RevisionID})
366404
if err == nil || !errors.As(err, &ce) {
367405
t.Errorf("Expected error writing file with same revision: %v", err)
368406
}
@@ -382,7 +420,7 @@ func TestConflictsForFileInWorkspace(t *testing.T) {
382420
}
383421

384422
// Ensure we can write a new file after deleting the latest revision
385-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test4"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: revisions[0].RevisionID})
423+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test4"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: revisions[0].RevisionID})
386424
if err != nil {
387425
t.Fatalf("Error creating file: %v", err)
388426
}
@@ -501,15 +539,15 @@ func TestCreateAndDeleteWorkspaceFromWorkspaceS3(t *testing.T) {
501539
t.Errorf("Error creating workspace from workspace: %v", err)
502540
}
503541

504-
data, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
542+
content, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
505543
WorkspaceID: newID,
506544
})
507545
if err != nil {
508546
t.Errorf("Error reading file: %v", err)
509547
}
510548

511-
if !bytes.Equal(data, []byte("hello world")) {
512-
t.Errorf("Unexpected content: %s", data)
549+
if !bytes.Equal(content.Content, []byte("hello world")) {
550+
t.Errorf("Unexpected content: %s", content.Content)
513551
}
514552

515553
err = g.DeleteWorkspace(context.Background(), id)
@@ -545,15 +583,15 @@ func TestCreateAndDeleteDirectoryWorkspaceFromWorkspaceS3(t *testing.T) {
545583
t.Errorf("Error creating workspace from workspace: %v", err)
546584
}
547585

548-
data, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
586+
content, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
549587
WorkspaceID: newID,
550588
})
551589
if err != nil {
552590
t.Errorf("Error reading file: %v", err)
553591
}
554592

555-
if !bytes.Equal(data, []byte("hello world")) {
556-
t.Errorf("Unexpected content: %s", data)
593+
if !bytes.Equal(content.Content, []byte("hello world")) {
594+
t.Errorf("Unexpected content: %s", content.Content)
557595
}
558596

559597
err = g.DeleteWorkspace(context.Background(), id)
@@ -577,6 +615,13 @@ func TestCreateAndDeleteS3WorkspaceFromWorkspaceDirectory(t *testing.T) {
577615
t.Fatalf("Error creating workspace: %v", err)
578616
}
579617

618+
t.Cleanup(func() {
619+
err = g.DeleteWorkspace(context.Background(), id)
620+
if err != nil {
621+
t.Errorf("Error deleting workspace: %v", err)
622+
}
623+
})
624+
580625
err = g.WriteFileInWorkspace(context.Background(), "file.txt", []byte("hello world"), WriteFileInWorkspaceOptions{
581626
WorkspaceID: id,
582627
})
@@ -589,26 +634,21 @@ func TestCreateAndDeleteS3WorkspaceFromWorkspaceDirectory(t *testing.T) {
589634
t.Errorf("Error creating workspace from workspace: %v", err)
590635
}
591636

592-
data, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
637+
content, err := g.ReadFileInWorkspace(context.Background(), "file.txt", ReadFileInWorkspaceOptions{
593638
WorkspaceID: newID,
594639
})
595640
if err != nil {
596-
t.Errorf("Error reading file: %v", err)
641+
t.Fatalf("Error reading file: %v", err)
597642
}
598643

599-
if !bytes.Equal(data, []byte("hello world")) {
600-
t.Errorf("Unexpected content: %s", data)
644+
if !bytes.Equal(content.Content, []byte("hello world")) {
645+
t.Errorf("Unexpected content: %s", content.Content)
601646
}
602647

603648
err = g.DeleteWorkspace(context.Background(), id)
604649
if err != nil {
605650
t.Errorf("Error deleting workspace: %v", err)
606651
}
607-
608-
err = g.DeleteWorkspace(context.Background(), newID)
609-
if err != nil {
610-
t.Errorf("Error deleting new workspace: %v", err)
611-
}
612652
}
613653

614654
func TestWriteReadAndDeleteFileFromWorkspaceS3(t *testing.T) {
@@ -638,8 +678,26 @@ func TestWriteReadAndDeleteFileFromWorkspaceS3(t *testing.T) {
638678
t.Errorf("Error reading file: %v", err)
639679
}
640680

641-
if !bytes.Equal(content, []byte("test")) {
642-
t.Errorf("Unexpected content: %s", content)
681+
if !bytes.Equal(content.Content, []byte("test")) {
682+
t.Errorf("Unexpected content: %s", content.Content)
683+
}
684+
685+
if content.RevisionID != "" {
686+
t.Errorf("Unexpected file revision ID when not requesting it: %s", content.RevisionID)
687+
}
688+
689+
// Read the file and request the revision ID
690+
content, err = g.ReadFileInWorkspace(context.Background(), "test.txt", ReadFileInWorkspaceOptions{WorkspaceID: id, WithLatestRevisionID: true})
691+
if err != nil {
692+
t.Errorf("Error reading file: %v", err)
693+
}
694+
695+
if !bytes.Equal(content.Content, []byte("test")) {
696+
t.Errorf("Unexpected content: %s", content.Content)
697+
}
698+
699+
if content.RevisionID == "" {
700+
t.Errorf("Expected file revision ID when requesting it: %s", content.RevisionID)
643701
}
644702

645703
// Stat the file to ensure it exists
@@ -668,6 +726,24 @@ func TestWriteReadAndDeleteFileFromWorkspaceS3(t *testing.T) {
668726
t.Errorf("Unexpected file mime type: %s", fileInfo.MimeType)
669727
}
670728

729+
if fileInfo.RevisionID != "" {
730+
t.Errorf("Unexpected file revision ID when not requesting it: %s", fileInfo.RevisionID)
731+
}
732+
733+
// Stat file and request the revision ID
734+
fileInfo, err = g.StatFileInWorkspace(context.Background(), "test.txt", StatFileInWorkspaceOptions{WorkspaceID: id, WithLatestRevisionID: true})
735+
if err != nil {
736+
t.Errorf("Error statting file: %v", err)
737+
}
738+
739+
if fileInfo.WorkspaceID != id {
740+
t.Errorf("Unexpected file workspace ID: %v", fileInfo.WorkspaceID)
741+
}
742+
743+
if fileInfo.RevisionID == "" {
744+
t.Errorf("Expected file revision ID when requesting it: %s", fileInfo.RevisionID)
745+
}
746+
671747
// Ensure we get the error we expect when trying to read a non-existent file
672748
_, err = g.ReadFileInWorkspace(context.Background(), "test1.txt", ReadFileInWorkspaceOptions{WorkspaceID: id})
673749
if nf := (*NotFoundInWorkspaceError)(nil); !errors.As(err, &nf) {
@@ -795,7 +871,7 @@ func TestConflictsForFileInWorkspaceS3(t *testing.T) {
795871

796872
ce := (*ConflictInWorkspaceError)(nil)
797873
// Writing a new file with a non-zero latest revision should fail
798-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test0"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: "1"})
874+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test0"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: "1"})
799875
if err == nil || !errors.As(err, &ce) {
800876
t.Errorf("Expected error writing file with non-zero latest revision: %v", err)
801877
}
@@ -820,7 +896,7 @@ func TestConflictsForFileInWorkspaceS3(t *testing.T) {
820896
}
821897

822898
// Writing to the file with the latest revision should succeed
823-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test2"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: revisions[0].RevisionID})
899+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test2"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: revisions[0].RevisionID})
824900
if err != nil {
825901
t.Fatalf("Error creating file: %v", err)
826902
}
@@ -835,7 +911,7 @@ func TestConflictsForFileInWorkspaceS3(t *testing.T) {
835911
}
836912

837913
// Writing to the file with the same revision should fail
838-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test3"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: revisions[0].RevisionID})
914+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test3"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: revisions[0].RevisionID})
839915
if err == nil || !errors.As(err, &ce) {
840916
t.Errorf("Expected error writing file with same revision: %v", err)
841917
}
@@ -855,7 +931,7 @@ func TestConflictsForFileInWorkspaceS3(t *testing.T) {
855931
}
856932

857933
// Ensure we can write a new file after deleting the latest revision
858-
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test4"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevision: revisions[0].RevisionID})
934+
err = g.WriteFileInWorkspace(context.Background(), "test.txt", []byte("test4"), WriteFileInWorkspaceOptions{WorkspaceID: id, LatestRevisionID: revisions[0].RevisionID})
859935
if err != nil {
860936
t.Fatalf("Error creating file: %v", err)
861937
}

0 commit comments

Comments
 (0)
Please sign in to comment.