Browse Source

Make hook status printing configurable with delay (#9641)

* Delay printing hook statuses until after 1 second

* Move to a 5s delay, wrapped writer structure and add config

* Update cmd/hook.go

* Apply suggestions from code review

* Update cmd/hook.go

Co-authored-by: Antoine GIRARD <sapk@users.noreply.github.com>
tags/v1.21.12.1
zeripath GitHub 5 years ago
parent
commit
65baacf227
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 128 additions and 26 deletions
  1. +122
    -26
      cmd/hook.go
  2. +2
    -0
      docs/content/doc/advanced/config-cheat-sheet.en-us.md
  3. +4
    -0
      modules/setting/git.go

+ 122
- 26
cmd/hook.go View File

@@ -8,10 +8,12 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"fmt" "fmt"
"io"
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"time"


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
@@ -58,6 +60,85 @@ var (
} }
) )


type delayWriter struct {
internal io.Writer
buf *bytes.Buffer
timer *time.Timer
}

func newDelayWriter(internal io.Writer, delay time.Duration) *delayWriter {
timer := time.NewTimer(delay)
return &delayWriter{
internal: internal,
buf: &bytes.Buffer{},
timer: timer,
}
}

func (d *delayWriter) Write(p []byte) (n int, err error) {
if d.buf != nil {
select {
case <-d.timer.C:
_, err := d.internal.Write(d.buf.Bytes())
if err != nil {
return 0, err
}
d.buf = nil
return d.internal.Write(p)
default:
return d.buf.Write(p)
}
}
return d.internal.Write(p)
}

func (d *delayWriter) WriteString(s string) (n int, err error) {
if d.buf != nil {
select {
case <-d.timer.C:
_, err := d.internal.Write(d.buf.Bytes())
if err != nil {
return 0, err
}
d.buf = nil
return d.internal.Write([]byte(s))
default:
return d.buf.WriteString(s)
}
}
return d.internal.Write([]byte(s))
}

func (d *delayWriter) Close() error {
if d == nil {
return nil
}
stopped := d.timer.Stop()
if stopped {
return nil
}
select {
case <-d.timer.C:
default:
}
if d.buf == nil {
return nil
}
_, err := d.internal.Write(d.buf.Bytes())
d.buf = nil
return err
}

type nilWriter struct{}

func (n *nilWriter) Write(p []byte) (int, error) {
return len(p), nil
}

func (n *nilWriter) WriteString(s string) (int, error) {
return len(s), nil
}

func runHookPreReceive(c *cli.Context) error { func runHookPreReceive(c *cli.Context) error {
if os.Getenv(models.EnvIsInternal) == "true" { if os.Getenv(models.EnvIsInternal) == "true" {
return nil return nil
@@ -101,6 +182,18 @@ Gitea or set your environment appropriately.`, "")
total := 0 total := 0
lastline := 0 lastline := 0


var out io.Writer
out = &nilWriter{}
if setting.Git.VerbosePush {
if setting.Git.VerbosePushDelay > 0 {
dWriter := newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
defer dWriter.Close()
out = dWriter
} else {
out = os.Stdout
}
}

for scanner.Scan() { for scanner.Scan() {
// TODO: support news feeds for wiki // TODO: support news feeds for wiki
if isWiki { if isWiki {
@@ -124,12 +217,10 @@ Gitea or set your environment appropriately.`, "")
newCommitIDs[count] = newCommitID newCommitIDs[count] = newCommitID
refFullNames[count] = refFullName refFullNames[count] = refFullName
count++ count++
fmt.Fprintf(os.Stdout, "*")
os.Stdout.Sync()
fmt.Fprintf(out, "*")


if count >= hookBatchSize { if count >= hookBatchSize {
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
os.Stdout.Sync()
fmt.Fprintf(out, " Checking %d branches\n", count)


hookOptions.OldCommitIDs = oldCommitIDs hookOptions.OldCommitIDs = oldCommitIDs
hookOptions.NewCommitIDs = newCommitIDs hookOptions.NewCommitIDs = newCommitIDs
@@ -147,12 +238,10 @@ Gitea or set your environment appropriately.`, "")
lastline = 0 lastline = 0
} }
} else { } else {
fmt.Fprintf(os.Stdout, ".")
os.Stdout.Sync()
fmt.Fprintf(out, ".")
} }
if lastline >= hookBatchSize { if lastline >= hookBatchSize {
fmt.Fprintf(os.Stdout, "\n")
os.Stdout.Sync()
fmt.Fprintf(out, "\n")
lastline = 0 lastline = 0
} }
} }
@@ -162,8 +251,7 @@ Gitea or set your environment appropriately.`, "")
hookOptions.NewCommitIDs = newCommitIDs[:count] hookOptions.NewCommitIDs = newCommitIDs[:count]
hookOptions.RefFullNames = refFullNames[:count] hookOptions.RefFullNames = refFullNames[:count]


fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
os.Stdout.Sync()
fmt.Fprintf(out, " Checking %d branches\n", count)


statusCode, msg := private.HookPreReceive(username, reponame, hookOptions) statusCode, msg := private.HookPreReceive(username, reponame, hookOptions)
switch statusCode { switch statusCode {
@@ -173,14 +261,11 @@ Gitea or set your environment appropriately.`, "")
fail(msg, "") fail(msg, "")
} }
} else if lastline > 0 { } else if lastline > 0 {
fmt.Fprintf(os.Stdout, "\n")
os.Stdout.Sync()
fmt.Fprintf(out, "\n")
lastline = 0 lastline = 0
} }


fmt.Fprintf(os.Stdout, "Checked %d references in total\n", total)
os.Stdout.Sync()

fmt.Fprintf(out, "Checked %d references in total\n", total)
return nil return nil
} }


@@ -206,6 +291,19 @@ Gitea or set your environment appropriately.`, "")
} }
} }


var out io.Writer
var dWriter *delayWriter
out = &nilWriter{}
if setting.Git.VerbosePush {
if setting.Git.VerbosePushDelay > 0 {
dWriter = newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
defer dWriter.Close()
out = dWriter
} else {
out = os.Stdout
}
}

// the environment setted on serv command // the environment setted on serv command
repoUser := os.Getenv(models.EnvRepoUsername) repoUser := os.Getenv(models.EnvRepoUsername)
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true") isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
@@ -241,7 +339,7 @@ Gitea or set your environment appropriately.`, "")
continue continue
} }


fmt.Fprintf(os.Stdout, ".")
fmt.Fprintf(out, ".")
oldCommitIDs[count] = string(fields[0]) oldCommitIDs[count] = string(fields[0])
newCommitIDs[count] = string(fields[1]) newCommitIDs[count] = string(fields[1])
refFullNames[count] = string(fields[2]) refFullNames[count] = string(fields[2])
@@ -250,16 +348,15 @@ Gitea or set your environment appropriately.`, "")
} }
count++ count++
total++ total++
os.Stdout.Sync()


if count >= hookBatchSize { if count >= hookBatchSize {
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
os.Stdout.Sync()
fmt.Fprintf(out, " Processing %d references\n", count)
hookOptions.OldCommitIDs = oldCommitIDs hookOptions.OldCommitIDs = oldCommitIDs
hookOptions.NewCommitIDs = newCommitIDs hookOptions.NewCommitIDs = newCommitIDs
hookOptions.RefFullNames = refFullNames hookOptions.RefFullNames = refFullNames
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions) resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
if resp == nil { if resp == nil {
_ = dWriter.Close()
hookPrintResults(results) hookPrintResults(results)
fail("Internal Server Error", err) fail("Internal Server Error", err)
} }
@@ -277,9 +374,9 @@ Gitea or set your environment appropriately.`, "")
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err) fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
} }
} }
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
os.Stdout.Sync()
fmt.Fprintf(out, "Processed %d references in total\n", total)


_ = dWriter.Close()
hookPrintResults(results) hookPrintResults(results)
return nil return nil
} }
@@ -288,19 +385,18 @@ Gitea or set your environment appropriately.`, "")
hookOptions.NewCommitIDs = newCommitIDs[:count] hookOptions.NewCommitIDs = newCommitIDs[:count]
hookOptions.RefFullNames = refFullNames[:count] hookOptions.RefFullNames = refFullNames[:count]


fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
os.Stdout.Sync()
fmt.Fprintf(out, " Processing %d references\n", count)


resp, err := private.HookPostReceive(repoUser, repoName, hookOptions) resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
if resp == nil { if resp == nil {
_ = dWriter.Close()
hookPrintResults(results) hookPrintResults(results)
fail("Internal Server Error", err) fail("Internal Server Error", err)
} }
wasEmpty = wasEmpty || resp.RepoWasEmpty wasEmpty = wasEmpty || resp.RepoWasEmpty
results = append(results, resp.Results...) results = append(results, resp.Results...)


fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
os.Stdout.Sync()
fmt.Fprintf(out, "Processed %d references in total\n", total)


if wasEmpty && masterPushed { if wasEmpty && masterPushed {
// We need to tell the repo to reset the default branch to master // We need to tell the repo to reset the default branch to master
@@ -309,7 +405,7 @@ Gitea or set your environment appropriately.`, "")
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err) fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
} }
} }
_ = dWriter.Close()
hookPrintResults(results) hookPrintResults(results)


return nil return nil


+ 2
- 0
docs/content/doc/advanced/config-cheat-sheet.en-us.md View File

@@ -522,6 +522,8 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view. - `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/ - `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1 - `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1
- `VERBOSE_PUSH`: **true**: Print status information about pushes as they are being processed.
- `VERBOSE_PUSH_DELAY`: **5s**: Only print verbose information if push takes longer than this delay.


## Git - Timeout settings (`git.timeout`) ## Git - Timeout settings (`git.timeout`)
- `DEFAUlT`: **360**: Git operations default timeout seconds. - `DEFAUlT`: **360**: Git operations default timeout seconds.


+ 4
- 0
modules/setting/git.go View File

@@ -21,6 +21,8 @@ var (
MaxGitDiffLines int MaxGitDiffLines int
MaxGitDiffLineCharacters int MaxGitDiffLineCharacters int
MaxGitDiffFiles int MaxGitDiffFiles int
VerbosePush bool
VerbosePushDelay time.Duration
GCArgs []string `ini:"GC_ARGS" delim:" "` GCArgs []string `ini:"GC_ARGS" delim:" "`
EnableAutoGitWireProtocol bool EnableAutoGitWireProtocol bool
Timeout struct { Timeout struct {
@@ -36,6 +38,8 @@ var (
MaxGitDiffLines: 1000, MaxGitDiffLines: 1000,
MaxGitDiffLineCharacters: 5000, MaxGitDiffLineCharacters: 5000,
MaxGitDiffFiles: 100, MaxGitDiffFiles: 100,
VerbosePush: true,
VerbosePushDelay: 5 * time.Second,
GCArgs: []string{}, GCArgs: []string{},
EnableAutoGitWireProtocol: true, EnableAutoGitWireProtocol: true,
Timeout: struct { Timeout: struct {


Loading…
Cancel
Save