diff options
Diffstat (limited to 'cmd/hook.go')
-rw-r--r-- | cmd/hook.go | 81 |
1 files changed, 49 insertions, 32 deletions
diff --git a/cmd/hook.go b/cmd/hook.go index 966e4a57ca..48a64fd197 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -293,9 +293,32 @@ Forgejo or set your environment appropriately.`, "") return nil } +// runHookUpdate process the update hook: https://git-scm.com/docs/githooks#update func runHookUpdate(c *cli.Context) error { - // Update is empty and is kept only for backwards compatibility - return nil + // Now if we're an internal don't do anything else + if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal { + return nil + } + + ctx, cancel := installSignals() + defer cancel() + + // The last three arguments given to the hook are in order: reference name, old commit ID and new commit ID. + args := os.Args[len(os.Args)-3:] + refFullName := git.RefName(args[0]) + newCommitID := args[2] + + // Only process pull references. + if !refFullName.IsPull() { + return nil + } + + // Deletion of the ref means that the new commit ID is only composed of '0'. + if strings.ContainsFunc(newCommitID, func(e rune) bool { return e != '0' }) { + return nil + } + + return fail(ctx, fmt.Sprintf("The deletion of %s is skipped as it's an internal reference.", refFullName), "") } func runHookPostReceive(c *cli.Context) error { @@ -583,7 +606,7 @@ Forgejo or set your environment appropriately.`, "") for { // note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed - rs, err = readPktLine(ctx, reader, pktLineTypeUnknow) + rs, err = readPktLine(ctx, reader, pktLineTypeUnknown) if err != nil { return err } @@ -604,7 +627,7 @@ Forgejo or set your environment appropriately.`, "") if hasPushOptions { for { - rs, err = readPktLine(ctx, reader, pktLineTypeUnknow) + rs, err = readPktLine(ctx, reader, pktLineTypeUnknown) if err != nil { return err } @@ -699,8 +722,8 @@ Forgejo or set your environment appropriately.`, "") type pktLineType int64 const ( - // UnKnow type - pktLineTypeUnknow pktLineType = 0 + // Unknown type + pktLineTypeUnknown pktLineType = 0 // flush-pkt "0000" pktLineTypeFlush pktLineType = iota // data line @@ -714,22 +737,16 @@ type gitPktLine struct { Data []byte } +// Reads an Pkt-Line from `in`. If requestType is not unknown, it will a func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) { - var ( - err error - r *gitPktLine - ) - - // read prefix + // Read length prefix lengthBytes := make([]byte, 4) - for i := 0; i < 4; i++ { - lengthBytes[i], err = in.ReadByte() - if err != nil { - return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err) - } + if n, err := in.Read(lengthBytes); n != 4 || err != nil { + return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err) } - r = new(gitPktLine) + var err error + r := &gitPktLine{} r.Length, err = strconv.ParseUint(string(lengthBytes), 16, 32) if err != nil { return nil, fail(ctx, "Protocol: format parse error", "Pkt-Line format is wrong :%v", err) @@ -748,11 +765,8 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType) } r.Data = make([]byte, r.Length-4) - for i := range r.Data { - r.Data[i], err = in.ReadByte() - if err != nil { - return nil, fail(ctx, "Protocol: data error", "Pkt-Line: read stdin failed : %v", err) - } + if n, err := io.ReadFull(in, r.Data); uint64(n) != r.Length-4 || err != nil { + return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err) } r.Type = pktLineTypeData @@ -768,20 +782,23 @@ func writeFlushPktLine(ctx context.Context, out io.Writer) error { return nil } +// Write an Pkt-Line based on `data` to `out` according to the specifcation. +// https://git-scm.com/docs/protocol-common func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error { - hexchar := []byte("0123456789abcdef") - hex := func(n uint64) byte { - return hexchar[(n)&15] + // Implementations SHOULD NOT send an empty pkt-line ("0004"). + if len(data) == 0 { + return fail(ctx, "Protocol: write error", "Not allowed to write empty Pkt-Line") } length := uint64(len(data) + 4) - tmp := make([]byte, 4) - tmp[0] = hex(length >> 12) - tmp[1] = hex(length >> 8) - tmp[2] = hex(length >> 4) - tmp[3] = hex(length) - lr, err := out.Write(tmp) + // The maximum length of a pkt-line’s data component is 65516 bytes. + // Implementations MUST NOT send pkt-line whose length exceeds 65520 (65516 bytes of payload + 4 bytes of length data). + if length > 65520 { + return fail(ctx, "Protocol: write error", "Pkt-Line exceeds maximum of 65520 bytes") + } + + lr, err := fmt.Fprintf(out, "%04x", length) if err != nil || lr != 4 { return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err) } |