@@ -488,7 +488,6 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
488488 }
489489 }
490490
491- var treeObjectContentReader io.Reader = file .ContentReader
492491 var oldEntry * git.TreeEntry
493492 // Assume that the file.ContentReader of a pure rename operation is invalid. Use the file content how it's present in
494493 // git instead
@@ -505,53 +504,15 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
505504 if oldEntry , err = commit .GetTreeEntryByPath (file .Options .fromTreePath ); err != nil {
506505 return err
507506 }
508- if treeObjectContentReader , err = oldEntry .Blob ().DataAsync (); err != nil {
509- return err
510- }
511- defer treeObjectContentReader .(io.ReadCloser ).Close ()
512507 }
513508
514- var lfsMetaObject * git_model.LFSMetaObject
515- if setting .LFS .StartServer && hasOldBranch {
516- // Check there is no way this can return multiple infos
517- attributesMap , err := attribute .CheckAttributes (ctx , t .gitRepo , "" /* use temp repo's working dir */ , attribute.CheckAttributeOpts {
518- Attributes : []string {attribute .Filter },
519- Filenames : []string {file .Options .treePath , file .Options .fromTreePath },
520- })
521- if err != nil {
522- return err
523- }
524-
525- var pointer lfs.Pointer
526- // Get existing lfs pointer if the operation is a pure rename and the old path is in lfs. This prevents the
527- // regeneration/rehash of a lfs pointer to the same data
528- if file .Operation == "rename" && attributesMap [file .Options .fromTreePath ] != nil && attributesMap [file .Options .fromTreePath ].Get (attribute .Filter ).ToString ().Value () == "lfs" {
529- if pointer , err = lfs .ReadPointer (treeObjectContentReader ); err != nil {
530- return err
531- }
532- }
533-
534- if attributesMap [file .Options .treePath ] != nil && attributesMap [file .Options .treePath ].Get (attribute .Filter ).ToString ().Value () == "lfs" {
535- if ! pointer .IsValid () {
536- if pointer , err = lfs .GeneratePointer (treeObjectContentReader ); err != nil {
537- return err
538- }
539- }
540-
541- lfsMetaObject = & git_model.LFSMetaObject {Pointer : pointer , RepositoryID : repoID }
542- treeObjectContentReader = strings .NewReader (pointer .StringContent ())
543- } else if pointer .IsValid () { // old path was in lfs, new is not
544- treeObjectContentReader , err = lfs .ReadMetaObject (pointer )
545- if err != nil {
546- return err
547- }
548- }
549- }
550-
551- // Add the object to the database
552- objectHash , err := t .HashObject (ctx , treeObjectContentReader )
553- if err != nil {
554- return err
509+ var objectHash string
510+ var lfsPointer * lfs.Pointer
511+ switch file .Operation {
512+ case "create" , "update" :
513+ objectHash , lfsPointer , err = createOrUpdateFile (ctx , t , file , hasOldBranch )
514+ case "rename" :
515+ objectHash , lfsPointer , err = renameFile (ctx , t , oldEntry , file , hasOldBranch )
555516 }
556517
557518 // Add the object to the index
@@ -565,9 +526,9 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
565526 }
566527 }
567528
568- if lfsMetaObject != nil {
529+ if lfsPointer != nil {
569530 // We have an LFS object - create it
570- lfsMetaObject , err = git_model .NewLFSMetaObject (ctx , lfsMetaObject . RepositoryID , lfsMetaObject . Pointer )
531+ lfsMetaObject , err : = git_model .NewLFSMetaObject (ctx , repoID , * lfsPointer )
571532 if err != nil {
572533 return err
573534 }
@@ -601,6 +562,99 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
601562 return nil
602563}
603564
565+ func createOrUpdateFile (ctx context.Context , t * TemporaryUploadRepository , file * ChangeRepoFile , hasOldBranch bool ) (string , * lfs.Pointer , error ) {
566+ treeObjectContentReader := file .ContentReader
567+ var lfsPointer * lfs.Pointer
568+ if setting .LFS .StartServer && hasOldBranch {
569+ // Check there is no way this can return multiple infos
570+ attributesMap , err := attribute .CheckAttributes (ctx , t .gitRepo , "" /* use temp repo's working dir */ , attribute.CheckAttributeOpts {
571+ Attributes : []string {attribute .Filter },
572+ Filenames : []string {file .Options .treePath },
573+ })
574+ if err != nil {
575+ return "" , nil , err
576+ }
577+
578+ if attributesMap [file .Options .treePath ] != nil && attributesMap [file .Options .treePath ].Get (attribute .Filter ).ToString ().Value () == "lfs" {
579+ // OK so we are supposed to LFS this data!
580+ pointer , err := lfs .GeneratePointer (treeObjectContentReader )
581+ if err != nil {
582+ return "" , nil , err
583+ }
584+ lfsPointer = & pointer
585+ treeObjectContentReader = strings .NewReader (pointer .StringContent ())
586+ }
587+ }
588+
589+ // Add the object to the database
590+ objectHash , err := t .HashObject (ctx , treeObjectContentReader )
591+ if err != nil {
592+ return "" , nil , err
593+ }
594+
595+ return objectHash , lfsPointer , nil
596+ }
597+
598+ func renameFile (ctx context.Context , t * TemporaryUploadRepository , oldEntry * git.TreeEntry , file * ChangeRepoFile , hasOldBranch bool ) (string , * lfs.Pointer , error ) {
599+ if setting .LFS .StartServer && hasOldBranch {
600+ attributesMap , err := attribute .CheckAttributes (ctx , t .gitRepo , "" /* use temp repo's working dir */ , attribute.CheckAttributeOpts {
601+ Attributes : []string {attribute .Filter },
602+ Filenames : []string {file .Options .treePath , file .Options .fromTreePath },
603+ })
604+ if err != nil {
605+ return "" , nil , err
606+ }
607+
608+ oldIsLfs := attributesMap [file .Options .fromTreePath ] != nil && attributesMap [file .Options .fromTreePath ].Get (attribute .Filter ).ToString ().Value () == "lfs"
609+ newIsLfs := attributesMap [file .Options .treePath ] != nil && attributesMap [file .Options .treePath ].Get (attribute .Filter ).ToString ().Value () == "lfs"
610+
611+ // If the old and new path are both in lfs or both not in lfs, the object hash of the old file can be used directly
612+ // as the object doesn't change
613+ if oldIsLfs == newIsLfs {
614+ return oldEntry .ID .String (), nil , nil
615+ }
616+
617+ oldEntryReader , err := oldEntry .Blob ().DataAsync ()
618+ if err != nil {
619+ return "" , nil , err
620+ }
621+ defer oldEntryReader .Close ()
622+
623+ var treeObjectContentReader io.Reader
624+ var lfsPointer * lfs.Pointer
625+ // If the old path is in lfs but the new isn't, read the content from lfs and add it as normal git object
626+ // If the new path is in lfs but the old isn't, read the content from the git object and generate a lfs
627+ // pointer of it
628+ if oldIsLfs {
629+ pointer , err := lfs .ReadPointer (oldEntryReader )
630+ if err != nil {
631+ return "" , nil , err
632+ }
633+ treeObjectContentReader , err = lfs .ReadMetaObject (pointer )
634+ if err != nil {
635+ return "" , nil , err
636+ }
637+ defer treeObjectContentReader .(io.ReadCloser ).Close ()
638+ } else {
639+ pointer , err := lfs .GeneratePointer (oldEntryReader )
640+ if err != nil {
641+ return "" , nil , err
642+ }
643+ treeObjectContentReader = strings .NewReader (pointer .StringContent ())
644+ lfsPointer = & pointer
645+ }
646+
647+ // Add the object to the database
648+ objectID , err := t .HashObject (ctx , treeObjectContentReader )
649+ if err != nil {
650+ return "" , nil , err
651+ }
652+ return objectID , lfsPointer , nil
653+ } else {
654+ return oldEntry .ID .String (), nil , nil
655+ }
656+ }
657+
604658// VerifyBranchProtection verify the branch protection for modifying the given treePath on the given branch
605659func VerifyBranchProtection (ctx context.Context , repo * repo_model.Repository , doer * user_model.User , branchName string , treePaths []string ) error {
606660 protectedBranch , err := git_model .GetFirstMatchProtectedBranchRule (ctx , repo .ID , branchName )
0 commit comments