in internal/gitaly/service/operations/commit_files.go [233:373]
func applyAction(
ctx context.Context,
action commitAction,
root *localrepo.TreeEntry,
repo *localrepo.Repo,
) error {
switch action := action.(type) {
case changeFileMode:
if err := root.Modify(
action.Path,
func(entry *localrepo.TreeEntry) error {
if action.ExecutableMode {
if entry.Mode != "100755" {
entry.Mode = "100755"
}
} else {
if entry.Mode == "100755" {
entry.Mode = "100644"
}
}
return nil
}); err != nil {
return translateError(err, action.Path)
}
case updateFile:
if err := root.Modify(
action.Path,
func(entry *localrepo.TreeEntry) error {
entry.OID = git.ObjectID(action.OID)
return nil
}); err != nil {
return translateError(err, action.Path)
}
case moveFile:
entry, err := root.Get(action.Path)
if err != nil {
return translateError(err, action.Path)
}
if entry.Type != localrepo.Blob {
return indexError{
path: action.Path,
errorType: errFileNotFound,
}
}
mode := entry.Mode
if action.OID == "" {
action.OID = string(entry.OID)
}
if err := root.Delete(action.Path); err != nil {
return translateError(err, action.Path)
}
if err := root.Add(
action.NewPath,
localrepo.TreeEntry{
OID: git.ObjectID(action.OID),
Mode: mode,
Path: filepath.Base(action.NewPath),
},
localrepo.WithOverwriteDirectory(),
); err != nil {
return translateError(err, action.NewPath)
}
case createDirectory:
if entry, err := root.Get(action.Path); err != nil && !errors.Is(err, localrepo.ErrEntryNotFound) {
return translateError(err, action.Path)
} else if entry != nil {
switch entry.Type {
case localrepo.Tree, localrepo.Submodule:
return indexError{
path: action.Path,
errorType: errDirectoryExists,
}
default:
return indexError{
path: action.Path,
errorType: errFileExists,
}
}
}
blobID, err := repo.WriteBlob(ctx, strings.NewReader(""), localrepo.WriteBlobConfig{
Path: filepath.Join(action.Path, ".gitkeep"),
})
if err != nil {
return err
}
if err := root.Add(
filepath.Join(action.Path, ".gitkeep"),
localrepo.TreeEntry{
Mode: "100644",
Path: ".gitkeep",
Type: localrepo.Blob,
OID: blobID,
},
); err != nil {
if errors.Is(err, localrepo.ErrEntryExists) {
return indexError{
path: action.Path,
errorType: errDirectoryExists,
}
}
return translateError(err, action.Path)
}
case createFile:
mode := "100644"
if action.ExecutableMode {
mode = "100755"
}
if err := root.Add(
action.Path,
localrepo.TreeEntry{
OID: git.ObjectID(action.OID),
Path: filepath.Base(action.Path),
Type: localrepo.Blob,
Mode: mode,
},
localrepo.WithOverwriteDirectory(),
); err != nil {
return translateError(err, action.Path)
}
case deleteFile:
if err := root.Delete(
action.Path,
); err != nil {
return translateError(err, action.Path)
}
default:
return errors.New("unsupported action")
}
return nil
}