@@ -181,6 +181,95 @@ func TestPackWriterPermissions(t *testing.T) {
181181 }
182182}
183183
184+ func TestPackWriterExistingReadOnly (t * testing.T ) {
185+ t .Parallel ()
186+
187+ for _ , tc := range []struct {
188+ name string
189+ fs billy.Filesystem
190+ }{
191+ {"BoundOS" , osfs .New (t .TempDir (), osfs .WithBoundOS ())},
192+ {"ChrootOS" , osfs .New (t .TempDir (), osfs .WithChrootOS ())},
193+ } {
194+ t .Run (tc .name , func (t * testing.T ) {
195+ t .Parallel ()
196+
197+ f := fixtures .Basic ().One ()
198+
199+ dot := New (tc .fs )
200+ require .NoError (t , dot .Initialize ())
201+
202+ pfPath := filepath .Join ("objects" , "pack" , fmt .Sprintf ("pack-%s.pack" , f .PackfileHash ))
203+ idxPath := filepath .Join ("objects" , "pack" , fmt .Sprintf ("pack-%s.idx" , f .PackfileHash ))
204+
205+ writePack := func () {
206+ t .Helper ()
207+ w , err := dot .NewObjectPack ()
208+ require .NoError (t , err )
209+
210+ _ , err = io .Copy (w , f .Packfile ())
211+ require .NoError (t , err )
212+ require .NoError (t , w .Close ())
213+ }
214+
215+ writePack ()
216+
217+ ro , err := isReadOnly (tc .fs , pfPath )
218+ require .NoError (t , err )
219+ assert .True (t , ro , "file %q is not read-only" , pfPath )
220+
221+ ro , err = isReadOnly (tc .fs , idxPath )
222+ require .NoError (t , err )
223+ assert .True (t , ro , "file %q is not read-only" , idxPath )
224+
225+ writePack ()
226+
227+ // Remove .idx only, keep .pack — the next write must
228+ // recreate .idx without touching the existing .pack.
229+ require .NoError (t , tc .fs .Remove (idxPath ))
230+ writePack ()
231+
232+ _ , err = tc .fs .Lstat (idxPath )
233+ require .NoError (t , err , ".idx should have been recreated" )
234+
235+ ro , err = isReadOnly (tc .fs , idxPath )
236+ require .NoError (t , err )
237+ assert .True (t , ro , "recreated %q is not read-only" , idxPath )
238+ })
239+ }
240+ }
241+
242+ func TestPackWriterRejectsNonRegularFile (t * testing.T ) {
243+ t .Parallel ()
244+
245+ for _ , ext := range []string {".idx" , ".pack" } {
246+ t .Run (ext , func (t * testing.T ) {
247+ t .Parallel ()
248+
249+ f := fixtures .Basic ().One ()
250+ fs := osfs .New (t .TempDir (), osfs .WithBoundOS ())
251+
252+ dot := New (fs )
253+ require .NoError (t , dot .Initialize ())
254+
255+ // Place a directory where the pack file should go.
256+ path := filepath .Join ("objects" , "pack" ,
257+ fmt .Sprintf ("pack-%s%s" , f .PackfileHash , ext ))
258+ require .NoError (t , fs .MkdirAll (path , 0o755 ))
259+
260+ w , err := dot .NewObjectPack ()
261+ require .NoError (t , err )
262+
263+ _ , err = io .Copy (w , f .Packfile ())
264+ require .NoError (t , err )
265+
266+ err = w .Close ()
267+ require .Error (t , err )
268+ assert .Contains (t , err .Error (), "unexpected file type" )
269+ })
270+ }
271+ }
272+
184273func TestObjectWriterPermissions (t * testing.T ) {
185274 t .Parallel ()
186275
0 commit comments