diff options
Diffstat (limited to 'internal/service/repository/rename.go')
-rw-r--r-- | internal/service/repository/rename.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/internal/service/repository/rename.go b/internal/service/repository/rename.go new file mode 100644 index 000000000..10bbee028 --- /dev/null +++ b/internal/service/repository/rename.go @@ -0,0 +1,57 @@ +package repository + +import ( + "context" + "errors" + "os" + "path/filepath" + + "gitlab.com/gitlab-org/gitaly/internal/helper" + "gitlab.com/gitlab-org/gitaly/proto/go/gitalypb" +) + +func (s *server) RenameRepository(ctx context.Context, in *gitalypb.RenameRepositoryRequest) (*gitalypb.RenameRepositoryResponse, error) { + if err := validateRenameRepositoryRequest(in); err != nil { + return nil, helper.ErrInvalidArgument(err) + } + + fromFullPath, err := helper.GetRepoPath(in.GetRepository()) + if err != nil { + return nil, helper.ErrInvalidArgument(err) + } + + toFullPath, err := helper.GetPath(&gitalypb.Repository{StorageName: in.GetRepository().GetStorageName(), RelativePath: in.GetRelativePath()}) + if err != nil { + return nil, helper.ErrInvalidArgument(err) + } + + if _, err = os.Stat(toFullPath); !os.IsNotExist(err) { + return nil, helper.ErrPreconditionFailed(errors.New("destination already exists")) + } + + if err = os.MkdirAll(filepath.Dir(toFullPath), 0755); err != nil { + return nil, helper.ErrInternal(err) + } + + if err = os.Rename(fromFullPath, toFullPath); err != nil { + return nil, helper.ErrInternal(err) + } + + return &gitalypb.RenameRepositoryResponse{}, nil +} + +func validateRenameRepositoryRequest(in *gitalypb.RenameRepositoryRequest) error { + if in.GetRepository() == nil { + return errors.New("from repository is empty") + } + + if in.GetRelativePath() == "" { + return errors.New("destination relative path is empty") + } + + if helper.ContainsPathTraversal(in.GetRelativePath()) { + return errors.New("relative_path contains path traversal") + } + + return nil +} |