Add basic repository lfs management (#7199)

This PR adds basic repository LFS management UI including the ability to find all possible pointers within the repository. Locks are not managed at present but would be addable through some simple additions.

* Add basic repository lfs management
* add auto-associate function
* Add functionality to find commits with this lfs file
* Add link to find commits on the lfs file view
* Adjust commit view to state the likely branch causing the commit
* Only read Oid from database
This commit is contained in:
zeripath 2019-10-28 18:31:55 +00:00 committed by GitHub
parent af8957bc4c
commit 5e6a008fba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 1151 additions and 137 deletions

View file

@ -8,6 +8,8 @@ import (
"io"
"code.gitea.io/gitea/modules/timeutil"
"xorm.io/builder"
)
// LFSMetaObject stores metadata for LFS tracked files.
@ -106,19 +108,91 @@ func (repo *Repository) GetLFSMetaObjectByOid(oid string) (*LFSMetaObject, error
// RemoveLFSMetaObjectByOid removes a LFSMetaObject entry from database by its OID.
// It may return ErrLFSObjectNotExist or a database error.
func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) error {
func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) (int64, error) {
if len(oid) == 0 {
return ErrLFSObjectNotExist
return 0, ErrLFSObjectNotExist
}
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return -1, err
}
m := &LFSMetaObject{Oid: oid, RepositoryID: repo.ID}
if _, err := sess.Delete(m); err != nil {
return -1, err
}
count, err := sess.Count(&LFSMetaObject{Oid: oid})
if err != nil {
return count, err
}
return count, sess.Commit()
}
// GetLFSMetaObjects returns all LFSMetaObjects associated with a repository
func (repo *Repository) GetLFSMetaObjects(page, pageSize int) ([]*LFSMetaObject, error) {
sess := x.NewSession()
defer sess.Close()
if page >= 0 && pageSize > 0 {
start := 0
if page > 0 {
start = (page - 1) * pageSize
}
sess.Limit(pageSize, start)
}
lfsObjects := make([]*LFSMetaObject, 0, pageSize)
return lfsObjects, sess.Find(&lfsObjects, &LFSMetaObject{RepositoryID: repo.ID})
}
// CountLFSMetaObjects returns a count of all LFSMetaObjects associated with a repository
func (repo *Repository) CountLFSMetaObjects() (int64, error) {
return x.Count(&LFSMetaObject{RepositoryID: repo.ID})
}
// LFSObjectAccessible checks if a provided Oid is accessible to the user
func LFSObjectAccessible(user *User, oid string) (bool, error) {
if user.IsAdmin {
count, err := x.Count(&LFSMetaObject{Oid: oid})
return (count > 0), err
}
cond := accessibleRepositoryCondition(user.ID)
count, err := x.Where(cond).Join("INNER", "repository", "`lfs_meta_object`.repository_id = `repository`.id").Count(&LFSMetaObject{Oid: oid})
return (count > 0), err
}
// LFSAutoAssociate auto associates accessible LFSMetaObjects
func LFSAutoAssociate(metas []*LFSMetaObject, user *User, repoID int64) error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
m := &LFSMetaObject{Oid: oid, RepositoryID: repo.ID}
if _, err := sess.Delete(m); err != nil {
oids := make([]interface{}, len(metas))
oidMap := make(map[string]*LFSMetaObject, len(metas))
for i, meta := range metas {
oids[i] = meta.Oid
oidMap[meta.Oid] = meta
}
cond := builder.NewCond()
if !user.IsAdmin {
cond = builder.In("`lfs_meta_object`.repository_id",
builder.Select("`repository`.id").From("repository").Where(accessibleRepositoryCondition(user.ID)))
}
newMetas := make([]*LFSMetaObject, 0, len(metas))
if err := sess.Cols("oid").Where(cond).In("oid", oids...).GroupBy("oid").Find(&newMetas); err != nil {
return err
}
for i := range newMetas {
newMetas[i].Size = oidMap[newMetas[i].Oid].Size
newMetas[i].RepositoryID = repoID
}
if _, err := sess.InsertMulti(newMetas); err != nil {
return err
}