aboutsummaryrefslogtreecommitdiffstats
path: root/models/git/lfs_lock.go
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2022-06-12 23:51:54 +0800
committerGitHub <noreply@github.com>2022-06-12 23:51:54 +0800
commit110fc57cbcf293c19ed7017d8ea528b4bbbd7396 (patch)
treeb36eb2ee0e3f8417a35ad095e25880b778ded0ba /models/git/lfs_lock.go
parenta9dc9b06e4a4106ec8315fe7b2922efa440ca199 (diff)
downloadgitea-110fc57cbcf293c19ed7017d8ea528b4bbbd7396.tar.gz
gitea-110fc57cbcf293c19ed7017d8ea528b4bbbd7396.zip
Move some code into models/git (#19879)
* Move access and repo permission to models/perm/access * fix test * Move some git related files into sub package models/git * Fix build * fix git test * move lfs to sub package * move more git related functions to models/git * Move functions sequence * Some improvements per @KN4CK3R and @delvh
Diffstat (limited to 'models/git/lfs_lock.go')
-rw-r--r--models/git/lfs_lock.go183
1 files changed, 183 insertions, 0 deletions
diff --git a/models/git/lfs_lock.go b/models/git/lfs_lock.go
new file mode 100644
index 0000000000..016db899a9
--- /dev/null
+++ b/models/git/lfs_lock.go
@@ -0,0 +1,183 @@
+// Copyright 2017 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package git
+
+import (
+ "context"
+ "fmt"
+ "path"
+ "strings"
+ "time"
+
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/perm"
+ access_model "code.gitea.io/gitea/models/perm/access"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// LFSLock represents a git lfs lock of repository.
+type LFSLock struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"INDEX NOT NULL"`
+ OwnerID int64 `xorm:"INDEX NOT NULL"`
+ Path string `xorm:"TEXT"`
+ Created time.Time `xorm:"created"`
+}
+
+func init() {
+ db.RegisterModel(new(LFSLock))
+}
+
+// BeforeInsert is invoked from XORM before inserting an object of this type.
+func (l *LFSLock) BeforeInsert() {
+ l.Path = cleanPath(l.Path)
+}
+
+func cleanPath(p string) string {
+ return path.Clean("/" + p)[1:]
+}
+
+// CreateLFSLock creates a new lock.
+func CreateLFSLock(repo *repo_model.Repository, lock *LFSLock) (*LFSLock, error) {
+ dbCtx, committer, err := db.TxContext()
+ if err != nil {
+ return nil, err
+ }
+ defer committer.Close()
+
+ if err := CheckLFSAccessForRepo(dbCtx, lock.OwnerID, repo, perm.AccessModeWrite); err != nil {
+ return nil, err
+ }
+
+ lock.Path = cleanPath(lock.Path)
+ lock.RepoID = repo.ID
+
+ l, err := GetLFSLock(dbCtx, repo, lock.Path)
+ if err == nil {
+ return l, ErrLFSLockAlreadyExist{lock.RepoID, lock.Path}
+ }
+ if !IsErrLFSLockNotExist(err) {
+ return nil, err
+ }
+
+ if err := db.Insert(dbCtx, lock); err != nil {
+ return nil, err
+ }
+
+ return lock, committer.Commit()
+}
+
+// GetLFSLock returns release by given path.
+func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
+ path = cleanPath(path)
+ rel := &LFSLock{RepoID: repo.ID}
+ has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
+ if err != nil {
+ return nil, err
+ }
+ if !has {
+ return nil, ErrLFSLockNotExist{0, repo.ID, path}
+ }
+ return rel, nil
+}
+
+// GetLFSLockByID returns release by given id.
+func GetLFSLockByID(ctx context.Context, id int64) (*LFSLock, error) {
+ lock := new(LFSLock)
+ has, err := db.GetEngine(ctx).ID(id).Get(lock)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrLFSLockNotExist{id, 0, ""}
+ }
+ return lock, nil
+}
+
+// GetLFSLockByRepoID returns a list of locks of repository.
+func GetLFSLockByRepoID(repoID int64, page, pageSize int) ([]*LFSLock, error) {
+ e := db.GetEngine(db.DefaultContext)
+ if page >= 0 && pageSize > 0 {
+ start := 0
+ if page > 0 {
+ start = (page - 1) * pageSize
+ }
+ e.Limit(pageSize, start)
+ }
+ lfsLocks := make([]*LFSLock, 0, pageSize)
+ return lfsLocks, e.Find(&lfsLocks, &LFSLock{RepoID: repoID})
+}
+
+// GetTreePathLock returns LSF lock for the treePath
+func GetTreePathLock(repoID int64, treePath string) (*LFSLock, error) {
+ if !setting.LFS.StartServer {
+ return nil, nil
+ }
+
+ locks, err := GetLFSLockByRepoID(repoID, 0, 0)
+ if err != nil {
+ return nil, err
+ }
+ for _, lock := range locks {
+ if lock.Path == treePath {
+ return lock, nil
+ }
+ }
+ return nil, nil
+}
+
+// CountLFSLockByRepoID returns a count of all LFSLocks associated with a repository.
+func CountLFSLockByRepoID(repoID int64) (int64, error) {
+ return db.GetEngine(db.DefaultContext).Count(&LFSLock{RepoID: repoID})
+}
+
+// DeleteLFSLockByID deletes a lock by given ID.
+func DeleteLFSLockByID(id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
+ dbCtx, committer, err := db.TxContext()
+ if err != nil {
+ return nil, err
+ }
+ defer committer.Close()
+
+ lock, err := GetLFSLockByID(dbCtx, id)
+ if err != nil {
+ return nil, err
+ }
+
+ if err := CheckLFSAccessForRepo(dbCtx, u.ID, repo, perm.AccessModeWrite); err != nil {
+ return nil, err
+ }
+
+ if !force && u.ID != lock.OwnerID {
+ return nil, fmt.Errorf("user doesn't own lock and force flag is not set")
+ }
+
+ if _, err := db.GetEngine(dbCtx).ID(id).Delete(new(LFSLock)); err != nil {
+ return nil, err
+ }
+
+ return lock, committer.Commit()
+}
+
+// CheckLFSAccessForRepo check needed access mode base on action
+func CheckLFSAccessForRepo(ctx context.Context, ownerID int64, repo *repo_model.Repository, mode perm.AccessMode) error {
+ if ownerID == 0 {
+ return ErrLFSUnauthorizedAction{repo.ID, "undefined", mode}
+ }
+ u, err := user_model.GetUserByIDCtx(ctx, ownerID)
+ if err != nil {
+ return err
+ }
+ perm, err := access_model.GetUserRepoPermission(ctx, repo, u)
+ if err != nil {
+ return err
+ }
+ if !perm.CanAccess(mode, unit.TypeCode) {
+ return ErrLFSUnauthorizedAction{repo.ID, u.DisplayName(), mode}
+ }
+ return nil
+}