Skip to content

Commit ed38cdc

Browse files
committed
Merge branch 'main' into lunny/default_editor
2 parents e2717c1 + 50f67d7 commit ed38cdc

File tree

6 files changed

+149
-24
lines changed

6 files changed

+149
-24
lines changed

docs/content/page/index.de-de.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
date: "2016-11-08T16:00:00+02:00"
2+
date: "2023-01-07T22:03:00+01:00"
33
title: "Dokumentation"
44
slug: "documentation"
55
url: "/de-de/"
@@ -27,11 +27,11 @@ Gitea ist ein [Gogs](http://gogs.io)-Fork.
2727
* 2 CPU Kerne und 1GB RAM sind für kleine Teams/Projekte ausreichend.
2828
* Gitea sollte unter einem seperaten nicht-root Account auf UNIX-Systemen ausgeführt werden.
2929
* Achtung: Gitea verwaltet die `~/.ssh/authorized_keys` Datei. Gitea unter einem normalen Benutzer auszuführen könnte dazu führen, dass dieser sich nicht mehr anmelden kann.
30-
* [Git](https://git-scm.com/) Version 2.0 oder später wird benötigt.
31-
* Wenn git >= 2.1.2. und [Git large file storage](https://git-lfs.github.com/) aktiviert ist, dann wird es auch in Gitea verwendbar sein.
32-
* Wenn git >= 2.18, dann wird das Rendern von Commit-Graphen automatisch aktiviert.
30+
* [Git](https://git-scm.com/) Version 2.0 oder aktueller wird benötigt.
31+
* Wenn Git >= 2.1.2 und [Git LFS](https://git-lfs.github.com/) vorhanden ist, dann wird Git LFS Support automatisch für Gitea aktiviert.
32+
* Wenn Git >= 2.18, dann wird das Rendern von Commit-Graphen automatisch aktiviert.
3333

3434
## Browser Unterstützung
3535

36-
* Letzten 2 Versions von Chrome, Firefox, Safari und Edge
36+
* Die neuesten zwei Versionen von Chrome, Firefox, Safari und Edge
3737
* Firefox ESR

models/db/context.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,19 +98,31 @@ type Committer interface {
9898
// halfCommitter is a wrapper of Committer.
9999
// It can be closed early, but can't be committed early, it is useful for reusing a transaction.
100100
type halfCommitter struct {
101-
Committer
101+
committer Committer
102+
committed bool
102103
}
103104

104-
func (*halfCommitter) Commit() error {
105-
// do nothing
105+
func (c *halfCommitter) Commit() error {
106+
c.committed = true
107+
// should do nothing, and the parent committer will commit later
106108
return nil
107109
}
108110

111+
func (c *halfCommitter) Close() error {
112+
if c.committed {
113+
// it's "commit and close", should do nothing, and the parent committer will commit later
114+
return nil
115+
}
116+
117+
// it's "rollback and close", let the parent committer rollback right now
118+
return c.committer.Close()
119+
}
120+
109121
// TxContext represents a transaction Context,
110122
// it will reuse the existing transaction in the parent context or create a new one.
111123
func TxContext(parentCtx context.Context) (*Context, Committer, error) {
112124
if sess, ok := inTransaction(parentCtx); ok {
113-
return newContext(parentCtx, sess, true), &halfCommitter{Committer: sess}, nil
125+
return newContext(parentCtx, sess, true), &halfCommitter{committer: sess}, nil
114126
}
115127

116128
sess := x.NewSession()
@@ -126,7 +138,12 @@ func TxContext(parentCtx context.Context) (*Context, Committer, error) {
126138
// this function will reuse it otherwise will create a new one and close it when finished.
127139
func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error {
128140
if sess, ok := inTransaction(parentCtx); ok {
129-
return f(newContext(parentCtx, sess, true))
141+
err := f(newContext(parentCtx, sess, true))
142+
if err != nil {
143+
// rollback immediately, in case the caller ignores returned error and tries to commit the transaction.
144+
_ = sess.Close()
145+
}
146+
return err
130147
}
131148
return txWithNoCheck(parentCtx, f)
132149
}

models/db/context_committer_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package db // it's not db_test, because this file is for testing the private type halfCommitter
5+
6+
import (
7+
"fmt"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
type MockCommitter struct {
14+
wants []string
15+
gots []string
16+
}
17+
18+
func NewMockCommitter(wants ...string) *MockCommitter {
19+
return &MockCommitter{
20+
wants: wants,
21+
}
22+
}
23+
24+
func (c *MockCommitter) Commit() error {
25+
c.gots = append(c.gots, "commit")
26+
return nil
27+
}
28+
29+
func (c *MockCommitter) Close() error {
30+
c.gots = append(c.gots, "close")
31+
return nil
32+
}
33+
34+
func (c *MockCommitter) Assert(t *testing.T) {
35+
assert.Equal(t, c.wants, c.gots, "want operations %v, but got %v", c.wants, c.gots)
36+
}
37+
38+
func Test_halfCommitter(t *testing.T) {
39+
/*
40+
Do something like:
41+
42+
ctx, committer, err := db.TxContext(db.DefaultContext)
43+
if err != nil {
44+
return nil
45+
}
46+
defer committer.Close()
47+
48+
// ...
49+
50+
if err != nil {
51+
return nil
52+
}
53+
54+
// ...
55+
56+
return committer.Commit()
57+
*/
58+
59+
testWithCommitter := func(committer Committer, f func(committer Committer) error) {
60+
if err := f(&halfCommitter{committer: committer}); err == nil {
61+
committer.Commit()
62+
}
63+
committer.Close()
64+
}
65+
66+
t.Run("commit and close", func(t *testing.T) {
67+
mockCommitter := NewMockCommitter("commit", "close")
68+
69+
testWithCommitter(mockCommitter, func(committer Committer) error {
70+
defer committer.Close()
71+
return committer.Commit()
72+
})
73+
74+
mockCommitter.Assert(t)
75+
})
76+
77+
t.Run("rollback and close", func(t *testing.T) {
78+
mockCommitter := NewMockCommitter("close", "close")
79+
80+
testWithCommitter(mockCommitter, func(committer Committer) error {
81+
defer committer.Close()
82+
if true {
83+
return fmt.Errorf("error")
84+
}
85+
return committer.Commit()
86+
})
87+
88+
mockCommitter.Assert(t)
89+
})
90+
91+
t.Run("close and commit", func(t *testing.T) {
92+
mockCommitter := NewMockCommitter("close", "close")
93+
94+
testWithCommitter(mockCommitter, func(committer Committer) error {
95+
committer.Close()
96+
committer.Commit()
97+
return fmt.Errorf("error")
98+
})
99+
100+
mockCommitter.Assert(t)
101+
})
102+
}

modules/setting/mailer.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,25 @@ func newMailService() {
178178

179179
// we want to warn if users use SMTP on a non-local IP;
180180
// we might as well take the opportunity to check that it has an IP at all
181-
ips := tryResolveAddr(MailService.SMTPAddr)
182-
if MailService.Protocol == "smtp" {
183-
for _, ip := range ips {
184-
if !ip.IsLoopback() {
185-
log.Warn("connecting over insecure SMTP protocol to non-local address is not recommended")
186-
break
181+
// This check is not needed for sendmail
182+
switch MailService.Protocol {
183+
case "sendmail":
184+
var err error
185+
MailService.SendmailArgs, err = shellquote.Split(sec.Key("SENDMAIL_ARGS").String())
186+
if err != nil {
187+
log.Error("Failed to parse Sendmail args: '%s' with error %v", sec.Key("SENDMAIL_ARGS").String(), err)
188+
}
189+
case "smtp", "smtps", "smtp+starttls", "smtp+unix":
190+
ips := tryResolveAddr(MailService.SMTPAddr)
191+
if MailService.Protocol == "smtp" {
192+
for _, ip := range ips {
193+
if !ip.IsLoopback() {
194+
log.Warn("connecting over insecure SMTP protocol to non-local address is not recommended")
195+
break
196+
}
187197
}
188198
}
199+
case "dummy": // just mention and do nothing
189200
}
190201

191202
if MailService.From != "" {
@@ -214,14 +225,6 @@ func newMailService() {
214225
MailService.EnvelopeFrom = parsed.Address
215226
}
216227

217-
if MailService.Protocol == "sendmail" {
218-
var err error
219-
MailService.SendmailArgs, err = shellquote.Split(sec.Key("SENDMAIL_ARGS").String())
220-
if err != nil {
221-
log.Error("Failed to parse Sendmail args: %s with error %v", CustomConf, err)
222-
}
223-
}
224-
225228
log.Info("Mail Service Enabled")
226229
}
227230

templates/base/head_navbar.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
</div>
7878
{{else if .IsSigned}}
7979
<div class="right stackable menu">
80+
{{if EnableTimetracking}}
8081
<a class="active-stopwatch-trigger item ui label {{if not .ActiveStopwatch}}hidden{{end}}" href="{{.ActiveStopwatch.IssueLink}}">
8182
<span class="text">
8283
<span class="fitted item">
@@ -115,6 +116,7 @@
115116
</form>
116117
</div>
117118
</div>
119+
{{end}}
118120

119121
<a href="{{AppSubUrl}}/notifications" class="item tooltip not-mobile" data-content="{{.locale.Tr "notifications"}}" aria-label="{{.locale.Tr "notifications"}}">
120122
<span class="text">

web_src/js/features/stopwatch.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export function initStopwatch() {
2424
trigger: 'click',
2525
maxWidth: 'none',
2626
interactive: true,
27+
hideOnClick: true,
2728
});
2829

2930
// global stop watch (in the head_navbar), it should always work in any case either the EventSource or the PeriodicPoller is used.

0 commit comments

Comments
 (0)