diff --git a/internal/local/lock.go b/internal/local/lock.go index c44d6c9..d0b3d60 100644 --- a/internal/local/lock.go +++ b/internal/local/lock.go @@ -32,21 +32,17 @@ func NewLockFile(path string) (*LockFile, error) { path: path, temp: temp, } - // If the lock file already exists, return an error. - if _, err := os.Stat(temp); err == nil { - f, err := os.Open(temp) - if err != nil { - return nil, transfer.ErrConflict - } + + if f, err := os.OpenFile(temp, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666); err == nil { lf.tempFile = f - return lf, transfer.ErrConflict - } - f, err := os.Create(temp) - if err != nil { - return nil, err + return lf, nil + } else if os.IsExist(err) { + if f, err = os.OpenFile(temp, os.O_RDONLY, 0666); err == nil { + lf.tempFile = f + return lf, transfer.ErrConflict + } } - lf.tempFile = f - return lf, nil + return nil, transfer.ErrConflict } // Write writes the given data to the lock file. diff --git a/internal/local/lock_test.go b/internal/local/lock_test.go new file mode 100644 index 0000000..68d28e7 --- /dev/null +++ b/internal/local/lock_test.go @@ -0,0 +1,37 @@ +package local_test + +import ( + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/charmbracelet/git-lfs-transfer/internal/local" + "github.com/charmbracelet/git-lfs-transfer/transfer" +) + +func TestTakeLock(t *testing.T) { + tb := testing.TB(t) + tb.Helper() + path := filepath.Join(tb.TempDir(), "test_subject") + testfile, err := local.NewLockFile(path) + defer func() { _ = testfile.Close() }() + assert.Equal(t, err, nil) + assert.NotEqual(t, testfile, nil) +} + +func TestMissLock(t *testing.T) { + tb := testing.TB(t) + tb.Helper() + path := filepath.Join(tb.TempDir(), "test_subject") + testfile, err := local.NewLockFile(path) + defer testfile.Close() + assert.Equal(t, err, nil) + assert.NotEqual(t, testfile, nil) + t2, e2 := local.NewLockFile(path) + if t2 != nil { + defer t2.Close() + } + assert.Equal(t, e2, transfer.ErrConflict) + assert.NotEqual(t, t2, nil) +}