nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: spf13/afero
Pull request #239 (2020-04-11 09:58:12)

Fix renaming a dir with sub-directories
I think it should fix issue #141 

nono: @bep hi, this is an old pull request but I think it would still be a good fix for afero. I have rebased it and listened to the comments made by @0xmichalis. If you have time to look at it, it would be appreciated.

Patch:
diff --git a/memmap.go b/memmap.go
index d06975e..5cfc0a6 100644
--- a/memmap.go
+++ b/memmap.go
@@ -319,6 +319,18 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
 	} else {
 		return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
 	}
+
+	for p, fileData := range m.getData() {
+		if strings.HasPrefix(p, oldname+FilePathSeparator) {
+			m.mu.RUnlock()
+			m.mu.Lock()
+			delete(m.getData(), p)
+			p := strings.Replace(p, oldname, newname, 1)
+			m.getData()[p] = fileData
+			m.mu.Unlock()
+			m.mu.RLock()
+		}
+	}
 	return nil
 }
 


Test patch:
diff --git a/memmap_test.go b/memmap_test.go
index 4f2bbad..318e95f 100644
--- a/memmap_test.go
+++ b/memmap_test.go
@@ -776,3 +776,60 @@ func TestMemMapFsConfurrentMkdir(t *testing.T) {
 		t.Errorf("found %d files, but expect %d", len(foundFiles), n)
 	}
 }
+
+func TestMemFsRenameDir(t *testing.T) {
+	const srcPath = "/src"
+	const dstPath = "/dst"
+	const subDir = "dir"
+	const subFile = "file.txt"
+
+	fs := NewMemMapFs()
+
+	err := fs.MkdirAll(srcPath+FilePathSeparator+subDir, 0777)
+	if err != nil {
+		t.Fatalf("MkDirAll failed: %s", err)
+	}
+
+	f, err := fs.Create(srcPath + FilePathSeparator + subFile)
+	if err != nil {
+		t.Fatalf("Create failed: %s", err)
+	}
+	if err = f.Close(); err != nil {
+		t.Fatalf("Close failed: %s", err)
+	}
+
+	err = fs.Rename(srcPath, dstPath)
+	if err != nil {
+		t.Fatalf("Rename failed: %s", err)
+	}
+
+	_, err = fs.Stat(srcPath + FilePathSeparator + subDir)
+	if err == nil {
+		t.Fatalf("SubDir still exists in the source dir")
+	}
+
+	_, err = fs.Stat(srcPath + FilePathSeparator + subFile)
+	if err == nil {
+		t.Fatalf("SubFile still exists in the source dir")
+	}
+
+	_, err = fs.Stat(dstPath + FilePathSeparator + subDir)
+	if err != nil {
+		t.Fatalf("SubDir stat in the destination dir: %s", err)
+	}
+
+	_, err = fs.Stat(dstPath + FilePathSeparator + subFile)
+	if err != nil {
+		t.Fatalf("SubFile stat in the destination dir: %s", err)
+	}
+
+	err = fs.Mkdir(srcPath, 0777)
+	if err != nil {
+		t.Fatalf("Cannot recreate the source dir: %s", err)
+	}
+
+	err = fs.Mkdir(srcPath+FilePathSeparator+subDir, 0777)
+	if err != nil {
+		t.Errorf("Cannot recreate the subdir in the source dir: %s", err)
+	}
+}
Repository: spf13/afero
Pull request #249 (2020-07-12 01:51:51)

Prevent MemMapFs.Chmod from changing all mode bits
I ran into an issue where my program called `fs.Chmod` and it changed from a directory to a regular file. This one had me stumped for weeks 😅 

After checking [`os.Chmod`'s docs](https://golang.org/pkg/os/#Chmod), I bit-masked the part Chmod is permitted to set, then OR'd it with the file's other previous mode bits. I also added a test to check the file type after setting all permission bits to 0.


Patch:
diff --git a/memmap.go b/memmap.go
index b7b1474..6be0e9c 100644
--- a/memmap.go
+++ b/memmap.go
@@ -141,9 +141,7 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
 	m.registerWithParent(item)
 	m.mu.Unlock()
 
-	m.Chmod(name, perm|os.ModeDir)
-
-	return nil
+	return m.setFileMode(name, perm|os.ModeDir)
 }
 
 func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
@@ -240,7 +238,7 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro
 		}
 	}
 	if chmod {
-		m.Chmod(name, perm)
+		return file, m.setFileMode(name, perm)
 	}
 	return file, nil
 }
@@ -321,6 +319,22 @@ func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
 }
 
 func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
+	const chmodBits = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky // Only a subset of bits are allowed to be changed. Documented under os.Chmod()
+	mode &= chmodBits
+
+	m.mu.RLock()
+	f, ok := m.getData()[name]
+	m.mu.RUnlock()
+	if !ok {
+		return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
+	}
+	prevOtherBits := mem.GetFileInfo(f).Mode() & ^chmodBits
+
+	mode = prevOtherBits | mode
+	return m.setFileMode(name, mode)
+}
+
+func (m *MemMapFs) setFileMode(name string, mode os.FileMode) error {
 	name = normalizePath(name)
 
 	m.mu.RLock()


Test patch:
diff --git a/memmap_test.go b/memmap_test.go
index a88ea30..371096f 100644
--- a/memmap_test.go
+++ b/memmap_test.go
@@ -472,3 +472,34 @@ func TestMemFsUnexpectedEOF(t *testing.T) {
 		t.Fatal("Expected ErrUnexpectedEOF")
 	}
 }
+
+func TestMemFsChmod(t *testing.T) {
+	t.Parallel()
+
+	fs := NewMemMapFs()
+	const file = "hello"
+	if err := fs.Mkdir(file, 0700); err != nil {
+		t.Fatal(err)
+	}
+
+	info, err := fs.Stat(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if info.Mode().String() != "drwx------" {
+		t.Fatal("mkdir failed to create a directory: mode =", info.Mode())
+	}
+
+	err = fs.Chmod(file, 0)
+	if err != nil {
+		t.Error("Failed to run chmod:", err)
+	}
+
+	info, err = fs.Stat(file)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if info.Mode().String() != "d---------" {
+		t.Error("chmod should not change file type. New mode =", info.Mode())
+	}
+}
Repository: spf13/afero
Pull request #263 (2020-09-02 06:00:45)

mem: fix incorrect offset in Write
Hello, everyone,

Recently I needed an in-memory implementation of io.WriteSeeker and tried to use File. Unfortunately, my code panicked using afero's File implementation whereas os.File implementation worked flawlessly.

It looks like Write incorrectly sets offset after appending data. I've written a test for correct behaviour and implemented a fix.

Also, I check `whence` value in Seek against `io.Seek*` literals so it reads easier for people with bad memory like me.


Patch:
diff --git a/mem/file.go b/mem/file.go
index 699f1fb..07b2e12 100644
--- a/mem/file.go
+++ b/mem/file.go
@@ -225,11 +225,11 @@ func (f *File) Seek(offset int64, whence int) (int64, error) {
 		return 0, ErrFileClosed
 	}
 	switch whence {
-	case 0:
+	case io.SeekStart:
 		atomic.StoreInt64(&f.at, offset)
-	case 1:
-		atomic.AddInt64(&f.at, int64(offset))
-	case 2:
+	case io.SeekCurrent:
+		atomic.AddInt64(&f.at, offset)
+	case io.SeekEnd:
 		atomic.StoreInt64(&f.at, int64(len(f.fileData.data))+offset)
 	}
 	return f.at, nil
@@ -260,7 +260,7 @@ func (f *File) Write(b []byte) (n int, err error) {
 	}
 	setModTime(f.fileData, time.Now())
 
-	atomic.StoreInt64(&f.at, int64(len(f.fileData.data)))
+	atomic.AddInt64(&f.at, int64(n))
 	return
 }
 


Test patch:
diff --git a/mem/file_test.go b/mem/file_test.go
index bb54db6..22af970 100644
--- a/mem/file_test.go
+++ b/mem/file_test.go
@@ -1,6 +1,7 @@
 package mem
 
 import (
+	"bytes"
 	"io"
 	"testing"
 	"time"
@@ -205,3 +206,42 @@ func TestFileReadAtSeekOffset(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestFileWriteAndSeek(t *testing.T) {
+	fd := CreateFile("foo")
+	f := NewFileHandle(fd)
+
+	assert := func(expected bool, v ...interface{}) {
+		if !expected {
+			t.Helper()
+			t.Fatal(v...)
+		}
+	}
+
+	data4 := []byte{0, 1, 2, 3}
+	data20 := bytes.Repeat(data4, 5)
+	var off int64
+
+	for i := 0; i < 100; i++ {
+		// write 20 bytes
+		n, err := f.Write(data20)
+		assert(err == nil, err)
+		off += int64(n)
+		assert(n == len(data20), n)
+		assert(off == int64((i+1)*len(data20)), off)
+
+		// rewind to start and write 4 bytes there
+		cur, err := f.Seek(-off, io.SeekCurrent)
+		assert(err == nil, err)
+		assert(cur == 0, cur)
+
+		n, err = f.Write(data4)
+		assert(err == nil, err)
+		assert(n == len(data4), n)
+
+		// back at the end
+		cur, err = f.Seek(off-int64(n), io.SeekCurrent)
+		assert(err == nil, err)
+		assert(cur == off, cur, off)
+	}
+}
Repository: spf13/afero
Pull request #264 (2020-09-07 05:08:17)

Make MemMapFs implement Lstater
MemMapFs does not currently implement Lstater which can make it a bit difficult when a program is wanting to call Lstat on an unknown filesystem, so I am implementing the interface. The real call is to `Stat()`, and a `false` is simply returned to indicate that an Lstat was not called.

This change was prompted in my work of https://github.com/chigopher/pathlib, specifically: https://github.com/chigopher/pathlib/pull/16. The issue arose when testing a Walk function that calls LstatIfPossible, where the test uses a MemMapFs.


Patch:
diff --git a/memmap.go b/memmap.go
index bbcc238..0fa9592 100644
--- a/memmap.go
+++ b/memmap.go
@@ -317,6 +317,11 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
 	return nil
 }
 
+func (m *MemMapFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
+	fileInfo, err := m.Stat(name)
+	return fileInfo, false, err
+}
+
 func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
 	f, err := m.Open(name)
 	if err != nil {


Test patch:
diff --git a/memmap_test.go b/memmap_test.go
index 6ce742c..476909d 100644
--- a/memmap_test.go
+++ b/memmap_test.go
@@ -650,3 +650,31 @@ func TestMemFsOpenFileModeIllegal(t *testing.T) {
 		t.Fatalf("should not be able to use OpenFile to set illegal mode: %s", info.Mode().String())
 	}
 }
+
+// LstatIfPossible should always return false, since MemMapFs does not
+// support symlinks.
+func TestMemFsLstatIfPossible(t *testing.T) {
+	t.Parallel()
+
+	fs := NewMemMapFs()
+
+	// We assert that fs implements Lstater
+	fsAsserted, ok := fs.(Lstater)
+	if !ok {
+		t.Fatalf("The filesytem does not implement Lstater")
+	}
+
+	file, err := fs.OpenFile("/a.txt", os.O_CREATE, 0o644)
+	if err != nil {
+		t.Fatalf("Error when opening file: %v", err)
+	}
+	defer file.Close()
+
+	_, lstatCalled, err := fsAsserted.LstatIfPossible("/a.txt")
+	if err != nil {
+		t.Fatalf("Function returned err: %v", err)
+	}
+	if lstatCalled {
+		t.Fatalf("Function indicated lstat was called. This should never be true.")
+	}
+}
Repository: spf13/afero
Pull request #268 (2020-10-05 22:26:46)

Do not panic on passing empty tar reader to tarfs
Corrects a bug where passing an empty tar reader to tarfs would cause
adding the pseudoroot to panic with assignment to entry in nil map.

Signed-off-by: hasheddan <georgedanielmangum@gmail.com>

cc @agimenez because it looked like you implemented tarfs (thank you for your work!)

@kargakis would it be possible to get a v1.4.1 published after merge?


Patch:
diff --git a/tarfs/fs.go b/tarfs/fs.go
index ba3212b..f8a2ce2 100644
--- a/tarfs/fs.go
+++ b/tarfs/fs.go
@@ -63,6 +63,9 @@ func New(t *tar.Reader) *Fs {
 
 	}
 
+	if fs.files[afero.FilePathSeparator] == nil {
+		fs.files[afero.FilePathSeparator] = make(map[string]*File)
+	}
 	// Add a pseudoroot
 	fs.files[afero.FilePathSeparator][""] = &File{
 		h: &tar.Header{


Test patch:
diff --git a/tarfs/tarfs_test.go b/tarfs/tarfs_test.go
index 8d5eaab..c588c79 100644
--- a/tarfs/tarfs_test.go
+++ b/tarfs/tarfs_test.go
@@ -9,6 +9,7 @@ import (
 	"os"
 	"path/filepath"
 	"reflect"
+	"strings"
 	"syscall"
 	"testing"
 
@@ -54,6 +55,9 @@ func TestMain(m *testing.M) {
 
 	tfs := New(tar.NewReader(tf))
 	afs = &afero.Afero{Fs: tfs}
+
+	// Check that an empty reader does not panic.
+	_ = New(tar.NewReader(strings.NewReader("")))
 	os.Exit(m.Run())
 }