Truncate files on Write
parent
edc451f9c6
commit
0158f7e1ed
|
@ -10,18 +10,19 @@ import (
|
|||
|
||||
const pasteFileMode = 0644
|
||||
|
||||
// ReadWriteSeekCloser implements reading, writing, seeking, and closing
|
||||
type ReadWriteSeekCloser interface {
|
||||
// TruncatableFile implements reading, writing, seeking, truncation, and closing
|
||||
type TruncatableFile interface {
|
||||
Truncate(size int64) error
|
||||
io.ReadWriteSeeker
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// Paster holds a single paste from the system
|
||||
// Implements io.ReadWriteCloser
|
||||
// Implements TruncatableFile
|
||||
type Paster struct {
|
||||
Paste repository.Paste
|
||||
pasteDir string
|
||||
file ReadWriteSeekCloser
|
||||
file TruncatableFile
|
||||
}
|
||||
|
||||
func (p *Paster) getPath() string {
|
||||
|
@ -56,11 +57,6 @@ func (p *Paster) prepareAndDo(buffer []byte, action func([]byte) (int, error)) (
|
|||
}
|
||||
}
|
||||
|
||||
_, err := p.file.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return action(buffer)
|
||||
}
|
||||
|
||||
|
@ -76,6 +72,16 @@ func (p *Paster) Read(buffer []byte) (int, error) {
|
|||
func (p *Paster) Write(contents []byte) (int, error) {
|
||||
// Wrap in closure to handle the nil file case
|
||||
return p.prepareAndDo(contents, func(buffer []byte) (int, error) {
|
||||
// Start writing at the beginning.
|
||||
_, err := p.file.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
err = p.file.Truncate(0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return p.file.Write(buffer)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -26,6 +26,12 @@ func (file *MockFile) Write(buffer []byte) (int, error) {
|
|||
return args.Int(0), args.Error(1)
|
||||
}
|
||||
|
||||
func (file *MockFile) Truncate(size int64) error {
|
||||
args := file.Called(size)
|
||||
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (file *MockFile) Seek(offset int64, whence int) (int64, error) {
|
||||
args := file.Called(offset, whence)
|
||||
|
||||
|
@ -64,10 +70,10 @@ func TestRead(t *testing.T) {
|
|||
buffer[i] = byte(char)
|
||||
}
|
||||
}).Once()
|
||||
// Ensure we seek to the start of the file
|
||||
mockFile.On("Seek", int64(0), 0).Return(int64(0), nil).Once()
|
||||
mockFile.AssertNotCalled(t, "Seek")
|
||||
mockFile.AssertNotCalled(t, "Close")
|
||||
mockFile.AssertNotCalled(t, "Write")
|
||||
mockFile.AssertNotCalled(t, "Truncate")
|
||||
|
||||
paster.Read(readBuffer)
|
||||
mockFile.AssertExpectations(t)
|
||||
|
@ -82,6 +88,7 @@ func TestWrite(t *testing.T) {
|
|||
mockFile.On("Write", testPaste).Return(len(testPaste), nil).Once()
|
||||
// Ensure we seek to the start of the file
|
||||
mockFile.On("Seek", int64(0), 0).Return(int64(0), nil).Once()
|
||||
mockFile.On("Truncate", int64(0)).Return(nil).Once()
|
||||
mockFile.AssertNotCalled(t, "Close")
|
||||
|
||||
paster.Write(testPaste)
|
||||
|
@ -93,7 +100,8 @@ func TestClose(t *testing.T) {
|
|||
mockFile := paster.file.(*MockFile)
|
||||
|
||||
mockFile.On("Close").Return(nil).Once()
|
||||
mockFile.AssertNotCalled(t, "Close")
|
||||
mockFile.AssertNotCalled(t, "Write")
|
||||
mockFile.AssertNotCalled(t, "Truncate")
|
||||
mockFile.AssertNotCalled(t, "Seek")
|
||||
mockFile.AssertNotCalled(t, "Read")
|
||||
// If we write to the file on close, that isn't the worst thing in the world and we won't enforce it being a problem
|
||||
|
|
Loading…
Reference in New Issue