Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make hook status printing configurable with delay #9641

Merged
merged 9 commits into from
Jan 12, 2020
Merged
148 changes: 122 additions & 26 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"bufio"
"bytes"
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
Expand Down Expand Up @@ -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
zeripath marked this conversation as resolved.
Show resolved Hide resolved
}

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 {
if os.Getenv(models.EnvIsInternal) == "true" {
return nil
Expand Down Expand Up @@ -101,6 +182,18 @@ Gitea or set your environment appropriately.`, "")
total := 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() {
// TODO: support news feeds for wiki
if isWiki {
Expand All @@ -124,12 +217,10 @@ Gitea or set your environment appropriately.`, "")
newCommitIDs[count] = newCommitID
refFullNames[count] = refFullName
count++
fmt.Fprintf(os.Stdout, "*")
os.Stdout.Sync()
fmt.Fprintf(out, "*")

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.NewCommitIDs = newCommitIDs
Expand All @@ -147,12 +238,10 @@ Gitea or set your environment appropriately.`, "")
lastline = 0
}
} else {
fmt.Fprintf(os.Stdout, ".")
os.Stdout.Sync()
fmt.Fprintf(out, ".")
}
if lastline >= hookBatchSize {
fmt.Fprintf(os.Stdout, "\n")
os.Stdout.Sync()
fmt.Fprintf(out, "\n")
lastline = 0
}
}
Expand All @@ -162,8 +251,7 @@ Gitea or set your environment appropriately.`, "")
hookOptions.NewCommitIDs = newCommitIDs[: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)
switch statusCode {
Expand All @@ -173,14 +261,11 @@ Gitea or set your environment appropriately.`, "")
fail(msg, "")
}
} else if lastline > 0 {
fmt.Fprintf(os.Stdout, "\n")
os.Stdout.Sync()
fmt.Fprintf(out, "\n")
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
}

Expand All @@ -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
repoUser := os.Getenv(models.EnvRepoUsername)
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
Expand Down Expand Up @@ -241,7 +339,7 @@ Gitea or set your environment appropriately.`, "")
continue
}

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

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.NewCommitIDs = newCommitIDs
hookOptions.RefFullNames = refFullNames
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
if resp == nil {
_ = dWriter.Close()
hookPrintResults(results)
fail("Internal Server Error", err)
}
Expand All @@ -277,9 +374,9 @@ Gitea or set your environment appropriately.`, "")
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)
return nil
}
Expand All @@ -288,19 +385,18 @@ Gitea or set your environment appropriately.`, "")
hookOptions.NewCommitIDs = newCommitIDs[: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)
if resp == nil {
_ = dWriter.Close()
hookPrintResults(results)
fail("Internal Server Error", err)
}
wasEmpty = wasEmpty || resp.RepoWasEmpty
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 {
// We need to tell the repo to reset the default branch to master
Expand All @@ -309,7 +405,7 @@ Gitea or set your environment appropriately.`, "")
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
}
}

_ = dWriter.Close()
hookPrintResults(results)

return nil
Expand Down
2 changes: 2 additions & 0 deletions docs/content/doc/advanced/config-cheat-sheet.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on https://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
- `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`)
- `DEFAUlT`: **360**: Git operations default timeout seconds.
Expand Down
4 changes: 4 additions & 0 deletions modules/setting/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ var (
MaxGitDiffLines int
MaxGitDiffLineCharacters int
MaxGitDiffFiles int
VerbosePush bool
VerbosePushDelay time.Duration
GCArgs []string `ini:"GC_ARGS" delim:" "`
EnableAutoGitWireProtocol bool
Timeout struct {
Expand All @@ -36,6 +38,8 @@ var (
MaxGitDiffLines: 1000,
MaxGitDiffLineCharacters: 5000,
MaxGitDiffFiles: 100,
VerbosePush: true,
VerbosePushDelay: 5 * time.Second,
GCArgs: []string{},
EnableAutoGitWireProtocol: true,
Timeout: struct {
Expand Down