Browse Source

#1773

speed up hhh~
tags/v1.22.5.1^2
open_test 3 years ago
parent
commit
761bba0ca0
2 changed files with 100 additions and 174 deletions
  1. +28
    -0
      modules/repofiles/temp_repo.go
  2. +72
    -174
      modules/repofiles/update.go

+ 28
- 0
modules/repofiles/temp_repo.go View File

@@ -109,6 +109,34 @@ func (t *TemporaryUploadRepository) LsFiles(filenames ...string) ([]string, erro
return filelist, nil
}

// LsFilesStage list all files with stage format in index for the given paths
// if the given path is directory ,then return all files under it
// if the given path is file ,then return the file
func (t *TemporaryUploadRepository) LsFilesStage(paths ...string) ([]string, error) {
stdOut := new(bytes.Buffer)
stdErr := new(bytes.Buffer)

cmdArgs := []string{"ls-files", "-z", "-s", "--"}
for _, arg := range paths {
if arg != "" {
cmdArgs = append(cmdArgs, arg)
}
}

if err := git.NewCommand(cmdArgs...).RunInDirPipeline(t.basePath, stdOut, stdErr); err != nil {
log.Error("Unable to run git ls-files for temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String())
err = fmt.Errorf("Unable to run git ls-files for temporary repo of: %s Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
return nil, err
}

filelist := make([]string, 0)
for _, line := range bytes.Split(stdOut.Bytes(), []byte{'\000'}) {
filelist = append(filelist, string(line))
}

return filelist, nil
}

// RemoveFilesFromIndex removes the given files from the index
func (t *TemporaryUploadRepository) RemoveFilesFromIndex(filenames ...string) error {
stdOut := new(bytes.Buffer)


+ 72
- 174
modules/repofiles/update.go View File

@@ -9,7 +9,6 @@ import (
"container/list"
"fmt"
"path"
"regexp"
"strings"
"time"

@@ -777,39 +776,10 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
return err
}

// A NewBranch can be specified for the file to be created/updated in a new branch.
// Check to make sure the branch does not already exist, otherwise we can't proceed.
// If we aren't branching to a new branch, make sure user can commit to the given branch
protectedBranch, err := repo.GetBranchProtection(opts.BranchName)
if err != nil {
//make sure user can commit to the given branch
if err := checkBranchProtection(doer, repo, opts.BranchName, opts.TreePath); err != nil {
return err
}
if protectedBranch != nil {
if !protectedBranch.CanUserPush(doer.ID) {
return models.ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
if protectedBranch.RequireSignedCommits {
_, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), opts.BranchName)
if err != nil {
if !models.IsErrWontSign(err) {
return err
}
return models.ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
}
patterns := protectedBranch.GetProtectedFilePatterns()
for _, pat := range patterns {
if pat.Match(strings.ToLower(opts.TreePath)) {
return models.ErrFilePathProtected{
Path: opts.TreePath,
}
}
}
}

// Check that the path given in opts.treePath is valid (not a git path)
treePath := CleanUploadFileName(opts.TreePath)
@@ -826,8 +796,6 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
}
}

message := strings.TrimSpace(opts.Message)

author, committer := GetAuthorAndCommitterUsers(opts.Author, opts.Committer, doer)

t, err := NewTemporaryUploadRepository(repo)
@@ -854,22 +822,20 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
}
opts.LastCommitID = lastCommitID.String()

//encoding := "UTF-8"
//bom := false
//executable := false

fromTreeEntry, err := commit.GetTreeEntryByPath(fromTreePath)
if err != nil {
return err
}
if opts.LastCommitID == "" {
// When updating a file, a lastCommitID or SHA needs to be given to make sure other commits
// When updating a file, a lastCommitID needs to be given to make sure other commits
// haven't been made. We throw an error if one wasn't provided.
return models.ErrSHAOrCommitIDNotProvided{}
}

//if fromTreePath not exist,return error
_, err = commit.GetTreeEntryByPath(fromTreePath)
if err != nil {
return err
}

// If a lastCommitID was given and it doesn't match the commitID of the head of the branch throw
// an error, but only if we aren't creating a new branch.
// an error.
if commit.ID.String() != opts.LastCommitID {
if changed, err := commit.FileChangedSinceCommit(fromTreePath, opts.LastCommitID); err != nil {
return err
@@ -879,11 +845,11 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
CurrentCommitID: opts.LastCommitID,
}
}
// The file wasn't modified, so we are good to delete it
}

entry, err := commit.GetTreeEntryByPath(treePath)
if err == nil || (!git.IsErrNotExist(err) && !entry.IsDir()) {
//if treePath has been exist,return error
_, err = commit.GetTreeEntryByPath(treePath)
if err == nil || !git.IsErrNotExist(err) {
// Means the file has been exist in new path
return models.ErrFilePathInvalid{
Message: fmt.Sprintf("a file exists where you’re trying to create a subdirectory [path: %s]", treePath),
@@ -893,18 +859,9 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
}
}

if fromTreeEntry.IsDir() {
tree, err := commit.Tree.SubTree(fromTreePath)
if err != nil {
return err
}
if err := moveAndAddDir(fromTreePath, treePath, opts.BranchName, tree, commit, t); err != nil {
return err
}
} else {
if err := moveAndAddFile(opts.FromTreePath, opts.TreePath, entry, t); err != nil {
return err
}
//move and add files to index
if err = moveAndAddFiles(fromTreePath, treePath, t); err != nil {
return err
}

// Now write the tree
@@ -914,6 +871,7 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
}

// Now commit the tree
message := strings.TrimSpace(opts.Message)
commitHash, err := t.CommitTree(author, committer, treeHash, message)
if err != nil {
return err
@@ -928,133 +886,73 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo
return nil
}

func moveAndAddDir(oldTreePath, newTreePath, branchName string, currentTree *git.Tree, currentBranchCommit *git.Commit, t *TemporaryUploadRepository) error {

//if _, err := git.NewCommand("checkout", branchName).RunInDir(t.basePath); err != nil {
// return fmt.Errorf("moveAndAddFile: %v", err)
//}
//获取oldTreePath的objectHash
//s, err := git.NewCommand("cat-file", "-p", fmt.Sprint(currentTree.ID)).RunInDir(t.basePath)
//if err != nil {
// return fmt.Errorf("moveAndAddFile: %v", err)
//}
//objectHash, err := t.HashObject(strings.NewReader(s))
objectHash := fmt.Sprint(currentTree.ID)

// Add the object to the index
if _, err := git.NewCommand("update-index", "--add", "--cacheinfo", "40000", objectHash, newTreePath).RunInDir(t.basePath); err != nil {
stderr := err.Error()
if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched {
return models.ErrFilePathInvalid{
Message: newTreePath,
Path: newTreePath,
func checkBranchProtection(doer *models.User, repo *models.Repository, branchName, treePath string) error {
//make sure user can commit to the given branch
protectedBranch, err := repo.GetBranchProtection(branchName)
if err != nil {
return err
}
if protectedBranch != nil {
if !protectedBranch.CanUserPush(doer.ID) {
return models.ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
log.Error("Unable to add object to index: %s %s %s in temporary repo %s(%s) Error: %v", "40000", objectHash, newTreePath, t.repo.FullName(), t.basePath, err)
return fmt.Errorf("Unable to add object to index at %s in temporary repo %s Error: %v", newTreePath, t.repo.FullName(), err)
}
//if err := t.AddObjectToIndex("40000", objectHash, newTreePath); err != nil {
// return err
//}
//entries, err := currentTree.ListEntries()
//if err != nil {
// return err
//}
//for _, v := range entries {
// tempNewPath := path.Join(newTreePath, v.Name())
// tempOldPath := path.Join(oldTreePath, v.Name())
// fromEntry, err := currentBranchCommit.GetTreeEntryByPath(tempOldPath)
// if err != nil {
// return err
// }
//
// //if v.IsDir() {
// // subTree, err := currentTree.SubTree(v.Name())
// // if err != nil {
// // return err
// // }
// // if err := moveAndAddDir(tempOldPath, tempNewPath, branchName, subTree, currentBranchCommit, t); err != nil {
// // return err
// // }
// //} else {
// if err := moveAndAddFile(tempOldPath, tempNewPath, fromEntry, t); err != nil {
// return err
// }
// //}
//
// //if v.IsDir() {
// // subTree, err := currentTree.SubTree(v.Name())
// // if err != nil {
// // return err
// // }
// // if err := moveAndAddDir(path.Join(oldTreePath, v.Name()), path.Join(newTreePath, v.Name()), lastCommitID, subTree, currentBranchCommit, t); err != nil {
// // return err
// // }
// //} else {
// // if err := moveAndAddFile(path.Join(oldTreePath, v.Name()), path.Join(newTreePath, v.Name()), lastCommitID, currentBranchCommit, t); err != nil {
// // return err
// // }
// //}
//}

if protectedBranch.RequireSignedCommits {
_, _, err := repo.SignCRUDAction(doer, repo.RepoPath(), branchName)
if err != nil {
if !models.IsErrWontSign(err) {
return err
}
return models.ErrUserCannotCommit{
UserName: doer.LowerName,
}
}
}
patterns := protectedBranch.GetProtectedFilePatterns()
for _, pat := range patterns {
if pat.Match(strings.ToLower(treePath)) {
return models.ErrFilePathProtected{
Path: treePath,
}
}
}
}
return nil
}

func moveAndAddFile(oldTreePath, newTreePath string, fromEntry *git.TreeEntry, t *TemporaryUploadRepository) error {
//if _, err := git.NewCommand("mv", oldTreePath, newTreePath).RunInDir(t.basePath); err != nil {
// return fmt.Errorf("moveAndAddFile: %v", err)
//}

executable := fromEntry.IsExecutable()
func moveAndAddFiles(oldTreePath, newTreePath string, t *TemporaryUploadRepository) error {
array, err := t.LsFilesStage(oldTreePath)
if err != nil {
return err
}
if len(array) == 0 {
return git.ErrNotExist{RelPath: oldTreePath}
}
stdOut := new(bytes.Buffer)
stdErr := new(bytes.Buffer)
stdIn := new(bytes.Buffer)
stdIn.WriteString("0 0000000000000000000000000000000000000000\t")
stdIn.WriteString(oldTreePath)
stdIn.WriteByte('\000')
for _, v := range array {
if v == "" {
continue
}
v = strings.ReplaceAll(v, "0\t", "")
tmpArray := strings.Split(v, " ")
oldPath := tmpArray[2]
newPath := newTreePath + strings.TrimPrefix(oldPath, oldTreePath)
stdIn.WriteString("0 0000000000000000000000000000000000000000\t")
stdIn.WriteString(oldPath)
stdIn.WriteByte('\000')
stdIn.WriteString(tmpArray[0] + " ")
stdIn.WriteString(tmpArray[1] + "\t")
stdIn.WriteString(newPath)
stdIn.WriteByte('\000')
}

if err := git.NewCommand("update-index", "--remove", "-z", "--index-info").RunInDirFullPipeline(t.basePath, stdOut, stdErr, stdIn); err != nil {
if err := git.NewCommand("update-index", "--replace", "-z", "--index-info").RunInDirFullPipeline(t.basePath, stdOut, stdErr, stdIn); err != nil {
log.Error("Unable to update-index for temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String())
return fmt.Errorf("Unable to update-index for temporary repo: %s Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
}
//
//if _, err := git.NewCommand("update-index", "--remove", "-z", "index-info", oldTreePath).RunInDir(t.basePath); err != nil {
// log.Error("Unable to update-index for temporary repo: %s (%s) Error: %v\n", t.repo.FullName(), t.basePath, err)
// return fmt.Errorf("Unable to update-index for temporary repo: %s Error: %v\n", t.repo.FullName(), err)
//}
//if err := t.RemoveFilesFromIndex(oldTreePath); err != nil {
// return err
//}

//获取oldTreePath的objectHash
objectHash := fmt.Sprint(fromEntry.Blob().ID)

// Add the object to the index
if fromEntry.IsDir() {
if _, err := git.NewCommand("update-index", "--add", "--cacheinfo", "40000", objectHash, newTreePath).RunInDir(t.basePath); err != nil {
stderr := err.Error()
if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched {
return models.ErrFilePathInvalid{
Message: newTreePath,
Path: newTreePath,
}
}
log.Error("Unable to add object to index: %s %s %s in temporary repo %s(%s) Error: %v", "40000", objectHash, newTreePath, t.repo.FullName(), t.basePath, err)
return fmt.Errorf("Unable to add object to index at %s in temporary repo %s Error: %v", newTreePath, t.repo.FullName(), err)
}
if err := t.AddObjectToIndex("40000", objectHash, newTreePath); err != nil {
return err
}
} else {
if executable {
if err := t.AddObjectToIndex("100755", objectHash, newTreePath); err != nil {
return err
}
} else {
if err := t.AddObjectToIndex("100644", objectHash, newTreePath); err != nil {
return err
}
}
}
return nil
}

Loading…
Cancel
Save