@@ -7,11 +7,13 @@ package models
77import (
88 "context"
99 "errors"
10+ "fmt"
1011
1112 "code.gitea.io/gitea/models/db"
1213 repo_model "code.gitea.io/gitea/models/repo"
1314 user_model "code.gitea.io/gitea/models/user"
1415 "code.gitea.io/gitea/modules/lfs"
16+ "code.gitea.io/gitea/modules/log"
1517 "code.gitea.io/gitea/modules/timeutil"
1618
1719 "xorm.io/builder"
@@ -145,6 +147,11 @@ func LFSObjectAccessible(user *user_model.User, oid string) (bool, error) {
145147 return count > 0 , err
146148}
147149
150+ // LFSObjectIsAssociated checks if a provided Oid is associated
151+ func LFSObjectIsAssociated (oid string ) (bool , error ) {
152+ return db .GetEngine (db .DefaultContext ).Exist (& LFSMetaObject {Pointer : lfs.Pointer {Oid : oid }})
153+ }
154+
148155// LFSAutoAssociate auto associates accessible LFSMetaObjects
149156func LFSAutoAssociate (metas []* LFSMetaObject , user * user_model.User , repoID int64 ) error {
150157 ctx , committer , err := db .TxContext ()
@@ -162,23 +169,39 @@ func LFSAutoAssociate(metas []*LFSMetaObject, user *user_model.User, repoID int6
162169 oidMap [meta .Oid ] = meta
163170 }
164171
165- cond := builder .NewCond ()
166172 if ! user .IsAdmin {
167- cond = builder .In ("`lfs_meta_object`.repository_id" ,
168- builder .Select ("`repository`.id" ).From ("repository" ).Where (accessibleRepositoryCondition (user )))
169- }
170- newMetas := make ([]* LFSMetaObject , 0 , len (metas ))
171- if err := sess .Cols ("oid" ).Where (cond ).In ("oid" , oids ... ).GroupBy ("oid" ).Find (& newMetas ); err != nil {
172- return err
173- }
174- for i := range newMetas {
175- newMetas [i ].Size = oidMap [newMetas [i ].Oid ].Size
176- newMetas [i ].RepositoryID = repoID
177- }
178- if err := db .Insert (ctx , newMetas ); err != nil {
179- return err
173+ newMetas := make ([]* LFSMetaObject , 0 , len (metas ))
174+ cond := builder .In (
175+ "`lfs_meta_object`.repository_id" ,
176+ builder .Select ("`repository`.id" ).From ("repository" ).Where (accessibleRepositoryCondition (user )),
177+ )
178+ err = sess .Cols ("oid" ).Where (cond ).In ("oid" , oids ... ).GroupBy ("oid" ).Find (& newMetas )
179+ if err != nil {
180+ return err
181+ }
182+ if len (newMetas ) != len (oidMap ) {
183+ return fmt .Errorf ("unable collect all LFS objects from database, expected %d, actually %d" , len (oidMap ), len (newMetas ))
184+ }
185+ for i := range newMetas {
186+ newMetas [i ].Size = oidMap [newMetas [i ].Oid ].Size
187+ newMetas [i ].RepositoryID = repoID
188+ }
189+ if err = db .Insert (ctx , newMetas ); err != nil {
190+ return err
191+ }
192+ } else {
193+ // admin can associate any LFS object to any repository, and we do not care about errors (eg: duplicated unique key),
194+ // even if error occurs, it won't hurt users and won't make things worse
195+ for i := range metas {
196+ _ , err = sess .Insert (& LFSMetaObject {
197+ Pointer : lfs.Pointer {Oid : metas [i ].Oid , Size : metas [i ].Size },
198+ RepositoryID : repoID ,
199+ })
200+ if err != nil {
201+ log .Warn ("failed to insert LFS meta object into database, err=%v" , err )
202+ }
203+ }
180204 }
181-
182205 return committer .Commit ()
183206}
184207
0 commit comments