Skip to content

Commit 65baacf

Browse files
zeripathsapk
andauthored
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 <[email protected]>
1 parent 83f9359 commit 65baacf

File tree

3 files changed

+128
-26
lines changed

3 files changed

+128
-26
lines changed

cmd/hook.go

Lines changed: 122 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import (
88
"bufio"
99
"bytes"
1010
"fmt"
11+
"io"
1112
"net/http"
1213
"os"
1314
"strconv"
1415
"strings"
16+
"time"
1517

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

63+
type delayWriter struct {
64+
internal io.Writer
65+
buf *bytes.Buffer
66+
timer *time.Timer
67+
}
68+
69+
func newDelayWriter(internal io.Writer, delay time.Duration) *delayWriter {
70+
timer := time.NewTimer(delay)
71+
return &delayWriter{
72+
internal: internal,
73+
buf: &bytes.Buffer{},
74+
timer: timer,
75+
}
76+
}
77+
78+
func (d *delayWriter) Write(p []byte) (n int, err error) {
79+
if d.buf != nil {
80+
select {
81+
case <-d.timer.C:
82+
_, err := d.internal.Write(d.buf.Bytes())
83+
if err != nil {
84+
return 0, err
85+
}
86+
d.buf = nil
87+
return d.internal.Write(p)
88+
default:
89+
return d.buf.Write(p)
90+
}
91+
}
92+
return d.internal.Write(p)
93+
}
94+
95+
func (d *delayWriter) WriteString(s string) (n int, err error) {
96+
if d.buf != nil {
97+
select {
98+
case <-d.timer.C:
99+
_, err := d.internal.Write(d.buf.Bytes())
100+
if err != nil {
101+
return 0, err
102+
}
103+
d.buf = nil
104+
return d.internal.Write([]byte(s))
105+
default:
106+
return d.buf.WriteString(s)
107+
}
108+
}
109+
return d.internal.Write([]byte(s))
110+
}
111+
112+
func (d *delayWriter) Close() error {
113+
if d == nil {
114+
return nil
115+
}
116+
stopped := d.timer.Stop()
117+
if stopped {
118+
return nil
119+
}
120+
select {
121+
case <-d.timer.C:
122+
default:
123+
}
124+
if d.buf == nil {
125+
return nil
126+
}
127+
_, err := d.internal.Write(d.buf.Bytes())
128+
d.buf = nil
129+
return err
130+
}
131+
132+
type nilWriter struct{}
133+
134+
func (n *nilWriter) Write(p []byte) (int, error) {
135+
return len(p), nil
136+
}
137+
138+
func (n *nilWriter) WriteString(s string) (int, error) {
139+
return len(s), nil
140+
}
141+
61142
func runHookPreReceive(c *cli.Context) error {
62143
if os.Getenv(models.EnvIsInternal) == "true" {
63144
return nil
@@ -101,6 +182,18 @@ Gitea or set your environment appropriately.`, "")
101182
total := 0
102183
lastline := 0
103184

185+
var out io.Writer
186+
out = &nilWriter{}
187+
if setting.Git.VerbosePush {
188+
if setting.Git.VerbosePushDelay > 0 {
189+
dWriter := newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
190+
defer dWriter.Close()
191+
out = dWriter
192+
} else {
193+
out = os.Stdout
194+
}
195+
}
196+
104197
for scanner.Scan() {
105198
// TODO: support news feeds for wiki
106199
if isWiki {
@@ -124,12 +217,10 @@ Gitea or set your environment appropriately.`, "")
124217
newCommitIDs[count] = newCommitID
125218
refFullNames[count] = refFullName
126219
count++
127-
fmt.Fprintf(os.Stdout, "*")
128-
os.Stdout.Sync()
220+
fmt.Fprintf(out, "*")
129221

130222
if count >= hookBatchSize {
131-
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
132-
os.Stdout.Sync()
223+
fmt.Fprintf(out, " Checking %d branches\n", count)
133224

134225
hookOptions.OldCommitIDs = oldCommitIDs
135226
hookOptions.NewCommitIDs = newCommitIDs
@@ -147,12 +238,10 @@ Gitea or set your environment appropriately.`, "")
147238
lastline = 0
148239
}
149240
} else {
150-
fmt.Fprintf(os.Stdout, ".")
151-
os.Stdout.Sync()
241+
fmt.Fprintf(out, ".")
152242
}
153243
if lastline >= hookBatchSize {
154-
fmt.Fprintf(os.Stdout, "\n")
155-
os.Stdout.Sync()
244+
fmt.Fprintf(out, "\n")
156245
lastline = 0
157246
}
158247
}
@@ -162,8 +251,7 @@ Gitea or set your environment appropriately.`, "")
162251
hookOptions.NewCommitIDs = newCommitIDs[:count]
163252
hookOptions.RefFullNames = refFullNames[:count]
164253

165-
fmt.Fprintf(os.Stdout, " Checking %d branches\n", count)
166-
os.Stdout.Sync()
254+
fmt.Fprintf(out, " Checking %d branches\n", count)
167255

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

181-
fmt.Fprintf(os.Stdout, "Checked %d references in total\n", total)
182-
os.Stdout.Sync()
183-
268+
fmt.Fprintf(out, "Checked %d references in total\n", total)
184269
return nil
185270
}
186271

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

294+
var out io.Writer
295+
var dWriter *delayWriter
296+
out = &nilWriter{}
297+
if setting.Git.VerbosePush {
298+
if setting.Git.VerbosePushDelay > 0 {
299+
dWriter = newDelayWriter(os.Stdout, setting.Git.VerbosePushDelay)
300+
defer dWriter.Close()
301+
out = dWriter
302+
} else {
303+
out = os.Stdout
304+
}
305+
}
306+
209307
// the environment setted on serv command
210308
repoUser := os.Getenv(models.EnvRepoUsername)
211309
isWiki := (os.Getenv(models.EnvRepoIsWiki) == "true")
@@ -241,7 +339,7 @@ Gitea or set your environment appropriately.`, "")
241339
continue
242340
}
243341

244-
fmt.Fprintf(os.Stdout, ".")
342+
fmt.Fprintf(out, ".")
245343
oldCommitIDs[count] = string(fields[0])
246344
newCommitIDs[count] = string(fields[1])
247345
refFullNames[count] = string(fields[2])
@@ -250,16 +348,15 @@ Gitea or set your environment appropriately.`, "")
250348
}
251349
count++
252350
total++
253-
os.Stdout.Sync()
254351

255352
if count >= hookBatchSize {
256-
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
257-
os.Stdout.Sync()
353+
fmt.Fprintf(out, " Processing %d references\n", count)
258354
hookOptions.OldCommitIDs = oldCommitIDs
259355
hookOptions.NewCommitIDs = newCommitIDs
260356
hookOptions.RefFullNames = refFullNames
261357
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
262358
if resp == nil {
359+
_ = dWriter.Close()
263360
hookPrintResults(results)
264361
fail("Internal Server Error", err)
265362
}
@@ -277,9 +374,9 @@ Gitea or set your environment appropriately.`, "")
277374
fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
278375
}
279376
}
280-
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
281-
os.Stdout.Sync()
377+
fmt.Fprintf(out, "Processed %d references in total\n", total)
282378

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

291-
fmt.Fprintf(os.Stdout, " Processing %d references\n", count)
292-
os.Stdout.Sync()
388+
fmt.Fprintf(out, " Processing %d references\n", count)
293389

294390
resp, err := private.HookPostReceive(repoUser, repoName, hookOptions)
295391
if resp == nil {
392+
_ = dWriter.Close()
296393
hookPrintResults(results)
297394
fail("Internal Server Error", err)
298395
}
299396
wasEmpty = wasEmpty || resp.RepoWasEmpty
300397
results = append(results, resp.Results...)
301398

302-
fmt.Fprintf(os.Stdout, "Processed %d references in total\n", total)
303-
os.Stdout.Sync()
399+
fmt.Fprintf(out, "Processed %d references in total\n", total)
304400

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

315411
return nil

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
522522
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
523523
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
524524
- `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
525+
- `VERBOSE_PUSH`: **true**: Print status information about pushes as they are being processed.
526+
- `VERBOSE_PUSH_DELAY`: **5s**: Only print verbose information if push takes longer than this delay.
525527

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

modules/setting/git.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ var (
2121
MaxGitDiffLines int
2222
MaxGitDiffLineCharacters int
2323
MaxGitDiffFiles int
24+
VerbosePush bool
25+
VerbosePushDelay time.Duration
2426
GCArgs []string `ini:"GC_ARGS" delim:" "`
2527
EnableAutoGitWireProtocol bool
2628
Timeout struct {
@@ -36,6 +38,8 @@ var (
3638
MaxGitDiffLines: 1000,
3739
MaxGitDiffLineCharacters: 5000,
3840
MaxGitDiffFiles: 100,
41+
VerbosePush: true,
42+
VerbosePushDelay: 5 * time.Second,
3943
GCArgs: []string{},
4044
EnableAutoGitWireProtocol: true,
4145
Timeout: struct {

0 commit comments

Comments
 (0)