新增: 删除文件逻辑
This commit is contained in:
parent
63ef5921d1
commit
60ce687fb5
|
@ -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 you’re 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 you’re trying to create a subdirectory [path: %s]", subTreePath),
|
||||
Message: fmt.Sprintf("a symbolic link exists where you’re 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 you’re 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 you’re 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 you’re 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
|
||||
|
|
Loading…
Reference in New Issue