Skip to content

Commit 5d20a62

Browse files
committed
storage: filesystem, Fix permissions for loose and packed objs
Align behaviour with upstream and v6, whereby all loose and packed objects are saved on disk as read-only as they are not meant to be modified due to their nature, as they are content addressable files. Signed-off-by: Paulo Gomes <[email protected]>
1 parent 8ed442c commit 5d20a62

4 files changed

Lines changed: 87 additions & 5 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ require (
1313
github.com/emirpasic/gods v1.18.1
1414
github.com/gliderlabs/ssh v0.3.8
1515
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376
16-
github.com/go-git/go-billy/v5 v5.6.2
16+
github.com/go-git/go-billy/v5 v5.7.0
1717
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399
1818
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8
1919
github.com/google/go-cmp v0.7.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
2525
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
2626
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
2727
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
28-
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
29-
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
28+
github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM=
29+
github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E=
3030
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
3131
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
3232
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=

storage/filesystem/dotgit/writers.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package dotgit
33
import (
44
"fmt"
55
"io"
6+
"runtime"
67
"sync/atomic"
78

89
"github.com/go-git/go-git/v5/plumbing"
910
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
1011
"github.com/go-git/go-git/v5/plumbing/format/objfile"
1112
"github.com/go-git/go-git/v5/plumbing/format/packfile"
1213
"github.com/go-git/go-git/v5/plumbing/hash"
14+
"github.com/go-git/go-git/v5/utils/trace"
1315

1416
"github.com/go-git/go-billy/v5"
1517
)
@@ -137,14 +139,22 @@ func (w *PackWriter) save() error {
137139
}
138140

139141
if err := w.encodeIdx(idx); err != nil {
142+
_ = idx.Close()
140143
return err
141144
}
142145

143146
if err := idx.Close(); err != nil {
144147
return err
145148
}
149+
fixPermissions(w.fs, fmt.Sprintf("%s.idx", base))
146150

147-
return w.fs.Rename(w.fw.Name(), fmt.Sprintf("%s.pack", base))
151+
packPath := fmt.Sprintf("%s.pack", base)
152+
if err := w.fs.Rename(w.fw.Name(), packPath); err != nil {
153+
return err
154+
}
155+
fixPermissions(w.fs, packPath)
156+
157+
return nil
148158
}
149159

150160
func (w *PackWriter) encodeIdx(writer io.Writer) error {
@@ -281,5 +291,22 @@ func (w *ObjectWriter) save() error {
281291
hex := w.Hash().String()
282292
file := w.fs.Join(objectsPath, hex[0:2], hex[2:hash.HexSize])
283293

284-
return w.fs.Rename(w.f.Name(), file)
294+
if err := w.fs.Rename(w.f.Name(), file); err != nil {
295+
return err
296+
}
297+
fixPermissions(w.fs, file)
298+
299+
return nil
300+
}
301+
302+
func fixPermissions(fs billy.Filesystem, path string) {
303+
if runtime.GOOS == "windows" {
304+
return
305+
}
306+
307+
if chmodFS, ok := fs.(billy.Chmod); ok {
308+
if err := chmodFS.Chmod(path, 0o444); err != nil {
309+
trace.General.Printf("failed to chmod %s: %v", path, err)
310+
}
311+
}
285312
}

storage/filesystem/dotgit/writers_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ import (
55
"io"
66
"os"
77
"strconv"
8+
"testing"
89

910
"github.com/go-git/go-billy/v5/osfs"
1011
"github.com/go-git/go-billy/v5/util"
1112
"github.com/go-git/go-git/v5/plumbing"
1213
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
1314
"github.com/go-git/go-git/v5/plumbing/format/packfile"
15+
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
1417

1518
fixtures "github.com/go-git/go-git-fixtures/v4"
1619
. "gopkg.in/check.v1"
@@ -135,3 +138,55 @@ func (s *SuiteDotGit) TestPackWriterUnusedNotify(c *C) {
135138

136139
c.Assert(w.Close(), IsNil)
137140
}
141+
142+
func TestPackWriterPermissions(t *testing.T) {
143+
t.Parallel()
144+
145+
f := fixtures.Basic().One()
146+
147+
fs := osfs.New(t.TempDir(), osfs.WithBoundOS())
148+
dot := New(fs)
149+
require.NoError(t, dot.Initialize())
150+
151+
w, err := dot.NewObjectPack()
152+
require.NoError(t, err)
153+
154+
_, err = io.Copy(w, f.Packfile())
155+
require.NoError(t, err)
156+
157+
require.NoError(t, w.Close())
158+
159+
pfPath := fmt.Sprintf("objects/pack/pack-%s.pack", f.PackfileHash)
160+
idxPath := fmt.Sprintf("objects/pack/pack-%s.idx", f.PackfileHash)
161+
162+
stat, err := fs.Stat(pfPath)
163+
require.NoError(t, err)
164+
assert.Equal(t, os.FileMode(0o444), stat.Mode().Perm())
165+
166+
stat, err = fs.Stat(idxPath)
167+
require.NoError(t, err)
168+
assert.Equal(t, os.FileMode(0o444), stat.Mode().Perm())
169+
}
170+
171+
func TestObjectWriterPermissions(t *testing.T) {
172+
t.Parallel()
173+
174+
fs := osfs.New(t.TempDir(), osfs.WithBoundOS())
175+
dot := New(fs)
176+
require.NoError(t, dot.Initialize())
177+
178+
w, err := dot.NewObject()
179+
require.NoError(t, err)
180+
181+
err = w.WriteHeader(plumbing.BlobObject, 14)
182+
require.NoError(t, err)
183+
184+
_, err = w.Write([]byte("this is a test"))
185+
require.NoError(t, err)
186+
187+
require.NoError(t, w.Close())
188+
189+
stat, err := fs.Stat("objects/a8/a940627d132695a9769df883f85992f0ff4a43")
190+
require.NoError(t, err)
191+
assert.Equal(t, os.FileMode(0o444), stat.Mode().Perm())
192+
}

0 commit comments

Comments
 (0)