mirror of
https://github.com/go-gitea/gitea
synced 2025-08-23 09:58:27 +00:00
Use configurable remote name for git commands (#35172)
Closes #19403, and makes it possible to use any remote name in code snippets for an empty repository and pull request. This change is very helpful to me, because I always use different name for my gitea remote. Uses setting config module to store the value. Default is `origin` for backward compatibility. ### Screenshots <details> <summary>Empty repo</summary> <img width="791" height="398" alt="image" src="https://github.com/user-attachments/assets/7214053d-a8dd-4e77-8c9d-78936d9859e0" /> </details> <details> <summary>Pull Request</summary> <img width="591" height="452" alt="image" src="https://github.com/user-attachments/assets/ebc3d25c-5d6d-481d-819d-9706af3c5594" /> </details> <details> <summary>Settings page</summary> <img width="1438" height="839" alt="image" src="https://github.com/user-attachments/assets/d92bfa2c-7adc-4efe-95fa-0c55ad13b3f5" /> </details> --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -49,6 +49,7 @@ func DefaultOpenWithEditorApps() OpenWithEditorAppsType {
|
|||||||
|
|
||||||
type RepositoryStruct struct {
|
type RepositoryStruct struct {
|
||||||
OpenWithEditorApps *config.Value[OpenWithEditorAppsType]
|
OpenWithEditorApps *config.Value[OpenWithEditorAppsType]
|
||||||
|
GitGuideRemoteName *config.Value[string]
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigStruct struct {
|
type ConfigStruct struct {
|
||||||
@@ -70,6 +71,7 @@ func initDefaultConfig() {
|
|||||||
},
|
},
|
||||||
Repository: &RepositoryStruct{
|
Repository: &RepositoryStruct{
|
||||||
OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"),
|
OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"),
|
||||||
|
GitGuideRemoteName: config.ValueJSON[string]("repository.git-guide-remote-name").WithDefault("origin"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,7 @@ func (value *Value[T]) Value(ctx context.Context) (v T) {
|
|||||||
|
|
||||||
rev := dg.GetRevision(ctx)
|
rev := dg.GetRevision(ctx)
|
||||||
|
|
||||||
// if the revision in database doesn't change, use the last value
|
// if the revision in the database doesn't change, use the last value
|
||||||
value.mu.RLock()
|
value.mu.RLock()
|
||||||
if rev == value.revision {
|
if rev == value.revision {
|
||||||
v = value.value
|
v = value.value
|
||||||
@@ -84,6 +84,10 @@ func (value *Value[T]) WithDefault(def T) *Value[T] {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (value *Value[T]) DefaultValue() T {
|
||||||
|
return value.def
|
||||||
|
}
|
||||||
|
|
||||||
func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] {
|
func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] {
|
||||||
value.cfgSecKey = cfgSecKey
|
value.cfgSecKey = cfgSecKey
|
||||||
return value
|
return value
|
||||||
|
@@ -3425,6 +3425,7 @@ config.picture_service = Picture Service
|
|||||||
config.disable_gravatar = Disable Gravatar
|
config.disable_gravatar = Disable Gravatar
|
||||||
config.enable_federated_avatar = Enable Federated Avatars
|
config.enable_federated_avatar = Enable Federated Avatars
|
||||||
config.open_with_editor_app_help = The "Open with" editors for the clone menu. If left empty, the default will be used. Expand to see the default.
|
config.open_with_editor_app_help = The "Open with" editors for the clone menu. If left empty, the default will be used. Expand to see the default.
|
||||||
|
config.git_guide_remote_name = Repository remote name for git commands in the guide
|
||||||
|
|
||||||
config.git_config = Git Configuration
|
config.git_config = Git Configuration
|
||||||
config.git_disable_diff_highlight = Disable Diff Syntax Highlight
|
config.git_disable_diff_highlight = Disable Diff Syntax Highlight
|
||||||
|
@@ -196,17 +196,21 @@ func ConfigSettings(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ChangeConfig(ctx *context.Context) {
|
func ChangeConfig(ctx *context.Context) {
|
||||||
key := strings.TrimSpace(ctx.FormString("key"))
|
|
||||||
value := ctx.FormString("value")
|
|
||||||
cfg := setting.Config()
|
cfg := setting.Config()
|
||||||
|
|
||||||
marshalBool := func(v string) (string, error) { //nolint:unparam // error is always nil
|
marshalBool := func(v string) ([]byte, error) {
|
||||||
if b, _ := strconv.ParseBool(v); b {
|
b, _ := strconv.ParseBool(v)
|
||||||
return "true", nil
|
return json.Marshal(b)
|
||||||
}
|
}
|
||||||
return "false", nil
|
|
||||||
|
marshalString := func(emptyDefault string) func(v string) ([]byte, error) {
|
||||||
|
return func(v string) ([]byte, error) {
|
||||||
|
return json.Marshal(util.IfZero(v, emptyDefault))
|
||||||
}
|
}
|
||||||
marshalOpenWithApps := func(value string) (string, error) {
|
}
|
||||||
|
|
||||||
|
marshalOpenWithApps := func(value string) ([]byte, error) {
|
||||||
|
// TODO: move the block alongside OpenWithEditorAppsType.ToTextareaString
|
||||||
lines := strings.Split(value, "\n")
|
lines := strings.Split(value, "\n")
|
||||||
var openWithEditorApps setting.OpenWithEditorAppsType
|
var openWithEditorApps setting.OpenWithEditorAppsType
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
@@ -224,32 +228,47 @@ func ChangeConfig(ctx *context.Context) {
|
|||||||
OpenURL: strings.TrimSpace(openURL),
|
OpenURL: strings.TrimSpace(openURL),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(openWithEditorApps)
|
return json.Marshal(openWithEditorApps)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
}
|
||||||
return string(b), nil
|
marshallers := map[string]func(string) ([]byte, error){
|
||||||
}
|
|
||||||
marshallers := map[string]func(string) (string, error){
|
|
||||||
cfg.Picture.DisableGravatar.DynKey(): marshalBool,
|
cfg.Picture.DisableGravatar.DynKey(): marshalBool,
|
||||||
cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool,
|
cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool,
|
||||||
cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps,
|
cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps,
|
||||||
|
cfg.Repository.GitGuideRemoteName.DynKey(): marshalString(cfg.Repository.GitGuideRemoteName.DefaultValue()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = ctx.Req.ParseForm()
|
||||||
|
configKeys := ctx.Req.Form["key"]
|
||||||
|
configValues := ctx.Req.Form["value"]
|
||||||
|
configSettings := map[string]string{}
|
||||||
|
loop:
|
||||||
|
for i, key := range configKeys {
|
||||||
|
if i >= len(configValues) {
|
||||||
|
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
value := configValues[i]
|
||||||
|
|
||||||
marshaller, hasMarshaller := marshallers[key]
|
marshaller, hasMarshaller := marshallers[key]
|
||||||
if !hasMarshaller {
|
if !hasMarshaller {
|
||||||
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
|
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
|
||||||
return
|
break loop
|
||||||
}
|
}
|
||||||
|
|
||||||
marshaledValue, err := marshaller(value)
|
marshaledValue, err := marshaller(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
|
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
configSettings[key] = string(marshaledValue)
|
||||||
|
}
|
||||||
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = system_model.SetSettings(ctx, map[string]string{key: marshaledValue}); err != nil {
|
if err := system_model.SetSettings(ctx, configSettings); err != nil {
|
||||||
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
|
ctx.ServerError("SetSettings", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
config.GetDynGetter().InvalidateCache()
|
config.GetDynGetter().InvalidateCache()
|
||||||
ctx.JSONOK()
|
ctx.JSONOK()
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
{{ctx.Locale.Tr "repository"}}
|
{{ctx.Locale.Tr "repository"}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
<form class="ui form form-fetch-action" method="post" action="{{AppSubUrl}}/-/admin/config?key={{.SystemConfig.Repository.OpenWithEditorApps.DynKey}}">
|
<form class="ui form form-fetch-action" method="post" action="{{AppSubUrl}}/-/admin/config">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<details>
|
<details>
|
||||||
<summary>{{ctx.Locale.Tr "admin.config.open_with_editor_app_help"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.config.open_with_editor_app_help"}}</summary>
|
||||||
@@ -32,7 +32,16 @@
|
|||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<textarea name="value">{{(.SystemConfig.Repository.OpenWithEditorApps.Value ctx).ToTextareaString}}</textarea>
|
{{$cfg := .SystemConfig.Repository.OpenWithEditorApps}}
|
||||||
|
<input type="hidden" name="key" value="{{$cfg.DynKey}}">
|
||||||
|
<textarea name="value">{{($cfg.Value ctx).ToTextareaString}}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label>{{ctx.Locale.Tr "admin.config.git_guide_remote_name"}}</label>
|
||||||
|
{{$cfg = .SystemConfig.Repository.GitGuideRemoteName}}
|
||||||
|
<input type="hidden" name="key" value="{{$cfg.DynKey}}">
|
||||||
|
<input name="value" value="{{$cfg.Value ctx}}" placeholder="{{$cfg.DefaultValue}}" maxlength="100" dir="auto" required pattern="^[A-Za-z0-9][\-_A-Za-z0-9]*$">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<button class="ui primary button">{{ctx.Locale.Tr "save"}}</button>
|
<button class="ui primary button">{{ctx.Locale.Tr "save"}}</button>
|
||||||
|
@@ -46,13 +46,14 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<h3>{{ctx.Locale.Tr "repo.create_new_repo_command"}}</h3>
|
<h3>{{ctx.Locale.Tr "repo.create_new_repo_command"}}</h3>
|
||||||
<div class="markup">
|
<div class="markup">
|
||||||
|
{{$gitRemoteName := $.SystemConfig.Repository.GitGuideRemoteName.Value ctx}}
|
||||||
<pre><code>touch README.md
|
<pre><code>touch README.md
|
||||||
git init{{if ne .Repository.ObjectFormatName "sha1"}} --object-format={{.Repository.ObjectFormatName}}{{end}}{{/* for sha256 repo, it needs to set "object-format" explicitly*/}}
|
git init{{if ne .Repository.ObjectFormatName "sha1"}} --object-format={{.Repository.ObjectFormatName}}{{end}}{{/* for sha256 repo, it needs to set "object-format" explicitly*/}}
|
||||||
{{if ne .Repository.DefaultBranch "master"}}git checkout -b {{.Repository.DefaultBranch}}{{end}}
|
{{if ne .Repository.DefaultBranch "master"}}git checkout -b {{.Repository.DefaultBranch}}{{end}}
|
||||||
git add README.md
|
git add README.md
|
||||||
git commit -m "first commit"
|
git commit -m "first commit"
|
||||||
git remote add origin <span class="js-clone-url">{{$.CloneButtonOriginLink.HTTPS}}</span>
|
git remote add {{$gitRemoteName}} <span class="js-clone-url">{{$.CloneButtonOriginLink.HTTPS}}</span>
|
||||||
git push -u origin {{.Repository.DefaultBranch}}</code></pre>
|
git push -u {{$gitRemoteName}} {{.Repository.DefaultBranch}}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
@@ -60,8 +61,8 @@ git push -u origin {{.Repository.DefaultBranch}}</code></pre>
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<h3>{{ctx.Locale.Tr "repo.push_exist_repo"}}</h3>
|
<h3>{{ctx.Locale.Tr "repo.push_exist_repo"}}</h3>
|
||||||
<div class="markup">
|
<div class="markup">
|
||||||
<pre><code>git remote add origin <span class="js-clone-url">{{$.CloneButtonOriginLink.HTTPS}}</span>
|
<pre><code>git remote add {{$gitRemoteName}} <span class="js-clone-url">{{$.CloneButtonOriginLink.HTTPS}}</span>
|
||||||
git push -u origin {{.Repository.DefaultBranch}}</code></pre>
|
git push -u {{$gitRemoteName}} {{.Repository.DefaultBranch}}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@@ -8,10 +8,11 @@
|
|||||||
{{$localBranch = print .PullRequest.HeadRepo.OwnerName "-" .PullRequest.HeadBranch}}
|
{{$localBranch = print .PullRequest.HeadRepo.OwnerName "-" .PullRequest.HeadBranch}}
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="ui secondary segment tw-font-mono">
|
<div class="ui secondary segment tw-font-mono">
|
||||||
|
{{$gitRemoteName := ctx.RootData.SystemConfig.Repository.GitGuideRemoteName.Value ctx}}
|
||||||
{{if eq .PullRequest.Flow 0}}
|
{{if eq .PullRequest.Flow 0}}
|
||||||
<div>git fetch -u {{if ne .PullRequest.HeadRepo.ID .PullRequest.BaseRepo.ID}}<origin-url data-url="{{.PullRequest.HeadRepo.Link}}"></origin-url>{{else}}origin{{end}} {{.PullRequest.HeadBranch}}:{{$localBranch}}</div>
|
<div>git fetch -u {{if ne .PullRequest.HeadRepo.ID .PullRequest.BaseRepo.ID}}<origin-url data-url="{{.PullRequest.HeadRepo.Link}}"></origin-url>{{else}}{{$gitRemoteName}}{{end}} {{.PullRequest.HeadBranch}}:{{$localBranch}}</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div>git fetch -u origin {{.PullRequest.GetGitHeadRefName}}:{{$localBranch}}</div>
|
<div>git fetch -u {{$gitRemoteName}} {{.PullRequest.GetGitHeadRefName}}:{{$localBranch}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div>git checkout {{$localBranch}}</div>
|
<div>git checkout {{$localBranch}}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,7 +51,7 @@
|
|||||||
<div>git checkout {{.PullRequest.BaseBranch}}</div>
|
<div>git checkout {{.PullRequest.BaseBranch}}</div>
|
||||||
<div>git merge {{$localBranch}}</div>
|
<div>git merge {{$localBranch}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>git push origin {{.PullRequest.BaseBranch}}</div>
|
<div>git push {{$gitRemoteName}} {{.PullRequest.BaseBranch}}</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user