1package smarthttp 2 3import ( 4 "context" 5 "fmt" 6 "io" 7 8 "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" 9 log "github.com/sirupsen/logrus" 10 "gitlab.com/gitlab-org/gitaly/v14/internal/git" 11 "gitlab.com/gitlab-org/gitaly/v14/internal/git/pktline" 12 "gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb" 13 "gitlab.com/gitlab-org/gitaly/v14/streamio" 14 "google.golang.org/grpc/codes" 15 "google.golang.org/grpc/status" 16) 17 18const ( 19 uploadPackSvc = "upload-pack" 20 receivePackSvc = "receive-pack" 21) 22 23func (s *server) InfoRefsUploadPack(in *gitalypb.InfoRefsRequest, stream gitalypb.SmartHTTPService_InfoRefsUploadPackServer) error { 24 repoPath, err := s.locator.GetRepoPath(in.GetRepository()) 25 if err != nil { 26 return err 27 } 28 29 w := streamio.NewWriter(func(p []byte) error { 30 return stream.Send(&gitalypb.InfoRefsResponse{Data: p}) 31 }) 32 33 return s.infoRefCache.tryCache(stream.Context(), in, w, func(w io.Writer) error { 34 return s.handleInfoRefs(stream.Context(), uploadPackSvc, repoPath, in, w) 35 }) 36} 37 38func (s *server) InfoRefsReceivePack(in *gitalypb.InfoRefsRequest, stream gitalypb.SmartHTTPService_InfoRefsReceivePackServer) error { 39 repoPath, err := s.locator.GetRepoPath(in.GetRepository()) 40 if err != nil { 41 return err 42 } 43 w := streamio.NewWriter(func(p []byte) error { 44 return stream.Send(&gitalypb.InfoRefsResponse{Data: p}) 45 }) 46 return s.handleInfoRefs(stream.Context(), receivePackSvc, repoPath, in, w) 47} 48 49func (s *server) handleInfoRefs(ctx context.Context, service, repoPath string, req *gitalypb.InfoRefsRequest, w io.Writer) error { 50 ctxlogrus.Extract(ctx).WithFields(log.Fields{ 51 "service": service, 52 }).Debug("handleInfoRefs") 53 54 cmdOpts := []git.CmdOpt{git.WithGitProtocol(ctx, req)} 55 if service == "receive-pack" { 56 cmdOpts = append(cmdOpts, git.WithRefTxHook(ctx, req.Repository, s.cfg)) 57 } 58 59 config, err := git.ConvertConfigOptions(req.GitConfigOptions) 60 if err != nil { 61 return err 62 } 63 cmdOpts = append(cmdOpts, git.WithConfig(config...)) 64 65 cmd, err := s.gitCmdFactory.NewWithoutRepo(ctx, git.SubCmd{ 66 Name: service, 67 Flags: []git.Option{git.Flag{Name: "--stateless-rpc"}, git.Flag{Name: "--advertise-refs"}}, 68 Args: []string{repoPath}, 69 }, cmdOpts...) 70 if err != nil { 71 if _, ok := status.FromError(err); ok { 72 return err 73 } 74 return status.Errorf(codes.Internal, "GetInfoRefs: cmd: %v", err) 75 } 76 77 if _, err := pktline.WriteString(w, fmt.Sprintf("# service=git-%s\n", service)); err != nil { 78 return status.Errorf(codes.Internal, "GetInfoRefs: pktLine: %v", err) 79 } 80 81 if err := pktline.WriteFlush(w); err != nil { 82 return status.Errorf(codes.Internal, "GetInfoRefs: pktFlush: %v", err) 83 } 84 85 if _, err := io.Copy(w, cmd); err != nil { 86 return status.Errorf(codes.Internal, "GetInfoRefs: %v", err) 87 } 88 89 if err := cmd.Wait(); err != nil { 90 return status.Errorf(codes.Internal, "GetInfoRefs: %v", err) 91 } 92 93 return nil 94} 95