Skip to content

Commit 43a397c

Browse files
jolheisermrsdizzie
andauthored
Initial support for push options (#12169)
* Initial support for push options Signed-off-by: jolheiser <[email protected]> * Fix misspelling 🤦 Signed-off-by: jolheiser <[email protected]> * Fix formatting after conflict resolution * defer close git repo * According the GitLab documentation, git >= 2.10 Signed-off-by: jolheiser <[email protected]> * Words are hard. Thanks @mrsdizzie 😅 Co-authored-by: mrsdizzie <[email protected]> * Only update if there are push options Signed-off-by: jolheiser <[email protected]> Co-authored-by: mrsdizzie <[email protected]>
1 parent e7d65cb commit 43a397c

File tree

6 files changed

+118
-0
lines changed

6 files changed

+118
-0
lines changed

cmd/doctor.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ var checklist = []check{
127127
isDefault: false,
128128
f: runDoctorUserStarNum,
129129
},
130+
{
131+
title: "Enable push options",
132+
name: "enable-push-options",
133+
isDefault: false,
134+
f: runDoctorEnablePushOptions,
135+
},
130136
// more checks please append here
131137
}
132138

@@ -605,3 +611,28 @@ func runDoctorCheckDBConsistency(ctx *cli.Context) ([]string, error) {
605611

606612
return results, nil
607613
}
614+
615+
func runDoctorEnablePushOptions(ctx *cli.Context) ([]string, error) {
616+
numRepos := 0
617+
_, err := iterateRepositories(func(repo *models.Repository) ([]string, error) {
618+
numRepos++
619+
r, err := git.OpenRepository(repo.RepoPath())
620+
if err != nil {
621+
return nil, err
622+
}
623+
defer r.Close()
624+
625+
if ctx.Bool("fix") {
626+
_, err := git.NewCommand("config", "receive.advertisePushOptions", "true").RunInDir(r.Path)
627+
return nil, err
628+
}
629+
630+
return nil, nil
631+
})
632+
633+
var prefix string
634+
if !ctx.Bool("fix") {
635+
prefix = "DRY RUN: "
636+
}
637+
return []string{fmt.Sprintf("%sEnabled push options for %d repositories.", prefix, numRepos)}, err
638+
}

cmd/hook.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ Gitea or set your environment appropriately.`, "")
178178
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
179179
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
180180
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
181+
GitPushOptions: pushOptions(),
181182
ProtectedBranchID: prID,
182183
IsDeployKey: isDeployKey,
183184
}
@@ -326,6 +327,7 @@ Gitea or set your environment appropriately.`, "")
326327
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
327328
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
328329
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
330+
GitPushOptions: pushOptions(),
329331
}
330332
oldCommitIDs := make([]string, hookBatchSize)
331333
newCommitIDs := make([]string, hookBatchSize)
@@ -438,3 +440,17 @@ func hookPrintResults(results []private.HookPostReceiveBranchResult) {
438440
os.Stderr.Sync()
439441
}
440442
}
443+
444+
func pushOptions() map[string]string {
445+
opts := make(map[string]string)
446+
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
447+
for idx := 0; idx < pushCount; idx++ {
448+
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
449+
kv := strings.SplitN(opt, "=", 2)
450+
if len(kv) == 2 {
451+
opts[kv[0]] = kv[1]
452+
}
453+
}
454+
}
455+
return opts
456+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
date: "2020-07-06T16:00:00+02:00"
3+
title: "Usage: Push Options"
4+
slug: "push-options"
5+
weight: 15
6+
toc: true
7+
draft: false
8+
menu:
9+
sidebar:
10+
parent: "usage"
11+
name: "Push Options"
12+
weight: 15
13+
identifier: "push-options"
14+
---
15+
16+
# Push Options
17+
18+
In Gitea `1.13`, support for some [push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)
19+
were added.
20+
21+
22+
## Supported Options
23+
24+
- `repo.private` (true|false) - Change the repository's visibility.
25+
This is particularly useful when combined with push-to-create.
26+
- `repo.template` (true|false) - Change whether the repository is a template.
27+
28+
Example of changing a repository's visibility to public:
29+
```shell
30+
git push -o repo.private=false -u origin master
31+
```

modules/git/git.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ func Init(ctx context.Context) error {
120120
return err
121121
}
122122

123+
if version.Compare(gitVersion, "2.10", ">=") {
124+
if err := checkAndSetConfig("receive.advertisePushOptions", "true", true); err != nil {
125+
return err
126+
}
127+
}
128+
123129
if version.Compare(gitVersion, "2.18", ">=") {
124130
if err := checkAndSetConfig("core.commitGraph", "true", true); err != nil {
125131
return err

modules/private/hook.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"fmt"
1010
"net/http"
1111
"net/url"
12+
"strconv"
1213
"time"
1314

1415
"code.gitea.io/gitea/modules/setting"
@@ -19,8 +20,28 @@ const (
1920
GitAlternativeObjectDirectories = "GIT_ALTERNATE_OBJECT_DIRECTORIES"
2021
GitObjectDirectory = "GIT_OBJECT_DIRECTORY"
2122
GitQuarantinePath = "GIT_QUARANTINE_PATH"
23+
GitPushOptionCount = "GIT_PUSH_OPTION_COUNT"
2224
)
2325

26+
// GitPushOptions is a wrapper around a map[string]string
27+
type GitPushOptions map[string]string
28+
29+
// GitPushOptions keys
30+
const (
31+
GitPushOptionRepoPrivate = "repo.private"
32+
GitPushOptionRepoTemplate = "repo.template"
33+
)
34+
35+
// Bool checks for a key in the map and parses as a boolean
36+
func (g GitPushOptions) Bool(key string, def bool) bool {
37+
if val, ok := g[key]; ok {
38+
if b, err := strconv.ParseBool(val); err == nil {
39+
return b
40+
}
41+
}
42+
return def
43+
}
44+
2445
// HookOptions represents the options for the Hook calls
2546
type HookOptions struct {
2647
OldCommitIDs []string
@@ -31,6 +52,7 @@ type HookOptions struct {
3152
GitObjectDirectory string
3253
GitAlternativeObjectDirectories string
3354
GitQuarantinePath string
55+
GitPushOptions GitPushOptions
3456
ProtectedBranchID int64
3557
IsDeployKey bool
3658
}

routers/private/hook.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,18 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) {
436436
}
437437
}
438438

439+
// Push Options
440+
if repo != nil && len(opts.GitPushOptions) > 0 {
441+
repo.IsPrivate = opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate, repo.IsPrivate)
442+
repo.IsTemplate = opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate, repo.IsTemplate)
443+
if err := models.UpdateRepositoryCols(repo, "is_private", "is_template"); err != nil {
444+
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
445+
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
446+
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
447+
})
448+
}
449+
}
450+
439451
results := make([]private.HookPostReceiveBranchResult, 0, len(opts.OldCommitIDs))
440452

441453
// We have to reload the repo in case its state is changed above

0 commit comments

Comments
 (0)