Skip to content

Commit 597c19d

Browse files
authored
Merge branch 'master' into assets_dir
2 parents 13bb69b + 27f9bda commit 597c19d

File tree

13 files changed

+274
-107
lines changed

13 files changed

+274
-107
lines changed

cmd/dump.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
129129
Name: "skip-custom-dir",
130130
Usage: "Skip custom directory",
131131
},
132+
cli.BoolFlag{
133+
Name: "skip-lfs-data",
134+
Usage: "Skip LFS data",
135+
},
136+
cli.BoolFlag{
137+
Name: "skip-attachment-data",
138+
Usage: "Skip attachment data",
139+
},
132140
cli.GenericFlag{
133141
Name: "type",
134142
Value: outputTypeEnum,
@@ -214,7 +222,9 @@ func runDump(ctx *cli.Context) error {
214222
fatal("Failed to include repositories: %v", err)
215223
}
216224

217-
if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error {
225+
if ctx.IsSet("skip-lfs-data") && ctx.Bool("skip-lfs-data") {
226+
log.Info("Skip dumping LFS data")
227+
} else if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error {
218228
info, err := object.Stat()
219229
if err != nil {
220230
return err
@@ -313,7 +323,9 @@ func runDump(ctx *cli.Context) error {
313323
}
314324
}
315325

316-
if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error {
326+
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
327+
log.Info("Skip dumping attachment data")
328+
} else if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error {
317329
info, err := object.Stat()
318330
if err != nil {
319331
return err

docs/content/doc/installation/with-docker-rootless.en-us.md

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ services:
8989
server:
9090
image: gitea/gitea:latest-rootless
9191
+ environment:
92-
+ - DB_TYPE=mysql
93-
+ - DB_HOST=db:3306
94-
+ - DB_NAME=gitea
95-
+ - DB_USER=gitea
96-
+ - DB_PASSWD=gitea
92+
+ - GITEA__database__TYPE=mysql
93+
+ - GITEA__database__HOST=db:3306
94+
+ - GITEA__database__NAME=gitea
95+
+ - GITEA__database__USER=gitea
96+
+ - GITEA__database__PASSWD=gitea
9797
restart: always
9898
volumes:
9999
- ./data:/var/lib/gitea
@@ -130,11 +130,11 @@ services:
130130
server:
131131
image: gitea/gitea:latest-rootless
132132
environment:
133-
+ - DB_TYPE=postgres
134-
+ - DB_HOST=db:5432
135-
+ - DB_NAME=gitea
136-
+ - DB_USER=gitea
137-
+ - DB_PASSWD=gitea
133+
+ - GITEA__database__TYPE=postgres
134+
+ - GITEA__database__HOST=db:5432
135+
+ - GITEA__database__NAME=gitea
136+
+ - GITEA__database__USER=gitea
137+
+ - GITEA__database__PASSWD=gitea
138138
restart: always
139139
volumes:
140140
- ./data:/var/lib/gitea
@@ -233,31 +233,6 @@ favorite browser to finalize the installation. Visit http://server-ip:3000 and f
233233
installation wizard. If the database was started with the `docker-compose` setup as
234234
documented above, please note that `db` must be used as the database hostname.
235235

236-
## Environments variables
237-
238-
You can configure some of Gitea's settings via environment variables:
239-
240-
(Default values are provided in **bold**)
241-
242-
* `APP_NAME`: **"Gitea: Git with a cup of tea"**: Application name, used in the page title.
243-
* `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
244-
* `SSH_DOMAIN`: **localhost**: Domain name of this server, used for the displayed clone URL in Gitea's UI.
245-
* `SSH_PORT`: **2222**: SSH port displayed in clone URL.
246-
* `SSH_LISTEN_PORT`: **%(SSH\_PORT)s**: Port for the built-in SSH server.
247-
* `DISABLE_SSH`: **false**: Disable SSH feature when it's not available.
248-
* `HTTP_PORT`: **3000**: HTTP listen port.
249-
* `ROOT_URL`: **""**: Overwrite the automatically generated public URL. This is useful if the internal and the external URL don't match (e.g. in Docker).
250-
* `LFS_START_SERVER`: **false**: Enables git-lfs support.
251-
* `DB_TYPE`: **sqlite3**: The database type in use \[mysql, postgres, mssql, sqlite3\].
252-
* `DB_HOST`: **localhost:3306**: Database host address and port.
253-
* `DB_NAME`: **gitea**: Database name.
254-
* `DB_USER`: **root**: Database username.
255-
* `DB_PASSWD`: **"\<empty>"**: Database user password. Use \`your password\` for quoting if you use special characters in the password.
256-
* `INSTALL_LOCK`: **false**: Disallow access to the install page.
257-
* `SECRET_KEY`: **""**: Global secret key. This should be changed. If this has a value and `INSTALL_LOCK` is empty, `INSTALL_LOCK` will automatically set to `true`.
258-
* `DISABLE_REGISTRATION`: **false**: Disable registration, after which only admin can create accounts for users.
259-
* `REQUIRE_SIGNIN_VIEW`: **false**: Enable this to force users to log in to view any page.
260-
261236
# Customization
262237

263238
Customization files described [here](https://docs.gitea.io/en-us/customizing-gitea/) should

docs/content/doc/installation/with-docker.en-us.md

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ services:
118118
environment:
119119
- USER_UID=1000
120120
- USER_GID=1000
121-
+ - DB_TYPE=mysql
122-
+ - DB_HOST=db:3306
123-
+ - DB_NAME=gitea
124-
+ - DB_USER=gitea
125-
+ - DB_PASSWD=gitea
121+
+ - GITEA__database__TYPE=mysql
122+
+ - GITEA__database__HOST=db:3306
123+
+ - GITEA__database__NAME=gitea
124+
+ - GITEA__database__USER=gitea
125+
+ - GITEA__database__PASSWD=gitea
126126
restart: always
127127
networks:
128128
- gitea
@@ -169,11 +169,11 @@ services:
169169
environment:
170170
- USER_UID=1000
171171
- USER_GID=1000
172-
+ - DB_TYPE=postgres
173-
+ - DB_HOST=db:5432
174-
+ - DB_NAME=gitea
175-
+ - DB_USER=gitea
176-
+ - DB_PASSWD=gitea
172+
+ - GITEA__database__TYPE=postgres
173+
+ - GITEA__database__HOST=db:5432
174+
+ - GITEA__database__NAME=gitea
175+
+ - GITEA__database__USER=gitea
176+
+ - GITEA__database__PASSWD=gitea
177177
restart: always
178178
networks:
179179
- gitea
@@ -256,31 +256,9 @@ favorite browser to finalize the installation. Visit http://server-ip:3000 and f
256256
installation wizard. If the database was started with the `docker-compose` setup as
257257
documented above, please note that `db` must be used as the database hostname.
258258

259-
## Environment variables
260-
261-
You can configure some of Gitea's settings via environment variables:
262-
263-
(Default values are provided in **bold**)
264-
265-
- `APP_NAME`: **"Gitea: Git with a cup of tea"**: Application name, used in the page title.
266-
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
267-
- `DOMAIN`: **localhost**: Domain name of this server, used for the displayed http clone URL in Gitea's UI.
268-
- `SSH_DOMAIN`: **localhost**: Domain name of this server, used for the displayed ssh clone URL in Gitea's UI. If the install page is enabled, SSH Domain Server takes DOMAIN value in the form (which overwrite this setting on save).
269-
- `SSH_PORT`: **22**: SSH port displayed in clone URL.
270-
- `SSH_LISTEN_PORT`: **%(SSH_PORT)s**: Port for the built-in SSH server.
271-
- `DISABLE_SSH`: **false**: Disable SSH feature when it's not available. If you want to disable SSH feature, you should set SSH port to `0` when installing Gitea.
272-
- `HTTP_PORT`: **3000**: HTTP listen port.
273-
- `ROOT_URL`: **""**: Overwrite the automatically generated public URL. This is useful if the internal and the external URL don't match (e.g. in Docker).
274-
- `LFS_START_SERVER`: **false**: Enables git-lfs support.
275-
- `DB_TYPE`: **sqlite3**: The database type in use \[mysql, postgres, mssql, sqlite3\].
276-
- `DB_HOST`: **localhost:3306**: Database host address and port.
277-
- `DB_NAME`: **gitea**: Database name.
278-
- `DB_USER`: **root**: Database username.
279-
- `DB_PASSWD`: **"\<empty>"**: Database user password. Use \`your password\` for quoting if you use special characters in the password.
280-
- `INSTALL_LOCK`: **false**: Disallow access to the install page.
281-
- `SECRET_KEY`: **""**: Global secret key. This should be changed. If this has a value and `INSTALL_LOCK` is empty, `INSTALL_LOCK` will automatically set to `true`.
282-
- `DISABLE_REGISTRATION`: **false**: Disable registration, after which only admin can create accounts for users.
283-
- `REQUIRE_SIGNIN_VIEW`: **false**: Enable this to force users to log in to view any page.
259+
## Configure the user inside Gitea using environment variables
260+
261+
- `USER`: **git**: The username of the user that runs Gitea within the container.
284262
- `USER_UID`: **1000**: The UID (Unix user ID) of the user that runs Gitea within the container. Match this to the UID of the owner of the `/data` volume if using host volumes (this is not necessary with named volumes).
285263
- `USER_GID`: **1000**: The GID (Unix group ID) of the user that runs Gitea within the container. Match this to the GID of the owner of the `/data` volume if using host volumes (this is not necessary with named volumes).
286264

modules/httpcache/httpcache.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net/http"
1111
"os"
1212
"strconv"
13+
"strings"
1314
"time"
1415

1516
"code.gitea.io/gitea/modules/setting"
@@ -26,11 +27,13 @@ func GetCacheControl() string {
2627
// generateETag generates an ETag based on size, filename and file modification time
2728
func generateETag(fi os.FileInfo) string {
2829
etag := fmt.Sprint(fi.Size()) + fi.Name() + fi.ModTime().UTC().Format(http.TimeFormat)
29-
return base64.StdEncoding.EncodeToString([]byte(etag))
30+
return `"` + base64.StdEncoding.EncodeToString([]byte(etag)) + `"`
3031
}
3132

3233
// HandleTimeCache handles time-based caching for a HTTP request
3334
func HandleTimeCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (handled bool) {
35+
w.Header().Set("Cache-Control", GetCacheControl())
36+
3437
ifModifiedSince := req.Header.Get("If-Modified-Since")
3538
if ifModifiedSince != "" {
3639
t, err := time.Parse(http.TimeFormat, ifModifiedSince)
@@ -40,20 +43,40 @@ func HandleTimeCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (
4043
}
4144
}
4245

43-
w.Header().Set("Cache-Control", GetCacheControl())
4446
w.Header().Set("Last-Modified", fi.ModTime().Format(http.TimeFormat))
4547
return false
4648
}
4749

48-
// HandleEtagCache handles ETag-based caching for a HTTP request
49-
func HandleEtagCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (handled bool) {
50+
// HandleFileETagCache handles ETag-based caching for a HTTP request
51+
func HandleFileETagCache(req *http.Request, w http.ResponseWriter, fi os.FileInfo) (handled bool) {
5052
etag := generateETag(fi)
51-
if req.Header.Get("If-None-Match") == etag {
52-
w.WriteHeader(http.StatusNotModified)
53-
return true
54-
}
53+
return HandleGenericETagCache(req, w, etag)
54+
}
5555

56+
// HandleGenericETagCache handles ETag-based caching for a HTTP request.
57+
// It returns true if the request was handled.
58+
func HandleGenericETagCache(req *http.Request, w http.ResponseWriter, etag string) (handled bool) {
59+
if len(etag) > 0 {
60+
w.Header().Set("Etag", etag)
61+
if checkIfNoneMatchIsValid(req, etag) {
62+
w.WriteHeader(http.StatusNotModified)
63+
return true
64+
}
65+
}
5666
w.Header().Set("Cache-Control", GetCacheControl())
57-
w.Header().Set("ETag", etag)
67+
return false
68+
}
69+
70+
// checkIfNoneMatchIsValid tests if the header If-None-Match matches the ETag
71+
func checkIfNoneMatchIsValid(req *http.Request, etag string) bool {
72+
ifNoneMatch := req.Header.Get("If-None-Match")
73+
if len(ifNoneMatch) > 0 {
74+
for _, item := range strings.Split(ifNoneMatch, ",") {
75+
item = strings.TrimSpace(item)
76+
if item == etag {
77+
return true
78+
}
79+
}
80+
}
5881
return false
5982
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package httpcache
6+
7+
import (
8+
"net/http"
9+
"net/http/httptest"
10+
"os"
11+
"testing"
12+
"time"
13+
14+
"github.com/stretchr/testify/assert"
15+
)
16+
17+
type mockFileInfo struct {
18+
}
19+
20+
func (m mockFileInfo) Name() string { return "gitea.test" }
21+
func (m mockFileInfo) Size() int64 { return int64(10) }
22+
func (m mockFileInfo) Mode() os.FileMode { return os.ModePerm }
23+
func (m mockFileInfo) ModTime() time.Time { return time.Time{} }
24+
func (m mockFileInfo) IsDir() bool { return false }
25+
func (m mockFileInfo) Sys() interface{} { return nil }
26+
27+
func TestHandleFileETagCache(t *testing.T) {
28+
fi := mockFileInfo{}
29+
etag := `"MTBnaXRlYS50ZXN0TW9uLCAwMSBKYW4gMDAwMSAwMDowMDowMCBHTVQ="`
30+
31+
t.Run("No_If-None-Match", func(t *testing.T) {
32+
req := &http.Request{Header: make(http.Header)}
33+
w := httptest.NewRecorder()
34+
35+
handled := HandleFileETagCache(req, w, fi)
36+
37+
assert.False(t, handled)
38+
assert.Len(t, w.Header(), 2)
39+
assert.Contains(t, w.Header(), "Cache-Control")
40+
assert.Contains(t, w.Header(), "Etag")
41+
assert.Equal(t, etag, w.Header().Get("Etag"))
42+
})
43+
t.Run("Wrong_If-None-Match", func(t *testing.T) {
44+
req := &http.Request{Header: make(http.Header)}
45+
w := httptest.NewRecorder()
46+
47+
req.Header.Set("If-None-Match", `"wrong etag"`)
48+
49+
handled := HandleFileETagCache(req, w, fi)
50+
51+
assert.False(t, handled)
52+
assert.Len(t, w.Header(), 2)
53+
assert.Contains(t, w.Header(), "Cache-Control")
54+
assert.Contains(t, w.Header(), "Etag")
55+
assert.Equal(t, etag, w.Header().Get("Etag"))
56+
})
57+
t.Run("Correct_If-None-Match", func(t *testing.T) {
58+
req := &http.Request{Header: make(http.Header)}
59+
w := httptest.NewRecorder()
60+
61+
req.Header.Set("If-None-Match", etag)
62+
63+
handled := HandleFileETagCache(req, w, fi)
64+
65+
assert.True(t, handled)
66+
assert.Len(t, w.Header(), 1)
67+
assert.Contains(t, w.Header(), "Etag")
68+
assert.Equal(t, etag, w.Header().Get("Etag"))
69+
assert.Equal(t, http.StatusNotModified, w.Code)
70+
})
71+
}
72+
73+
func TestHandleGenericETagCache(t *testing.T) {
74+
etag := `"test"`
75+
76+
t.Run("No_If-None-Match", func(t *testing.T) {
77+
req := &http.Request{Header: make(http.Header)}
78+
w := httptest.NewRecorder()
79+
80+
handled := HandleGenericETagCache(req, w, etag)
81+
82+
assert.False(t, handled)
83+
assert.Len(t, w.Header(), 2)
84+
assert.Contains(t, w.Header(), "Cache-Control")
85+
assert.Contains(t, w.Header(), "Etag")
86+
assert.Equal(t, etag, w.Header().Get("Etag"))
87+
})
88+
t.Run("Wrong_If-None-Match", func(t *testing.T) {
89+
req := &http.Request{Header: make(http.Header)}
90+
w := httptest.NewRecorder()
91+
92+
req.Header.Set("If-None-Match", `"wrong etag"`)
93+
94+
handled := HandleGenericETagCache(req, w, etag)
95+
96+
assert.False(t, handled)
97+
assert.Len(t, w.Header(), 2)
98+
assert.Contains(t, w.Header(), "Cache-Control")
99+
assert.Contains(t, w.Header(), "Etag")
100+
assert.Equal(t, etag, w.Header().Get("Etag"))
101+
})
102+
t.Run("Correct_If-None-Match", func(t *testing.T) {
103+
req := &http.Request{Header: make(http.Header)}
104+
w := httptest.NewRecorder()
105+
106+
req.Header.Set("If-None-Match", etag)
107+
108+
handled := HandleGenericETagCache(req, w, etag)
109+
110+
assert.True(t, handled)
111+
assert.Len(t, w.Header(), 1)
112+
assert.Contains(t, w.Header(), "Etag")
113+
assert.Equal(t, etag, w.Header().Get("Etag"))
114+
assert.Equal(t, http.StatusNotModified, w.Code)
115+
})
116+
t.Run("Multiple_Wrong_If-None-Match", func(t *testing.T) {
117+
req := &http.Request{Header: make(http.Header)}
118+
w := httptest.NewRecorder()
119+
120+
req.Header.Set("If-None-Match", `"wrong etag", "wrong etag "`)
121+
122+
handled := HandleGenericETagCache(req, w, etag)
123+
124+
assert.False(t, handled)
125+
assert.Len(t, w.Header(), 2)
126+
assert.Contains(t, w.Header(), "Cache-Control")
127+
assert.Contains(t, w.Header(), "Etag")
128+
assert.Equal(t, etag, w.Header().Get("Etag"))
129+
})
130+
t.Run("Multiple_Correct_If-None-Match", func(t *testing.T) {
131+
req := &http.Request{Header: make(http.Header)}
132+
w := httptest.NewRecorder()
133+
134+
req.Header.Set("If-None-Match", `"wrong etag", `+etag)
135+
136+
handled := HandleGenericETagCache(req, w, etag)
137+
138+
assert.True(t, handled)
139+
assert.Len(t, w.Header(), 1)
140+
assert.Contains(t, w.Header(), "Etag")
141+
assert.Equal(t, etag, w.Header().Get("Etag"))
142+
assert.Equal(t, http.StatusNotModified, w.Code)
143+
})
144+
}

modules/public/public.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func (opts *Options) handle(w http.ResponseWriter, req *http.Request, opt *Optio
164164
log.Println("[Static] Serving " + file)
165165
}
166166

167-
if httpcache.HandleEtagCache(req, w, fi) {
167+
if httpcache.HandleFileETagCache(req, w, fi) {
168168
return true
169169
}
170170

0 commit comments

Comments
 (0)