Skip to content

Commit 8080ace

Browse files
wxiaoguangsilverwindKN4CK3RGiteaBot
authored
Support changing git config through app.ini, use diff.algorithm=histogram by default (#24860)
Close #13454 , Close #23255, Close #14697 (and maybe more related issues) Many users have the requirement to customize the git config. This PR introduces an easy way: put the options in Gitea's app.ini `[git.config]`, then the config options will be applied to git config. And it can support more flexible default config values, eg: now `diff.algorithm=histogram` by default. According to: https://stackoverflow.com/a/32367597/4754037 , `histogram diff` is efficient and doesn't like to cause server-side problems. --------- Co-authored-by: silverwind <[email protected]> Co-authored-by: KN4CK3R <[email protected]> Co-authored-by: Giteabot <[email protected]>
1 parent 910bf31 commit 8080ace

File tree

7 files changed

+134
-38
lines changed

7 files changed

+134
-38
lines changed

custom/conf/app.example.ini

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,28 @@ LEVEL = Info
682682
;; Disable the usage of using partial clones for git.
683683
;DISABLE_PARTIAL_CLONE = false
684684

685+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
686+
;; Git Operation timeout in seconds
687+
;[git.timeout]
688+
;DEFAULT = 360
689+
;MIGRATE = 600
690+
;MIRROR = 300
691+
;CLONE = 300
692+
;PULL = 300
693+
;GC = 60
694+
695+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
696+
;; Git Reflog timeout in days
697+
;[git.reflog]
698+
;ENABLED = true
699+
;EXPIRATION = 90
700+
701+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
702+
;; Git config options
703+
;; This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
704+
;[git.config]
705+
;diff.algorithm = histogram
706+
685707
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
686708
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
687709
[service]
@@ -2176,32 +2198,6 @@ LEVEL = Info
21762198
;Check at least this proportion of LFSMetaObjects per repo. (This may cause all stale LFSMetaObjects to be checked.)
21772199
;PROPORTION_TO_CHECK_PER_REPO = 0.6
21782200

2179-
2180-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2181-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2182-
;; Git Operation timeout in seconds
2183-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2184-
;[git.timeout]
2185-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2186-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2187-
;DEFAULT = 360
2188-
;MIGRATE = 600
2189-
;MIRROR = 300
2190-
;CLONE = 300
2191-
;PULL = 300
2192-
;GC = 60
2193-
2194-
2195-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2196-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2197-
;; Git Reflog timeout in days
2198-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2199-
;[git.reflog]
2200-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2201-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2202-
;ENABLED = true
2203-
;EXPIRATION = 90
2204-
22052201
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22062202
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22072203
;[mirror]

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,12 +1054,7 @@ Default templates for project boards:
10541054
- `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false.
10551055
- `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git.
10561056

1057-
## Git - Reflog settings (`git.reflog`)
1058-
1059-
- `ENABLED`: **true** Set to true to enable Git to write changes to reflogs in each repo.
1060-
- `EXPIRATION`: **90** Reflog entry lifetime, in days. Entries are removed opportunistically by Git.
1061-
1062-
## Git - Timeout settings (`git.timeout`)
1057+
### Git - Timeout settings (`git.timeout`)
10631058

10641059
- `DEFAULT`: **360**: Git operations default timeout seconds.
10651060
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
@@ -1068,6 +1063,18 @@ Default templates for project boards:
10681063
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
10691064
- `GC`: **60**: Git repository GC timeout seconds.
10701065

1066+
### Git - Reflog settings (`git.reflog`)
1067+
1068+
- `ENABLED`: **true** Set to true to enable Git to write changes to reflogs in each repo.
1069+
- `EXPIRATION`: **90** Reflog entry lifetime, in days. Entries are removed opportunistically by Git.
1070+
1071+
### Git - Config options (`git.config`)
1072+
1073+
The key/value pairs in this section will be used as git config.
1074+
This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
1075+
1076+
- `diff.algorithm`: **histogram**
1077+
10711078
## Metrics (`metrics`)
10721079

10731080
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.

docs/content/doc/administration/customizing-gitea.en-us.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,22 @@ Place custom files in corresponding sub-folder under `custom/options`.
282282

283283
To add custom .gitignore, add a file with existing [.gitignore rules](https://git-scm.com/docs/gitignore) in it to `$GITEA_CUSTOM/options/gitignore`
284284

285+
## Customizing the git configuration
286+
287+
Starting with Gitea 1.20, you can customize the git configuration via the `git.config` section.
288+
289+
### Enabling signed git pushes
290+
291+
To enable signed git pushes, set these two options:
292+
293+
```ini
294+
[git.config]
295+
receive.advertisePushOptions = true
296+
receive.certNonceSeed = <randomstring>
297+
```
298+
299+
`certNonceSeed` should be set to a random string and be kept secret.
300+
285301
### Labels
286302

287303
Starting with Gitea 1.19, you can add a file that follows the [YAML label format](https://github.com/go-gitea/gitea/blob/main/options/label/Advanced.yaml) to `$GITEA_CUSTOM/options/label`:

modules/git/git.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ func syncGitConfig() (err error) {
224224
return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err)
225225
}
226226

227+
// first, write user's git config options to git config file
228+
// user config options could be overwritten by builtin values later, because if a value is builtin, it must have some special purposes
229+
for k, v := range setting.GitConfig.Options {
230+
if err = configSet(strings.ToLower(k), v); err != nil {
231+
return err
232+
}
233+
}
234+
227235
// Git requires setting user.name and user.email in order to commit changes - old comment: "if they're not set just add some defaults"
228236
// TODO: need to confirm whether users really need to change these values manually. It seems that these values are dummy only and not really used.
229237
// If these values are not really used, then they can be set (overwritten) directly without considering about existence.

modules/git/git_test.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ func TestMain(m *testing.M) {
4242
}
4343
}
4444

45-
func TestGitConfig(t *testing.T) {
46-
gitConfigContains := func(sub string) bool {
47-
if b, err := os.ReadFile(HomeDir() + "/.gitconfig"); err == nil {
48-
return strings.Contains(string(b), sub)
49-
}
50-
return false
45+
func gitConfigContains(sub string) bool {
46+
if b, err := os.ReadFile(HomeDir() + "/.gitconfig"); err == nil {
47+
return strings.Contains(string(b), sub)
5148
}
49+
return false
50+
}
5251

52+
func TestGitConfig(t *testing.T) {
5353
assert.False(t, gitConfigContains("key-a"))
5454

5555
assert.NoError(t, configSetNonExist("test.key-a", "val-a"))
@@ -81,3 +81,15 @@ func TestGitConfig(t *testing.T) {
8181
assert.NoError(t, configUnsetAll("test.key-x", "*"))
8282
assert.False(t, gitConfigContains("key-x = *"))
8383
}
84+
85+
func TestSyncConfig(t *testing.T) {
86+
oldGitConfig := setting.GitConfig
87+
defer func() {
88+
setting.GitConfig = oldGitConfig
89+
}()
90+
91+
setting.GitConfig.Options["sync-test.cfg-key-a"] = "CfgValA"
92+
assert.NoError(t, syncGitConfig())
93+
assert.True(t, gitConfigContains("[sync-test]"))
94+
assert.True(t, gitConfigContains("cfg-key-a = CfgValA"))
95+
}

modules/setting/git.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package setting
55

66
import (
77
"path/filepath"
8+
"strings"
89
"time"
910

1011
"code.gitea.io/gitea/modules/log"
@@ -78,12 +79,28 @@ var Git = struct {
7879
},
7980
}
8081

82+
var GitConfig = struct {
83+
Options map[string]string
84+
}{
85+
Options: make(map[string]string),
86+
}
87+
8188
func loadGitFrom(rootCfg ConfigProvider) {
8289
sec := rootCfg.Section("git")
8390
if err := sec.MapTo(&Git); err != nil {
8491
log.Fatal("Failed to map Git settings: %v", err)
8592
}
8693

94+
secGitConfig := rootCfg.Section("git.config")
95+
GitConfig.Options = make(map[string]string)
96+
for _, key := range secGitConfig.Keys() {
97+
// git config key is case-insensitive, so always use lower-case
98+
GitConfig.Options[strings.ToLower(key.Name())] = key.String()
99+
}
100+
if _, ok := GitConfig.Options["diff.algorithm"]; !ok {
101+
GitConfig.Options["diff.algorithm"] = "histogram"
102+
}
103+
87104
Git.HomePath = sec.Key("HOME_PATH").MustString("home")
88105
if !filepath.IsAbs(Git.HomePath) {
89106
Git.HomePath = filepath.Join(AppDataPath, Git.HomePath)

modules/setting/git_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package setting
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestGitConfig(t *testing.T) {
13+
oldGit := Git
14+
oldGitConfig := GitConfig
15+
defer func() {
16+
Git = oldGit
17+
GitConfig = oldGitConfig
18+
}()
19+
20+
cfg, err := NewConfigProviderFromData(`
21+
[git.config]
22+
a.b = 1
23+
`)
24+
assert.NoError(t, err)
25+
loadGitFrom(cfg)
26+
27+
assert.Len(t, GitConfig.Options, 2)
28+
assert.EqualValues(t, "1", GitConfig.Options["a.b"])
29+
assert.EqualValues(t, "histogram", GitConfig.Options["diff.algorithm"])
30+
31+
cfg, err = NewConfigProviderFromData(`
32+
[git.config]
33+
diff.algorithm = other
34+
`)
35+
assert.NoError(t, err)
36+
loadGitFrom(cfg)
37+
38+
assert.Len(t, GitConfig.Options, 1)
39+
assert.EqualValues(t, "other", GitConfig.Options["diff.algorithm"])
40+
}

0 commit comments

Comments
 (0)