drone/gitrpc/operations.go

153 lines
4.3 KiB
Go

// Copyright 2023 Harness, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gitrpc
import (
"bytes"
"context"
"errors"
"io"
"time"
"github.com/harness/gitness/gitrpc/rpc"
)
type FileAction string
const (
CreateAction FileAction = "CREATE"
UpdateAction FileAction = "UPDATE"
DeleteAction = "DELETE"
MoveAction = "MOVE"
)
func (FileAction) Enum() []interface{} {
return []interface{}{CreateAction, UpdateAction, DeleteAction, MoveAction}
}
// CommitFileAction holds file operation data.
type CommitFileAction struct {
Action FileAction
Path string
Payload []byte
SHA string
}
// CommitFilesParams holds the data for file operations.
type CommitFilesParams struct {
WriteParams
Title string
Message string
Branch string
NewBranch string
Actions []CommitFileAction
// Committer overwrites the git committer used for committing the files
// (optional, default: actor)
Committer *Identity
// CommitterDate overwrites the git committer date used for committing the files
// (optional, default: current time on server)
CommitterDate *time.Time
// Author overwrites the git author used for committing the files
// (optional, default: committer)
Author *Identity
// AuthorDate overwrites the git author date used for committing the files
// (optional, default: committer date)
AuthorDate *time.Time
}
type CommitFilesResponse struct {
CommitID string
}
func (c *Client) CommitFiles(ctx context.Context, params *CommitFilesParams) (CommitFilesResponse, error) {
stream, err := c.commitFilesService.CommitFiles(ctx)
if err != nil {
return CommitFilesResponse{}, processRPCErrorf(err, "failed to open file stream")
}
if err = stream.Send(&rpc.CommitFilesRequest{
Payload: &rpc.CommitFilesRequest_Header{
Header: &rpc.CommitFilesRequestHeader{
Base: mapToRPCWriteRequest(params.WriteParams),
BranchName: params.Branch,
NewBranchName: params.NewBranch,
Title: params.Title,
Message: params.Message,
Author: mapToRPCIdentityOptional(params.Author),
AuthorDate: mapToRPCTimeOptional(params.AuthorDate),
Committer: mapToRPCIdentityOptional(params.Committer),
CommitterDate: mapToRPCTimeOptional(params.CommitterDate),
},
},
}); err != nil {
return CommitFilesResponse{}, processRPCErrorf(err, "failed to send file headers")
}
for _, action := range params.Actions {
// send headers
if err = stream.Send(&rpc.CommitFilesRequest{
Payload: &rpc.CommitFilesRequest_Action{
Action: &rpc.CommitFilesAction{
Payload: &rpc.CommitFilesAction_Header{
Header: &rpc.CommitFilesActionHeader{
Action: rpc.CommitFilesActionHeader_ActionType(
rpc.CommitFilesActionHeader_ActionType_value[string(action.Action)]),
Path: action.Path,
Sha: action.SHA,
},
},
},
},
}); err != nil {
return CommitFilesResponse{}, processRPCErrorf(err, "failed to send file action to the stream")
}
// send file content
buffer := make([]byte, FileTransferChunkSize)
reader := bytes.NewReader(action.Payload)
for {
n, err := reader.Read(buffer)
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return CommitFilesResponse{}, processRPCErrorf(err, "cannot read buffer")
}
if err = stream.Send(&rpc.CommitFilesRequest{
Payload: &rpc.CommitFilesRequest_Action{
Action: &rpc.CommitFilesAction{
Payload: &rpc.CommitFilesAction_Content{
Content: buffer[:n],
},
},
},
}); err != nil {
return CommitFilesResponse{}, processRPCErrorf(err, "failed to send file to the stream")
}
}
}
recv, err := stream.CloseAndRecv()
if err != nil {
return CommitFilesResponse{}, processRPCErrorf(err, "failed to close the stream")
}
return CommitFilesResponse{
CommitID: recv.CommitId,
}, nil
}