新增: 删除文件逻辑

This commit is contained in:
yystopf 2022-07-13 14:37:41 +08:00
parent 63ef5921d1
commit 60ce687fb5
1 changed files with 190 additions and 132 deletions

View File

@ -618,14 +618,72 @@ func CreateOrUpdateOrDeleteRepofiles(repo *models.Repository, doer *models.User,
opts.LastCommitID = lastCommitID.String()
}
encoding := "UTF-8"
bom := false
executable := false
if optActionType == ActionTypeDelete {
// Get the files in the index
filesInIndex, err := t.LsFiles(optTreePath)
if err != nil {
return nil, fmt.Errorf("DeleteRepoFile: %v", err)
}
// Find the file we want to delete in the index
inFilelist := false
for _, file := range filesInIndex {
if file == optTreePath {
inFilelist = true
break
}
}
if !inFilelist {
return nil, models.ErrRepoFileDoesNotExist{
Path: optTreePath,
}
}
// Get the entry of treePath and check if the SHA given is the same as the file
entry, err := commit.GetTreeEntryByPath(treePath)
if err != nil {
return nil, err
}
if opts.SHA != "" {
// If a SHA was given and the SHA given doesn't match the SHA of the fromTreePath, throw error
if opts.SHA != entry.ID.String() {
return nil, models.ErrSHADoesNotMatch{
Path: treePath,
GivenSHA: opts.SHA,
CurrentSHA: entry.ID.String(),
}
}
} else if opts.LastCommitID != "" {
// 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 && opts.OldBranch == opts.NewBranch {
// CommitIDs don't match, but we don't want to throw a ErrCommitIDDoesNotMatch unless
// this specific file has been edited since opts.LastCommitID
if changed, err := commit.FileChangedSinceCommit(treePath, opts.LastCommitID); err != nil {
return nil, err
} else if changed {
return nil, models.ErrCommitIDDoesNotMatch{
GivenCommitID: opts.LastCommitID,
CurrentCommitID: opts.LastCommitID,
}
}
// The file wasn't modified, so we are good to delete it
}
} else {
// When deleting a file, a lastCommitID or SHA needs to be given to make sure other commits haven't been
// made. We throw an error if one wasn't provided.
return nil, models.ErrSHAOrCommitIDNotProvided{}
}
// Remove the file from the index
if err := t.RemoveFilesFromIndex(optTreePath); err != nil {
return nil, err
}
} else {
encoding := "UTF-8"
bom := false
executable := false
switch optActionType {
case ActionTypeCreate:
case ActionTypeDelete:
default:
fromEntry, err := commit.GetTreeEntryByPath(fromTreePath)
if err != nil {
return nil, err
@ -654,127 +712,147 @@ func CreateOrUpdateOrDeleteRepofiles(repo *models.Repository, doer *models.User,
}
encoding, bom = detectEncodingAndBOM(fromEntry, repo)
executable = fromEntry.IsExecutable()
}
treePathParts := strings.Split(treePath, "/")
subTreePath := ""
for index, part := range treePathParts {
subTreePath = path.Join(subTreePath, part)
entry, err := commit.GetTreeEntryByPath(subTreePath)
if err != nil {
if git.IsErrNotExist(err) {
break
treePathParts := strings.Split(treePath, "/")
subTreePath := ""
for index, part := range treePathParts {
subTreePath = path.Join(subTreePath, part)
entry, err := commit.GetTreeEntryByPath(subTreePath)
if err != nil {
if git.IsErrNotExist(err) {
break
}
return nil, err
}
return nil, err
}
if index < len(treePathParts)-1 {
if !entry.IsDir() {
if index < len(treePathParts)-1 {
if !entry.IsDir() {
return nil, models.ErrFilePathInvalid{
Message: fmt.Sprintf("a file exists where youre trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
Type: git.EntryModeBlob,
}
}
} else if entry.IsLink() {
return nil, models.ErrFilePathInvalid{
Message: fmt.Sprintf("a file exists where youre trying to create a subdirectory [path: %s]", subTreePath),
Message: fmt.Sprintf("a symbolic link exists where youre trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
Type: git.EntryModeBlob,
Type: git.EntryModeSymlink,
}
}
} else if entry.IsLink() {
return nil, models.ErrFilePathInvalid{
Message: fmt.Sprintf("a symbolic link exists where youre trying to create a subdirectory [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
Type: git.EntryModeSymlink,
}
} else if entry.IsDir() {
return nil, models.ErrFilePathInvalid{
Message: fmt.Sprintf("a directory exists where youre trying to create a file [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
Type: git.EntryModeTree,
}
} else if fromTreePath != treePath || optActionType == ActionTypeCreate {
return nil, models.ErrRepoFileAlreadyExists{
Path: treePath,
}
}
}
// Get the two paths (might be the same if not moving) from the index if they exist
filesInIndex, err := t.LsFiles(optTreePath, optFromTreePath)
if err != nil {
return nil, fmt.Errorf("UpdateRepoFile: %v", err)
}
if optActionType == ActionTypeCreate {
for _, file := range filesInIndex {
if file == optTreePath {
} else if entry.IsDir() {
return nil, models.ErrFilePathInvalid{
Message: fmt.Sprintf("a directory exists where youre trying to create a file [path: %s]", subTreePath),
Path: subTreePath,
Name: part,
Type: git.EntryModeTree,
}
} else if fromTreePath != treePath || optActionType == ActionTypeCreate {
return nil, models.ErrRepoFileAlreadyExists{
Path: optTreePath,
Path: treePath,
}
}
}
}
// Get the two paths (might be the same if not moving) from the index if they exist
filesInIndex, err := t.LsFiles(optTreePath, optFromTreePath)
if err != nil {
return nil, fmt.Errorf("UpdateOrCreateRepoFile: %v", err)
}
// Remove the old path from the tree
if fromTreePath != treePath && len(filesInIndex) > 0 {
for _, file := range filesInIndex {
if file == fromTreePath {
if err := t.RemoveFilesFromIndex(optFromTreePath); err != nil {
if optActionType == ActionTypeCreate {
for _, file := range filesInIndex {
if file == optTreePath {
return nil, models.ErrRepoFileAlreadyExists{
Path: optTreePath,
}
}
}
}
// Remove the old path from the tree
if fromTreePath != treePath && len(filesInIndex) > 0 {
for _, file := range filesInIndex {
if file == fromTreePath {
if err := t.RemoveFilesFromIndex(optFromTreePath); err != nil {
return nil, err
}
}
}
}
content := optContent
if bom {
content = string(charset.UTF8BOM) + content
}
if encoding != "UTF-8" {
charsetEncoding, _ := stdcharset.Lookup(encoding)
if charsetEncoding != nil {
result, _, err := transform.String(charsetEncoding.NewEncoder(), content)
if err != nil {
log.Error("Error re-encoding %s (%s) as %s - will stay as UTF-8: %v", optTreePath, optFromTreePath, encoding, err)
result = content
}
content = result
} else {
log.Error("Unknown encoding: %s", encoding)
}
}
optContent = content
var lfsMetaObject *models.LFSMetaObject
if setting.LFS.StartServer {
filename2attribute2info, err := t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
Attributes: []string{"filter"},
Filenames: []string{treePath},
})
if err != nil {
return nil, err
}
if filename2attribute2info[treePath] != nil && filename2attribute2info[treePath]["filter"] == "lfs" {
pointer, err := lfs.GeneratePointer(strings.NewReader(optContent))
if err != nil {
return nil, err
}
lfsMetaObject = &models.LFSMetaObject{Pointer: pointer, RepositoryID: repo.ID}
content = pointer.StringContent()
}
}
objectHash, err := t.HashObject(strings.NewReader(content))
if err != nil {
return nil, err
}
if executable {
if err := t.AddObjectToIndex("100755", objectHash, treePath); err != nil {
return nil, err
}
} else {
if err := t.AddObjectToIndex("100644", objectHash, treePath); err != nil {
return nil, err
}
}
if lfsMetaObject != nil {
lfsMetaObject, err = models.NewLFSMetaObject(lfsMetaObject)
if err != nil {
return nil, err
}
contentStore := lfs.NewContentStore()
exist, err := contentStore.Exists(lfsMetaObject.Pointer)
if err != nil {
return nil, err
}
if !exist {
if err := contentStore.Put(lfsMetaObject.Pointer, strings.NewReader(optContent)); err != nil {
if _, err2 := repo.RemoveLFSMetaObjectByOid(lfsMetaObject.Oid); err2 != nil {
return nil, fmt.Errorf("Error whilst removing failed inserted LFS object %s: %v (Prev Error: %v)", lfsMetaObject.Oid, err2, err)
}
return nil, err
}
}
}
}
content := optContent
if bom {
content = string(charset.UTF8BOM) + content
}
if encoding != "UTF-8" {
charsetEncoding, _ := stdcharset.Lookup(encoding)
if charsetEncoding != nil {
result, _, err := transform.String(charsetEncoding.NewEncoder(), content)
if err != nil {
log.Error("Error re-encoding %s (%s) as %s - will stay as UTF-8: %v", optTreePath, optFromTreePath, encoding, err)
result = content
}
content = result
} else {
log.Error("Unknown encoding: %s", encoding)
}
}
optContent = content
var lfsMetaObject *models.LFSMetaObject
if setting.LFS.StartServer {
filename2attribute2info, err := t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
Attributes: []string{"filter"},
Filenames: []string{treePath},
})
if err != nil {
return nil, err
}
if filename2attribute2info[treePath] != nil && filename2attribute2info[treePath]["filter"] == "lfs" {
pointer, err := lfs.GeneratePointer(strings.NewReader(optContent))
if err != nil {
return nil, err
}
lfsMetaObject = &models.LFSMetaObject{Pointer: pointer, RepositoryID: repo.ID}
content = pointer.StringContent()
}
}
objectHash, err := t.HashObject(strings.NewReader(content))
if err != nil {
return nil, err
}
if executable {
if err := t.AddObjectToIndex("100755", objectHash, treePath); err != nil {
return nil, err
}
} else {
if err := t.AddObjectToIndex("100644", objectHash, treePath); err != nil {
return nil, err
}
}
treeHash, err := t.WriteTree()
@ -793,26 +871,6 @@ func CreateOrUpdateOrDeleteRepofiles(repo *models.Repository, doer *models.User,
return nil, err
}
if lfsMetaObject != nil {
lfsMetaObject, err = models.NewLFSMetaObject(lfsMetaObject)
if err != nil {
return nil, err
}
contentStore := lfs.NewContentStore()
exist, err := contentStore.Exists(lfsMetaObject.Pointer)
if err != nil {
return nil, err
}
if !exist {
if err := contentStore.Put(lfsMetaObject.Pointer, strings.NewReader(optContent)); err != nil {
if _, err2 := repo.RemoveLFSMetaObjectByOid(lfsMetaObject.Oid); err2 != nil {
return nil, fmt.Errorf("Error whilst removing failed inserted LFS object %s: %v (Prev Error: %v)", lfsMetaObject.Oid, err2, err)
}
return nil, err
}
}
}
if err := t.Push(doer, commitHash, opts.NewBranch); err != nil {
log.Error("%T %v", err, err)
return nil, err