1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
package client
import (
"context"
"io"
"gitlab.com/gitlab-org/gitaly/v16/internal/stream"
"gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"
"gitlab.com/gitlab-org/gitaly/v16/streamio"
"google.golang.org/grpc"
)
// UploadPack proxies an SSH git-upload-pack (git fetch) session to Gitaly
func UploadPack(ctx context.Context, conn *grpc.ClientConn, stdin io.Reader, stdout, stderr io.Writer, req *gitalypb.SSHUploadPackRequest) (int32, error) {
ctx2, cancel := context.WithCancel(ctx)
defer cancel()
ssh := gitalypb.NewSSHServiceClient(conn)
uploadPackStream, err := ssh.SSHUploadPack(ctx2)
if err != nil {
return 0, err
}
if err = uploadPackStream.Send(req); err != nil {
return 0, err
}
inWriter := streamio.NewWriter(func(p []byte) error {
return uploadPackStream.Send(&gitalypb.SSHUploadPackRequest{Stdin: p})
})
return stream.Handler(func() (stream.StdoutStderrResponse, error) {
return uploadPackStream.Recv()
}, func(errC chan error) {
_, errRecv := io.Copy(inWriter, stdin)
if err := uploadPackStream.CloseSend(); err != nil && errRecv == nil {
errC <- err
} else {
errC <- errRecv
}
}, stdout, stderr)
}
// UploadPackResult wraps ExitCode and PackfileNegotiationStatistics.
type UploadPackResult struct {
ExitCode int32
PackfileNegotiationStatistics *gitalypb.PackfileNegotiationStatistics
}
// UploadPackWithSidechannelWithResult proxies an SSH git-upload-pack (git fetch)
// session to Gitaly using a sidechannel for the raw data transfer.
func UploadPackWithSidechannelWithResult(
ctx context.Context,
conn *grpc.ClientConn,
reg *SidechannelRegistry,
stdin io.Reader,
stdout, stderr io.Writer,
req *gitalypb.SSHUploadPackWithSidechannelRequest,
) (UploadPackResult, error) {
result := UploadPackResult{}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
ctx, wt := reg.Register(ctx, func(c SidechannelConn) error {
return stream.ProxyPktLine(c, stdin, stdout, stderr)
})
defer func() {
// We aleady check the error further down.
_ = wt.Close()
}()
sshClient := gitalypb.NewSSHServiceClient(conn)
resp, err := sshClient.SSHUploadPackWithSidechannel(ctx, req)
if err != nil {
return result, err
}
result.ExitCode = 0
result.PackfileNegotiationStatistics = resp.PackfileNegotiationStatistics
if err := wt.Close(); err != nil {
return result, err
}
return result, nil
}
// UploadPackWithSidechannel proxies an SSH git-upload-pack (git fetch)
// session to Gitaly using a sidechannel for the raw data transfer.
// Deprecated: use UploadPackWithSidechannelWithResult instead.
func UploadPackWithSidechannel(
ctx context.Context,
conn *grpc.ClientConn,
reg *SidechannelRegistry,
stdin io.Reader,
stdout, stderr io.Writer,
req *gitalypb.SSHUploadPackWithSidechannelRequest,
) (int32, error) {
result, err := UploadPackWithSidechannelWithResult(ctx, conn, reg, stdin, stdout, stderr, req)
if err != nil {
return 0, err
}
return result.ExitCode, err
}
|