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

error.go « git « internal « workhorse - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e073df19fff67480a7e7e8aa4e77ead5e26f99e6 (plain)
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
package git

import (
	"errors"
	"fmt"
	"io"

	"gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
	"google.golang.org/grpc/status"

	"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
)

// For unwrapping google.golang.org/grpc/internal/status.Error
type grpcErr interface {
	GRPCStatus() *status.Status
	Error() string
}

// For cosmetic purposes in Sentry
type copyError struct{ error }

// handleLimitErr handles errors that come back from Gitaly that may be a
// LimitError. A LimitError is returned by Gitaly when it is at its limit in
// handling requests. Since this is a known error, we should print a sensible
// error message to the end user.
func handleLimitErr(err error, w io.Writer, f func(w io.Writer) error) {
	var statusErr grpcErr
	if !errors.As(err, &statusErr) {
		return
	}

	if st, ok := status.FromError(statusErr); ok {
		details := st.Details()
		for _, detail := range details {
			switch detail.(type) {
			case *gitalypb.LimitError:
				if err := f(w); err != nil {
					log.WithError(fmt.Errorf("handling limit error: %w", err))
				}
			}
		}
	}
}

// writeReceivePackError writes a "server is busy" error message to the
// git-receive-pack-result.
//
// 0023\x01001aunpack server is busy
// 00000044\x2GitLab is currently unable to handle this request due to load.
// 0000
//
// We write a line reporting that unpack failed, and then provide some progress
// information through the side-band 2 channel.
// See https://gitlab.com/gitlab-org/gitaly/-/tree/jc-return-structured-error-limits
// for more details.
func writeReceivePackError(w io.Writer) error {
	if _, err := fmt.Fprintf(w, "%04x", 35); err != nil {
		return err
	}

	if _, err := w.Write([]byte{0x01}); err != nil {
		return err
	}

	if _, err := fmt.Fprintf(w, "%04xunpack server is busy\n", 26); err != nil {
		return err
	}

	if _, err := w.Write([]byte("0000")); err != nil {
		return err
	}

	if _, err := fmt.Fprintf(w, "%04x", 68); err != nil {
		return err
	}

	if _, err := w.Write([]byte{0x2}); err != nil {
		return err
	}

	if _, err := fmt.Fprint(w, "GitLab is currently unable to handle this request due to load.\n"); err != nil {
		return err
	}

	if _, err := w.Write([]byte("0000")); err != nil {
		return err
	}

	return nil
}

// writeUploadPackError writes a "server is busy" error message that git
// understands and prints to stdout. UploadPack expects to receive pack data in
// PKT-LINE format. An error-line can be passed that begins with ERR.
// See https://git-scm.com/docs/pack-protocol/2.29.0#_pkt_line_format.
func writeUploadPackError(w io.Writer) error {
	_, err := fmt.Fprintf(w, "%04xERR GitLab is currently unable to handle this request due to load.\n", 71)
	return err
}