From bc2e4421326d17c4ecd90aae8d7e5c9d34afeb98 Mon Sep 17 00:00:00 2001 From: open_test Date: Thu, 12 May 2022 11:12:17 +0800 Subject: [PATCH] update --- modules/repofiles/update.go | 240 +++++++++++++++++++++--------------- routers/repo/editor.go | 4 + 2 files changed, 143 insertions(+), 101 deletions(-) diff --git a/modules/repofiles/update.go b/modules/repofiles/update.go index 2449386bb..702cdc415 100644 --- a/modules/repofiles/update.go +++ b/modules/repofiles/update.go @@ -9,6 +9,7 @@ import ( "container/list" "fmt" "path" + "regexp" "strings" "time" @@ -866,17 +867,42 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo // haven't been made. We throw an error if one wasn't provided. return models.ErrSHAOrCommitIDNotProvided{} } - //获取 + + // 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. + if commit.ID.String() != opts.LastCommitID { + if changed, err := commit.FileChangedSinceCommit(fromTreePath, opts.LastCommitID); err != nil { + return err + } else if changed { + return models.ErrCommitIDDoesNotMatch{ + GivenCommitID: opts.LastCommitID, + 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()) { + // 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), + Path: treePath, + Name: treePath, + Type: git.EntryModeBlob, + } + } + if fromTreeEntry.IsDir() { tree, err := commit.Tree.SubTree(fromTreePath) if err != nil { return err } - if err := moveAndAddDir(fromTreePath, treePath, opts.LastCommitID, tree, commit, t); err != nil { + if err := moveAndAddDir(fromTreePath, treePath, opts.BranchName, tree, commit, t); err != nil { return err } } else { - if err := moveAndAddFile(opts.FromTreePath, opts.TreePath, opts.LastCommitID, commit, t); err != nil { + if err := moveAndAddFile(opts.FromTreePath, opts.TreePath, entry, t); err != nil { return err } } @@ -902,120 +928,132 @@ func RenameRepoFile(repo *models.Repository, doer *models.User, opts *RenameRepo return nil } -func moveAndAddDir(oldTreePath, newTreePath, lastCommitID string, currentTree *git.Tree, currentBranchCommit *git.Commit, t *TemporaryUploadRepository) error { - entries, err := currentTree.ListEntries() - if err != nil { - return err - } - for _, v := range entries { - 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 - } - } - } - return nil -} +func moveAndAddDir(oldTreePath, newTreePath, branchName string, currentTree *git.Tree, currentBranchCommit *git.Commit, t *TemporaryUploadRepository) error { -func moveAndAddFile(oldTreePath, newTreePath, lastCommitID string, currentBranchCommit *git.Commit, t *TemporaryUploadRepository) error { - fromEntry, err := currentBranchCommit.GetTreeEntryByPath(oldTreePath) - 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. - if currentBranchCommit.ID.String() != lastCommitID { - if changed, err := currentBranchCommit.FileChangedSinceCommit(oldTreePath, lastCommitID); err != nil { - return err - } else if changed { - return models.ErrCommitIDDoesNotMatch{ - GivenCommitID: lastCommitID, - CurrentCommitID: lastCommitID, - } - } - // The file wasn't modified, so we are good to delete it - } - executable := fromEntry.IsExecutable() + //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) - // For the path where this file will be created/updated, we need to make - // sure no parts of the path are existing files or links except for the last - // item in the path which is the file name, and that shouldn't exist IF it is - // a new file OR is being moved to a new path. - treePathParts := strings.Split(newTreePath, "/") - subTreePath := "" - for index, part := range treePathParts { - subTreePath = path.Join(subTreePath, part) - entry, err := currentBranchCommit.GetTreeEntryByPath(subTreePath) - if err != nil { - if git.IsErrNotExist(err) { - // Means there is no item with that name, so we're good - break - } - return err - } - if index < len(treePathParts)-1 { - if !entry.IsDir() { - return models.ErrFilePathInvalid{ - Message: fmt.Sprintf("a file exists where you’re trying to create a subdirectory [path: %s]", subTreePath), - Path: subTreePath, - Name: part, - Type: git.EntryModeBlob, - } - } - } else if entry.IsLink() { - return models.ErrFilePathInvalid{ - Message: fmt.Sprintf("a symbolic link exists where you’re trying to create a subdirectory [path: %s]", subTreePath), - Path: subTreePath, - Name: part, - Type: git.EntryModeSymlink, - } - } else if entry.IsDir() { + // 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: fmt.Sprintf("a directory exists where you’re trying to create a file [path: %s]", subTreePath), - Path: subTreePath, - Name: part, - Type: git.EntryModeTree, + 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 + //} + //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 + // // } + // //} + //} - } + return nil +} - // Get the two paths (might be the same if not moving) from the index if they exist - filesInIndex, err := t.LsFiles(newTreePath, oldTreePath) - if err != nil { - return fmt.Errorf("UpdateRepoFile: %v", err) - } +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) + //} - // Remove the old path from the tree - if len(filesInIndex) > 0 { - for _, file := range filesInIndex { - if file == oldTreePath { - if err := t.RemoveFilesFromIndex(oldTreePath); err != nil { - return err - } - } - } - } + executable := fromEntry.IsExecutable() + stdOut := new(bytes.Buffer) + stdErr := new(bytes.Buffer) + stdIn := new(bytes.Buffer) + stdIn.WriteString("0 0000000000000000000000000000000000000000\t") + stdIn.WriteString(oldTreePath) + stdIn.WriteByte('\000') + + if err := git.NewCommand("update-index", "--remove", "-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 executable { - if err := t.AddObjectToIndex("100755", objectHash, newTreePath); err != nil { + 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 err := t.AddObjectToIndex("100644", objectHash, newTreePath); err != nil { - return err + 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 diff --git a/routers/repo/editor.go b/routers/repo/editor.go index babc748bf..b389759f5 100644 --- a/routers/repo/editor.go +++ b/routers/repo/editor.go @@ -808,6 +808,10 @@ func renameFilePost(ctx *context.Context, form auth.RenameRepoFileForm) { ctx.JSON(http.StatusOK, response.ServerError("param error")) return } + if form.TreePath == ctx.Repo.TreePath { + ctx.JSON(http.StatusOK, response.Success()) + return + } canCommit := renderCommitRights(ctx) branchName := ctx.Repo.BranchName