diff options
Diffstat (limited to 'routers/repo/lfs.go')
-rw-r--r-- | routers/repo/lfs.go | 210 |
1 files changed, 74 insertions, 136 deletions
diff --git a/routers/repo/lfs.go b/routers/repo/lfs.go index 07d36d67ec..457ffb6aba 100644 --- a/routers/repo/lfs.go +++ b/routers/repo/lfs.go @@ -5,7 +5,6 @@ package repo import ( - "bufio" "bytes" "fmt" gotemplate "html/template" @@ -15,7 +14,6 @@ import ( "path" "strconv" "strings" - "sync" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/base" @@ -266,7 +264,7 @@ func LFSFileGet(ctx *context.Context) { return } ctx.Data["LFSFile"] = meta - dataRc, err := lfs.ReadMetaObject(meta) + dataRc, err := lfs.ReadMetaObject(meta.Pointer) if err != nil { ctx.ServerError("LFSFileGet", err) return @@ -385,9 +383,8 @@ func LFSFileFind(ctx *context.Context) { ctx.Data["PageIsSettingsLFS"] = true var hash git.SHA1 if len(sha) == 0 { - meta := models.LFSMetaObject{Oid: oid, Size: size} - pointer := meta.Pointer() - hash = git.ComputeBlobHash([]byte(pointer)) + pointer := lfs.Pointer{Oid: oid, Size: size} + hash = git.ComputeBlobHash([]byte(pointer.StringContent())) sha = hash.String() } else { hash = git.MustIDFromString(sha) @@ -421,158 +418,99 @@ func LFSPointerFiles(ctx *context.Context) { } ctx.Data["LFSFilesLink"] = ctx.Repo.RepoLink + "/settings/lfs" - basePath := ctx.Repo.Repository.RepoPath() + err = func() error { + pointerChan := make(chan lfs.PointerBlob) + errChan := make(chan error, 1) + go lfs.SearchPointerBlobs(ctx.Req.Context(), ctx.Repo.GitRepo, pointerChan, errChan) + + numPointers := 0 + var numAssociated, numNoExist, numAssociatable int + + type pointerResult struct { + SHA string + Oid string + Size int64 + InRepo bool + Exists bool + Accessible bool + } + + results := []pointerResult{} - pointerChan := make(chan pointerResult) + contentStore := lfs.NewContentStore() + repo := ctx.Repo.Repository - catFileCheckReader, catFileCheckWriter := io.Pipe() - shasToBatchReader, shasToBatchWriter := io.Pipe() - catFileBatchReader, catFileBatchWriter := io.Pipe() - errChan := make(chan error, 1) - wg := sync.WaitGroup{} - wg.Add(5) + for pointerBlob := range pointerChan { + numPointers++ + + result := pointerResult{ + SHA: pointerBlob.Hash, + Oid: pointerBlob.Oid, + Size: pointerBlob.Size, + } - var numPointers, numAssociated, numNoExist, numAssociatable int + if _, err := repo.GetLFSMetaObjectByOid(pointerBlob.Oid); err != nil { + if err != models.ErrLFSObjectNotExist { + return err + } + } else { + result.InRepo = true + } - go func() { - defer wg.Done() - pointers := make([]pointerResult, 0, 50) - for pointer := range pointerChan { - pointers = append(pointers, pointer) - if pointer.InRepo { + result.Exists, err = contentStore.Exists(pointerBlob.Pointer) + if err != nil { + return err + } + + if result.Exists { + if !result.InRepo { + // Can we fix? + // OK well that's "simple" + // - we need to check whether current user has access to a repo that has access to the file + result.Accessible, err = models.LFSObjectAccessible(ctx.User, pointerBlob.Oid) + if err != nil { + return err + } + } else { + result.Accessible = true + } + } + + if result.InRepo { numAssociated++ } - if !pointer.Exists { + if !result.Exists { numNoExist++ } - if !pointer.InRepo && pointer.Accessible { + if !result.InRepo && result.Accessible { numAssociatable++ } + + results = append(results, result) + } + + err, has := <-errChan + if has { + return err } - numPointers = len(pointers) - ctx.Data["Pointers"] = pointers + + ctx.Data["Pointers"] = results ctx.Data["NumPointers"] = numPointers ctx.Data["NumAssociated"] = numAssociated ctx.Data["NumAssociatable"] = numAssociatable ctx.Data["NumNoExist"] = numNoExist ctx.Data["NumNotAssociated"] = numPointers - numAssociated + + return nil }() - go createPointerResultsFromCatFileBatch(catFileBatchReader, &wg, pointerChan, ctx.Repo.Repository, ctx.User) - go pipeline.CatFileBatch(shasToBatchReader, catFileBatchWriter, &wg, basePath) - go pipeline.BlobsLessThan1024FromCatFileBatchCheck(catFileCheckReader, shasToBatchWriter, &wg) - if git.CheckGitVersionAtLeast("2.6.0") != nil { - revListReader, revListWriter := io.Pipe() - shasToCheckReader, shasToCheckWriter := io.Pipe() - wg.Add(2) - go pipeline.CatFileBatchCheck(shasToCheckReader, catFileCheckWriter, &wg, basePath) - go pipeline.BlobsFromRevListObjects(revListReader, shasToCheckWriter, &wg) - go pipeline.RevListAllObjects(revListWriter, &wg, basePath, errChan) - } else { - go pipeline.CatFileBatchCheckAllObjects(catFileCheckWriter, &wg, basePath, errChan) + if err != nil { + ctx.ServerError("LFSPointerFiles", err) + return } - wg.Wait() - select { - case err, has := <-errChan: - if has { - ctx.ServerError("LFSPointerFiles", err) - } - default: - } ctx.HTML(http.StatusOK, tplSettingsLFSPointers) } -type pointerResult struct { - SHA string - Oid string - Size int64 - InRepo bool - Exists bool - Accessible bool -} - -func createPointerResultsFromCatFileBatch(catFileBatchReader *io.PipeReader, wg *sync.WaitGroup, pointerChan chan<- pointerResult, repo *models.Repository, user *models.User) { - defer wg.Done() - defer catFileBatchReader.Close() - contentStore := lfs.ContentStore{ObjectStorage: storage.LFS} - - bufferedReader := bufio.NewReader(catFileBatchReader) - buf := make([]byte, 1025) - for { - // File descriptor line: sha - sha, err := bufferedReader.ReadString(' ') - if err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - // Throw away the blob - if _, err := bufferedReader.ReadString(' '); err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - sizeStr, err := bufferedReader.ReadString('\n') - if err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - size, err := strconv.Atoi(sizeStr[:len(sizeStr)-1]) - if err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - pointerBuf := buf[:size+1] - if _, err := io.ReadFull(bufferedReader, pointerBuf); err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - pointerBuf = pointerBuf[:size] - // Now we need to check if the pointerBuf is an LFS pointer - pointer := lfs.IsPointerFile(&pointerBuf) - if pointer == nil { - continue - } - - result := pointerResult{ - SHA: strings.TrimSpace(sha), - Oid: pointer.Oid, - Size: pointer.Size, - } - - // Then we need to check that this pointer is in the db - if _, err := repo.GetLFSMetaObjectByOid(pointer.Oid); err != nil { - if err != models.ErrLFSObjectNotExist { - _ = catFileBatchReader.CloseWithError(err) - break - } - } else { - result.InRepo = true - } - - result.Exists, err = contentStore.Exists(pointer) - if err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - - if result.Exists { - if !result.InRepo { - // Can we fix? - // OK well that's "simple" - // - we need to check whether current user has access to a repo that has access to the file - result.Accessible, err = models.LFSObjectAccessible(user, result.Oid) - if err != nil { - _ = catFileBatchReader.CloseWithError(err) - break - } - } else { - result.Accessible = true - } - } - pointerChan <- result - } - close(pointerChan) -} - // LFSAutoAssociate auto associates accessible lfs files func LFSAutoAssociate(ctx *context.Context) { if !setting.LFS.StartServer { |