@@ -88,8 +88,25 @@ func (err ErrRepoFileDoesNotExist) Unwrap() error {
88
88
return util .ErrNotExist
89
89
}
90
90
91
+ type LazyReader interface {
92
+ io.Closer
93
+ OpenLazyReader () error
94
+ }
95
+
91
96
// ChangeRepoFiles adds, updates or removes multiple files in the given repository
92
- func ChangeRepoFiles (ctx context.Context , repo * repo_model.Repository , doer * user_model.User , opts * ChangeRepoFilesOptions ) (* structs.FilesResponse , error ) {
97
+ func ChangeRepoFiles (ctx context.Context , repo * repo_model.Repository , doer * user_model.User , opts * ChangeRepoFilesOptions ) (_ * structs.FilesResponse , errRet error ) {
98
+ var addedLfsPointers []lfs.Pointer
99
+ defer func () {
100
+ if errRet != nil {
101
+ for _ , lfsPointer := range addedLfsPointers {
102
+ _ , err := git_model .RemoveLFSMetaObjectByOid (ctx , repo .ID , lfsPointer .Oid )
103
+ if err != nil {
104
+ log .Error ("ChangeRepoFiles: RemoveLFSMetaObjectByOid failed: %v" , err )
105
+ }
106
+ }
107
+ }
108
+ }()
109
+
93
110
err := repo .MustNotBeArchived ()
94
111
if err != nil {
95
112
return nil , err
@@ -242,9 +259,13 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
242
259
for _ , file := range opts .Files {
243
260
switch file .Operation {
244
261
case "create" , "update" , "rename" :
245
- if err = CreateUpdateRenameFile (ctx , t , file , lfsContentStore , repo .ID , hasOldBranch ); err != nil {
262
+ addedLfsPointer , err := CreateUpdateRenameFile (ctx , t , file , lfsContentStore , repo .ID )
263
+ if err != nil {
246
264
return nil , err
247
265
}
266
+ if addedLfsPointer != nil {
267
+ addedLfsPointers = append (addedLfsPointers , * addedLfsPointer )
268
+ }
248
269
case "delete" :
249
270
if err = t .RemoveFilesFromIndex (ctx , file .TreePath ); err != nil {
250
271
return nil , err
@@ -454,18 +475,23 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
454
475
return nil
455
476
}
456
477
457
- func CreateUpdateRenameFile (ctx context.Context , t * TemporaryUploadRepository , file * ChangeRepoFile , contentStore * lfs.ContentStore , repoID int64 , hasOldBranch bool ) error {
478
+ func CreateUpdateRenameFile (ctx context.Context , t * TemporaryUploadRepository , file * ChangeRepoFile , contentStore * lfs.ContentStore , repoID int64 ) (addedLfsPointer * lfs.Pointer , _ error ) {
479
+ if rd , ok := file .ContentReader .(LazyReader ); ok {
480
+ if err := rd .OpenLazyReader (); err != nil {
481
+ return nil , fmt .Errorf ("OpenLazyReader: %w" , err )
482
+ }
483
+ defer rd .Close ()
484
+ }
485
+
458
486
// Get the two paths (might be the same if not moving) from the index if they exist
459
487
filesInIndex , err := t .LsFiles (ctx , file .TreePath , file .FromTreePath )
460
488
if err != nil {
461
- return fmt .Errorf ("UpdateRepoFile : %w" , err )
489
+ return nil , fmt .Errorf ("LsFiles : %w" , err )
462
490
}
463
491
// If is a new file (not updating) then the given path shouldn't exist
464
492
if file .Operation == "create" {
465
493
if slices .Contains (filesInIndex , file .TreePath ) {
466
- return ErrRepoFileAlreadyExists {
467
- Path : file .TreePath ,
468
- }
494
+ return nil , ErrRepoFileAlreadyExists {Path : file .TreePath }
469
495
}
470
496
}
471
497
@@ -474,7 +500,7 @@ func CreateUpdateRenameFile(ctx context.Context, t *TemporaryUploadRepository, f
474
500
for _ , indexFile := range filesInIndex {
475
501
if indexFile == file .Options .fromTreePath {
476
502
if err = t .RemoveFilesFromIndex (ctx , file .FromTreePath ); err != nil {
477
- return err
503
+ return nil , err
478
504
}
479
505
}
480
506
}
@@ -487,40 +513,41 @@ func CreateUpdateRenameFile(ctx context.Context, t *TemporaryUploadRepository, f
487
513
case "rename" :
488
514
writeObjectRet , err = writeRepoObjectForRename (ctx , t , file )
489
515
default :
490
- return util .NewInvalidArgumentErrorf ("unknown file modification operation: '%s'" , file .Operation )
516
+ return nil , util .NewInvalidArgumentErrorf ("unknown file modification operation: '%s'" , file .Operation )
491
517
}
492
518
if err != nil {
493
- return err
519
+ return nil , err
494
520
}
495
521
496
522
// Add the object to the index, the "file.Options.executable" is set in handleCheckErrors by the caller (legacy hacky approach)
497
523
if err = t .AddObjectToIndex (ctx , util .Iif (file .Options .executable , "100755" , "100644" ), writeObjectRet .ObjectHash , file .Options .treePath ); err != nil {
498
- return err
524
+ return nil , err
499
525
}
500
526
501
527
if writeObjectRet .LfsContent == nil {
502
- return nil // No LFS pointer, so nothing to do
528
+ return nil , nil // No LFS pointer, so nothing to do
503
529
}
504
530
defer writeObjectRet .LfsContent .Close ()
505
531
506
532
// Now we must store the content into an LFS object
507
533
lfsMetaObject , err := git_model .NewLFSMetaObject (ctx , repoID , writeObjectRet .LfsPointer )
508
534
if err != nil {
509
- return err
510
- }
511
- if exist , err := contentStore .Exists (lfsMetaObject .Pointer ); err != nil {
512
- return err
513
- } else if exist {
514
- return nil
535
+ return nil , err
515
536
}
516
-
517
- err = contentStore .Put (lfsMetaObject .Pointer , writeObjectRet .LfsContent )
537
+ exist , err := contentStore .Exists (lfsMetaObject .Pointer )
518
538
if err != nil {
519
- if _ , errRemove := git_model .RemoveLFSMetaObjectByOid (ctx , repoID , lfsMetaObject .Oid ); errRemove != nil {
520
- return fmt .Errorf ("unable to remove failed inserted LFS object %s: %v (Prev Error: %w)" , lfsMetaObject .Oid , errRemove , err )
539
+ return nil , err
540
+ }
541
+ if ! exist {
542
+ err = contentStore .Put (lfsMetaObject .Pointer , writeObjectRet .LfsContent )
543
+ if err != nil {
544
+ if _ , errRemove := git_model .RemoveLFSMetaObjectByOid (ctx , repoID , lfsMetaObject .Oid ); errRemove != nil {
545
+ return nil , fmt .Errorf ("unable to remove failed inserted LFS object %s: %v (Prev Error: %w)" , lfsMetaObject .Oid , errRemove , err )
546
+ }
547
+ return nil , err
521
548
}
522
549
}
523
- return err
550
+ return & lfsMetaObject . Pointer , nil
524
551
}
525
552
526
553
func checkIsLfsFileInGitAttributes (ctx context.Context , t * TemporaryUploadRepository , paths []string ) (ret []bool , err error ) {
0 commit comments