func applyAction()

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
}