Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2021-02-12 09:54:57 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-02-12 13:38:08 +0300
commitb9aabc183bd4a6aa42732e24dbb7b662f9edda66 (patch)
treea4de16efb508de3d0066b694e14566b2157a9554 /cmd/gitaly-hooks
parentcebe1d983e22fb5a3b95b3be7600883a1d37b7ee (diff)
gitaly-hooks: Pull hook logic into their own functions
By now, we support five different hooks with non-trivial logic, but they're all open-coded in the statement switching over the subcommand. This makes it rather hard to refactor and extend the code, so this commit moves the logic into per-hook functions. No functional changes are expected from this commit.
Diffstat (limited to 'cmd/gitaly-hooks')
-rw-r--r--cmd/gitaly-hooks/hooks.go275
1 files changed, 155 insertions, 120 deletions
diff --git a/cmd/gitaly-hooks/hooks.go b/cmd/gitaly-hooks/hooks.go
index 416936a22..d2663b109 100644
--- a/cmd/gitaly-hooks/hooks.go
+++ b/cmd/gitaly-hooks/hooks.go
@@ -80,135 +80,26 @@ func main() {
hookClient := gitalypb.NewHookServiceClient(conn)
- hookStatus := int32(1)
-
+ var returnCode int
switch subCmd {
case "update":
- args := os.Args[2:]
- if len(args) != 3 {
- logger.Fatalf("hook %q expects exactly three arguments", subCmd)
- }
- ref, oldValue, newValue := args[0], args[1], args[2]
-
- req := &gitalypb.UpdateHookRequest{
- Repository: payload.Repo,
- EnvironmentVariables: os.Environ(),
- Ref: []byte(ref),
- OldValue: oldValue,
- NewValue: newValue,
- }
-
- updateHookStream, err := hookClient.UpdateHook(ctx, req)
- if err != nil {
- logger.Fatalf("error when starting command for %q: %v", subCmd, err)
- }
-
- if hookStatus, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
- return updateHookStream.Recv()
- }, noopSender, os.Stdout, os.Stderr); err != nil {
- logger.Fatalf("error when receiving data for %q: %v", subCmd, err)
- }
+ returnCode, err = updateHook(ctx, payload, hookClient, os.Args)
case "pre-receive":
- preReceiveHookStream, err := hookClient.PreReceiveHook(ctx)
- if err != nil {
- logger.Fatalf("error when getting preReceiveHookStream client for %q: %v", subCmd, err)
- }
-
- if err := preReceiveHookStream.Send(&gitalypb.PreReceiveHookRequest{
- Repository: payload.Repo,
- EnvironmentVariables: os.Environ(),
- GitPushOptions: gitPushOptions(),
- }); err != nil {
- logger.Fatalf("error when sending request for %q: %v", subCmd, err)
- }
-
- f := sendFunc(streamio.NewWriter(func(p []byte) error {
- return preReceiveHookStream.Send(&gitalypb.PreReceiveHookRequest{Stdin: p})
- }), preReceiveHookStream, os.Stdin)
-
- if hookStatus, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
- return preReceiveHookStream.Recv()
- }, f, os.Stdout, os.Stderr); err != nil {
- logger.Fatalf("error when receiving data for %q: %v", subCmd, err)
- }
+ returnCode, err = preReceiveHook(ctx, payload, hookClient, os.Args)
case "post-receive":
- postReceiveHookStream, err := hookClient.PostReceiveHook(ctx)
- if err != nil {
- logger.Fatalf("error when getting stream client for %q: %v", subCmd, err)
- }
-
- if err := postReceiveHookStream.Send(&gitalypb.PostReceiveHookRequest{
- Repository: payload.Repo,
- EnvironmentVariables: os.Environ(),
- GitPushOptions: gitPushOptions(),
- }); err != nil {
- logger.Fatalf("error when sending request for %q: %v", subCmd, err)
- }
-
- f := sendFunc(streamio.NewWriter(func(p []byte) error {
- return postReceiveHookStream.Send(&gitalypb.PostReceiveHookRequest{Stdin: p})
- }), postReceiveHookStream, os.Stdin)
-
- if hookStatus, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
- return postReceiveHookStream.Recv()
- }, f, os.Stdout, os.Stderr); err != nil {
- logger.Fatalf("error when receiving data for %q: %v", subCmd, err)
- }
+ returnCode, err = postReceiveHook(ctx, payload, hookClient, os.Args)
case "reference-transaction":
- if len(os.Args) != 3 {
- logger.Fatalf("hook %q is missing required arguments", subCmd)
- }
-
- var state gitalypb.ReferenceTransactionHookRequest_State
- switch os.Args[2] {
- case "prepared":
- state = gitalypb.ReferenceTransactionHookRequest_PREPARED
- case "committed":
- state = gitalypb.ReferenceTransactionHookRequest_COMMITTED
- case "aborted":
- state = gitalypb.ReferenceTransactionHookRequest_ABORTED
- default:
- logger.Fatalf("hook %q has invalid state %s", subCmd, os.Args[2])
- }
-
- referenceTransactionHookStream, err := hookClient.ReferenceTransactionHook(ctx)
- if err != nil {
- logger.Fatalf("error when getting referenceTransactionHookStream client for %q: %v", subCmd, err)
- }
-
- if err := referenceTransactionHookStream.Send(&gitalypb.ReferenceTransactionHookRequest{
- Repository: payload.Repo,
- EnvironmentVariables: os.Environ(),
- State: state,
- }); err != nil {
- logger.Fatalf("error when sending request for %q: %v", subCmd, err)
- }
-
- f := sendFunc(streamio.NewWriter(func(p []byte) error {
- return referenceTransactionHookStream.Send(&gitalypb.ReferenceTransactionHookRequest{Stdin: p})
- }), referenceTransactionHookStream, os.Stdin)
-
- if hookStatus, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
- return referenceTransactionHookStream.Recv()
- }, f, os.Stdout, os.Stderr); err != nil {
- logger.Fatalf("error when receiving data for %q: %v", subCmd, err)
- }
+ returnCode, err = referenceTransactionHook(ctx, payload, hookClient, os.Args)
case "git":
- var args []string
- for _, a := range os.Args[2:] {
- args = append(args, fixFilterQuoteBug(a))
- }
-
- hookStatus = 0
- if err := handlePackObjects(ctx, hookClient, payload.Repo, args); err != nil {
- hookStatus = 1
- logger.Logger().WithFields(logrus.Fields{"args": args}).WithError(err).Error("PackObjectsHook RPC failed")
- }
+ returnCode, err = packObjectsHook(ctx, payload, hookClient, os.Args)
default:
- logger.Fatalf("subcommand name invalid: %q", subCmd)
+ returnCode, err = 1, fmt.Errorf("subcommand name invalid: %q", subCmd)
+ }
+ if err != nil {
+ logger.Fatal(err)
}
- os.Exit(int(hookStatus))
+ os.Exit(returnCode)
}
func noopSender(c chan error) {}
@@ -270,6 +161,150 @@ func check(configPath string) (*hook.CheckInfo, error) {
return hook.NewManager(config.NewLocator(cfg), nil, gitlabAPI, cfg).Check(context.TODO())
}
+func updateHook(ctx context.Context, payload git.HooksPayload, hookClient gitalypb.HookServiceClient, args []string) (int, error) {
+ args = args[2:]
+ if len(args) != 3 {
+ return 1, errors.New("update hook expects exactly three arguments")
+ }
+ ref, oldValue, newValue := args[0], args[1], args[2]
+
+ req := &gitalypb.UpdateHookRequest{
+ Repository: payload.Repo,
+ EnvironmentVariables: os.Environ(),
+ Ref: []byte(ref),
+ OldValue: oldValue,
+ NewValue: newValue,
+ }
+
+ updateHookStream, err := hookClient.UpdateHook(ctx, req)
+ if err != nil {
+ return 1, fmt.Errorf("error when starting command for update hook: %v", err)
+ }
+
+ var returnCode int32
+ if returnCode, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
+ return updateHookStream.Recv()
+ }, noopSender, os.Stdout, os.Stderr); err != nil {
+ return 1, fmt.Errorf("error when receiving data for update hook: %v", err)
+ }
+
+ return int(returnCode), nil
+}
+
+func preReceiveHook(ctx context.Context, payload git.HooksPayload, hookClient gitalypb.HookServiceClient, args []string) (int, error) {
+ preReceiveHookStream, err := hookClient.PreReceiveHook(ctx)
+ if err != nil {
+ return 1, fmt.Errorf("error when getting preReceiveHookStream client for: %v", err)
+ }
+
+ if err := preReceiveHookStream.Send(&gitalypb.PreReceiveHookRequest{
+ Repository: payload.Repo,
+ EnvironmentVariables: os.Environ(),
+ GitPushOptions: gitPushOptions(),
+ }); err != nil {
+ return 1, fmt.Errorf("error when sending request for pre-receive hook: %v", err)
+ }
+
+ f := sendFunc(streamio.NewWriter(func(p []byte) error {
+ return preReceiveHookStream.Send(&gitalypb.PreReceiveHookRequest{Stdin: p})
+ }), preReceiveHookStream, os.Stdin)
+
+ var returnCode int32
+ if returnCode, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
+ return preReceiveHookStream.Recv()
+ }, f, os.Stdout, os.Stderr); err != nil {
+ return 1, fmt.Errorf("error when receiving data for pre-receive hook: %v", err)
+ }
+
+ return int(returnCode), nil
+}
+
+func postReceiveHook(ctx context.Context, payload git.HooksPayload, hookClient gitalypb.HookServiceClient, args []string) (int, error) {
+ postReceiveHookStream, err := hookClient.PostReceiveHook(ctx)
+ if err != nil {
+ return 1, fmt.Errorf("error when getting stream client for post-receive hook: %v", err)
+ }
+
+ if err := postReceiveHookStream.Send(&gitalypb.PostReceiveHookRequest{
+ Repository: payload.Repo,
+ EnvironmentVariables: os.Environ(),
+ GitPushOptions: gitPushOptions(),
+ }); err != nil {
+ return 1, fmt.Errorf("error when sending request for post-receive hook: %v", err)
+ }
+
+ f := sendFunc(streamio.NewWriter(func(p []byte) error {
+ return postReceiveHookStream.Send(&gitalypb.PostReceiveHookRequest{Stdin: p})
+ }), postReceiveHookStream, os.Stdin)
+
+ var returnCode int32
+ if returnCode, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
+ return postReceiveHookStream.Recv()
+ }, f, os.Stdout, os.Stderr); err != nil {
+ return 1, fmt.Errorf("error when receiving data for post-receive hook: %v", err)
+ }
+
+ return int(returnCode), nil
+}
+
+func referenceTransactionHook(ctx context.Context, payload git.HooksPayload, hookClient gitalypb.HookServiceClient, args []string) (int, error) {
+ if len(args) != 3 {
+ return 1, errors.New("reference-transaction hook is missing required arguments")
+ }
+
+ var state gitalypb.ReferenceTransactionHookRequest_State
+ switch args[2] {
+ case "prepared":
+ state = gitalypb.ReferenceTransactionHookRequest_PREPARED
+ case "committed":
+ state = gitalypb.ReferenceTransactionHookRequest_COMMITTED
+ case "aborted":
+ state = gitalypb.ReferenceTransactionHookRequest_ABORTED
+ default:
+ return 1, fmt.Errorf("reference-transaction hook has invalid state: %q", args[2])
+ }
+
+ referenceTransactionHookStream, err := hookClient.ReferenceTransactionHook(ctx)
+ if err != nil {
+ return 1, fmt.Errorf("error when getting referenceTransactionHookStream client: %v", err)
+ }
+
+ if err := referenceTransactionHookStream.Send(&gitalypb.ReferenceTransactionHookRequest{
+ Repository: payload.Repo,
+ EnvironmentVariables: os.Environ(),
+ State: state,
+ }); err != nil {
+ return 1, fmt.Errorf("error when sending request for reference-transaction hook: %v", err)
+ }
+
+ f := sendFunc(streamio.NewWriter(func(p []byte) error {
+ return referenceTransactionHookStream.Send(&gitalypb.ReferenceTransactionHookRequest{Stdin: p})
+ }), referenceTransactionHookStream, os.Stdin)
+
+ var returnCode int32
+ if returnCode, err = stream.Handler(func() (stream.StdoutStderrResponse, error) {
+ return referenceTransactionHookStream.Recv()
+ }, f, os.Stdout, os.Stderr); err != nil {
+ return 1, fmt.Errorf("error when receiving data for reference-transaction hook: %v", err)
+ }
+
+ return int(returnCode), nil
+}
+
+func packObjectsHook(ctx context.Context, payload git.HooksPayload, hookClient gitalypb.HookServiceClient, args []string) (int, error) {
+ var fixedArgs []string
+ for _, a := range args[2:] {
+ fixedArgs = append(fixedArgs, fixFilterQuoteBug(a))
+ }
+
+ if err := handlePackObjects(ctx, hookClient, payload.Repo, fixedArgs); err != nil {
+ logger.Logger().WithFields(logrus.Fields{"args": args}).WithError(err).Error("PackObjectsHook RPC failed")
+ return 1, nil
+ }
+
+ return 0, nil
+}
+
// This is a workaround for a bug in Git:
// https://gitlab.com/gitlab-org/git/-/issues/82. Once that bug is fixed
// we should no longer need this. The fix function is harmless if the bug