Skip to content

Commit 1a2e5c5

Browse files
committed
filestore: Allow customising the destination path
1 parent 9bcb112 commit 1a2e5c5

File tree

2 files changed

+84
-4
lines changed

2 files changed

+84
-4
lines changed

pkg/filestore/filestore.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,15 @@ func (store FileStore) NewUpload(ctx context.Context, info handler.FileInfo) (ha
5252
if info.ID == "" {
5353
info.ID = uid.Uid()
5454
}
55+
56+
// The .info file's location can directly be deduced from the upload ID
57+
infoPath := store.infoPath(info.ID)
58+
// The binary file's location might be modified by the pre-create hook.
5559
binPath := store.binPath(info.ID)
60+
if info.Storage != nil && info.Storage["Path"] != "" {
61+
binPath = filepath.Join(store.Path, info.Storage["Path"])
62+
}
63+
5664
info.Storage = map[string]string{
5765
"Type": "filestore",
5866
"Path": binPath,
@@ -65,7 +73,7 @@ func (store FileStore) NewUpload(ctx context.Context, info handler.FileInfo) (ha
6573

6674
upload := &fileUpload{
6775
info: info,
68-
infoPath: store.infoPath(info.ID),
76+
infoPath: infoPath,
6977
binPath: binPath,
7078
}
7179

@@ -78,21 +86,25 @@ func (store FileStore) NewUpload(ctx context.Context, info handler.FileInfo) (ha
7886
}
7987

8088
func (store FileStore) GetUpload(ctx context.Context, id string) (handler.Upload, error) {
81-
info := handler.FileInfo{}
82-
data, err := os.ReadFile(store.infoPath(id))
89+
infoPath := store.infoPath(id)
90+
data, err := os.ReadFile(infoPath)
8391
if err != nil {
8492
if os.IsNotExist(err) {
8593
// Interpret os.ErrNotExist as 404 Not Found
8694
err = handler.ErrNotFound
8795
}
8896
return nil, err
8997
}
98+
var info handler.FileInfo
9099
if err := json.Unmarshal(data, &info); err != nil {
91100
return nil, err
92101
}
93102

103+
// TODO: Test whether this works with uploads created from previous tusd versions.
94104
binPath := store.binPath(id)
95-
infoPath := store.infoPath(id)
105+
if info.Storage != nil && info.Storage["Path"] != "" {
106+
binPath = info.Storage["Path"]
107+
}
96108
stat, err := os.Stat(binPath)
97109
if err != nil {
98110
if os.IsNotExist(err) {

pkg/filestore/filestore_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,71 @@ func TestDeclareLength(t *testing.T) {
245245
a.EqualValues(100, updatedInfo.Size)
246246
a.Equal(false, updatedInfo.SizeIsDeferred)
247247
}
248+
249+
// TestCustomPath tests whether the upload's destination can be customized.
250+
func TestCustomPath(t *testing.T) {
251+
a := assert.New(t)
252+
253+
tmp, err := os.MkdirTemp("", "tusd-filestore-")
254+
a.NoError(err)
255+
256+
store := FileStore{tmp}
257+
ctx := context.Background()
258+
259+
// Create new upload
260+
upload, err := store.NewUpload(ctx, handler.FileInfo{
261+
ID: "folder1/info",
262+
Size: 42,
263+
Storage: map[string]string{
264+
"Path": "./folder2/bin",
265+
},
266+
})
267+
a.NoError(err)
268+
a.NotEqual(nil, upload)
269+
270+
// Check info without writing
271+
info, err := upload.GetInfo(ctx)
272+
a.NoError(err)
273+
a.EqualValues(42, info.Size)
274+
a.EqualValues(0, info.Offset)
275+
a.Equal(2, len(info.Storage))
276+
a.Equal("filestore", info.Storage["Type"])
277+
a.Equal(filepath.Join(tmp, "./folder2/bin"), info.Storage["Path"])
278+
279+
// Write data to upload
280+
bytesWritten, err := upload.WriteChunk(ctx, 0, strings.NewReader("hello world"))
281+
a.NoError(err)
282+
a.EqualValues(len("hello world"), bytesWritten)
283+
284+
// Check new offset
285+
info, err = upload.GetInfo(ctx)
286+
a.NoError(err)
287+
a.EqualValues(42, info.Size)
288+
a.EqualValues(11, info.Offset)
289+
290+
// Read content
291+
reader, err := upload.GetReader(ctx)
292+
a.NoError(err)
293+
294+
content, err := io.ReadAll(reader)
295+
a.NoError(err)
296+
a.Equal("hello world", string(content))
297+
reader.(io.Closer).Close()
298+
299+
// Check that the output file and info file exist on disk
300+
statInfo, err := os.Stat(filepath.Join(tmp, "folder2/bin"))
301+
a.NoError(err)
302+
a.True(statInfo.Mode().IsRegular())
303+
a.EqualValues(11, statInfo.Size())
304+
statInfo, err = os.Stat(filepath.Join(tmp, "folder1/info.info"))
305+
a.NoError(err)
306+
a.True(statInfo.Mode().IsRegular())
307+
308+
// Terminate upload
309+
a.NoError(store.AsTerminatableUpload(upload).Terminate(ctx))
310+
311+
// Test if upload is deleted
312+
upload, err = store.GetUpload(ctx, info.ID)
313+
a.Equal(nil, upload)
314+
a.Equal(handler.ErrNotFound, err)
315+
}

0 commit comments

Comments
 (0)