Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for push options #12169

Merged
merged 11 commits into from
Aug 23, 2020
31 changes: 31 additions & 0 deletions cmd/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ var checklist = []check{
isDefault: false,
f: runDoctorUserStarNum,
},
{
title: "Enable push options",
name: "enable-push-options",
isDefault: false,
f: runDoctorEnablePushOptions,
},
// more checks please append here
}

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

return results, nil
}

func runDoctorEnablePushOptions(ctx *cli.Context) ([]string, error) {
numRepos := 0
_, err := iterateRepositories(func(repo *models.Repository) ([]string, error) {
numRepos++
r, err := git.OpenRepository(repo.RepoPath())
jolheiser marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
defer r.Close()

if ctx.Bool("fix") {
_, err := git.NewCommand("config", "receive.advertisePushOptions", "true").RunInDir(r.Path)
return nil, err
}

return nil, nil
})

var prefix string
if !ctx.Bool("fix") {
prefix = "DRY RUN: "
}
return []string{fmt.Sprintf("%sEnabled push options for %d repositories.", prefix, numRepos)}, err
}
16 changes: 16 additions & 0 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ Gitea or set your environment appropriately.`, "")
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
GitPushOptions: pushOptions(),
ProtectedBranchID: prID,
IsDeployKey: isDeployKey,
}
Expand Down Expand Up @@ -326,6 +327,7 @@ Gitea or set your environment appropriately.`, "")
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
GitPushOptions: pushOptions(),
}
oldCommitIDs := make([]string, hookBatchSize)
newCommitIDs := make([]string, hookBatchSize)
Expand Down Expand Up @@ -438,3 +440,17 @@ func hookPrintResults(results []private.HookPostReceiveBranchResult) {
os.Stderr.Sync()
}
}

func pushOptions() map[string]string {
opts := make(map[string]string)
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
for idx := 0; idx < pushCount; idx++ {
opt := os.Getenv(fmt.Sprintf("GIT_PUSH_OPTION_%d", idx))
kv := strings.SplitN(opt, "=", 2)
if len(kv) == 2 {
opts[kv[0]] = kv[1]
}
}
}
return opts
}
31 changes: 31 additions & 0 deletions docs/content/doc/usage/push-options.en-us.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
date: "2020-07-06T16:00:00+02:00"
title: "Usage: Push Options"
slug: "push-options"
weight: 15
toc: true
draft: false
menu:
sidebar:
parent: "usage"
name: "Push Options"
weight: 15
identifier: "push-options"
---

# Push Options

In Gitea `1.13`, support for some [push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)
were added.


## Supported Options

- `repo.private` (true|false) - Change the repository's visibility.
This is particularly useful when combined with push-to-create.
- `repo.template` (true|false) - Change whether the repository is a template.

Example of changing a repository's visibility to public:
```shell
git push -o repo.private=false -u origin master
```
6 changes: 6 additions & 0 deletions modules/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ func Init(ctx context.Context) error {
return err
}

if version.Compare(gitVersion, "2.10", ">=") {
if err := checkAndSetConfig("receive.advertisePushOptions", "true", true); err != nil {
return err
}
}

if version.Compare(gitVersion, "2.18", ">=") {
if err := checkAndSetConfig("core.commitGraph", "true", true); err != nil {
return err
Expand Down
22 changes: 22 additions & 0 deletions modules/private/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"net/http"
"net/url"
"strconv"
"time"

"code.gitea.io/gitea/modules/setting"
Expand All @@ -19,8 +20,28 @@ const (
GitAlternativeObjectDirectories = "GIT_ALTERNATE_OBJECT_DIRECTORIES"
GitObjectDirectory = "GIT_OBJECT_DIRECTORY"
GitQuarantinePath = "GIT_QUARANTINE_PATH"
GitPushOptionCount = "GIT_PUSH_OPTION_COUNT"
)

// GitPushOptions is a wrapper around a map[string]string
type GitPushOptions map[string]string

// GitPushOptions keys
const (
GitPushOptionRepoPrivate = "repo.private"
GitPushOptionRepoTemplate = "repo.template"
)

// Bool checks for a key in the map and parses as a boolean
func (g GitPushOptions) Bool(key string, def bool) bool {
if val, ok := g[key]; ok {
if b, err := strconv.ParseBool(val); err == nil {
return b
}
}
return def
}

// HookOptions represents the options for the Hook calls
type HookOptions struct {
OldCommitIDs []string
Expand All @@ -31,6 +52,7 @@ type HookOptions struct {
GitObjectDirectory string
GitAlternativeObjectDirectories string
GitQuarantinePath string
GitPushOptions GitPushOptions
ProtectedBranchID int64
IsDeployKey bool
}
Expand Down
12 changes: 12 additions & 0 deletions routers/private/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,18 @@ func HookPostReceive(ctx *macaron.Context, opts private.HookOptions) {
}
}

// Push Options
if repo != nil && len(opts.GitPushOptions) > 0 {
repo.IsPrivate = opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate, repo.IsPrivate)
zeripath marked this conversation as resolved.
Show resolved Hide resolved
repo.IsTemplate = opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate, repo.IsTemplate)
if err := models.UpdateRepositoryCols(repo, "is_private", "is_template"); err != nil {
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
})
}
}

results := make([]private.HookPostReceiveBranchResult, 0, len(opts.OldCommitIDs))

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