* Option to set default branch at repository creation * Handle template repos with non-default master branch * Add DefaultBranch handling on creation to API Fix #9542 Signed-off-by: Andrew Thornton <art27@cantab.net>tags/v1.21.12.1
| @@ -929,6 +929,7 @@ type CreateRepoOptions struct { | |||||
| IssueLabels string | IssueLabels string | ||||
| License string | License string | ||||
| Readme string | Readme string | ||||
| DefaultBranch string | |||||
| IsPrivate bool | IsPrivate bool | ||||
| IsMirror bool | IsMirror bool | ||||
| AutoInit bool | AutoInit bool | ||||
| @@ -27,15 +27,16 @@ import ( | |||||
| // CreateRepoForm form for creating repository | // CreateRepoForm form for creating repository | ||||
| type CreateRepoForm struct { | type CreateRepoForm struct { | ||||
| UID int64 `binding:"Required"` | |||||
| RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | |||||
| Private bool | |||||
| Description string `binding:"MaxSize(255)"` | |||||
| AutoInit bool | |||||
| Gitignores string | |||||
| IssueLabels string | |||||
| License string | |||||
| Readme string | |||||
| UID int64 `binding:"Required"` | |||||
| RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | |||||
| Private bool | |||||
| Description string `binding:"MaxSize(255)"` | |||||
| DefaultBranch string `binding:"GitRefName;MaxSize(100)"` | |||||
| AutoInit bool | |||||
| Gitignores string | |||||
| IssueLabels string | |||||
| License string | |||||
| Readme string | |||||
| RepoTemplate int64 | RepoTemplate int64 | ||||
| GitContent bool | GitContent bool | ||||
| @@ -113,7 +113,8 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp | |||||
| // Clone to temporary path and do the init commit. | // Clone to temporary path and do the init commit. | ||||
| templateRepoPath := templateRepo.RepoPath() | templateRepoPath := templateRepo.RepoPath() | ||||
| if err := git.Clone(templateRepoPath, tmpDir, git.CloneRepoOptions{ | if err := git.Clone(templateRepoPath, tmpDir, git.CloneRepoOptions{ | ||||
| Depth: 1, | |||||
| Depth: 1, | |||||
| Branch: templateRepo.DefaultBranch, | |||||
| }); err != nil { | }); err != nil { | ||||
| return fmt.Errorf("git clone: %v", err) | return fmt.Errorf("git clone: %v", err) | ||||
| } | } | ||||
| @@ -180,7 +181,7 @@ func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmp | |||||
| return fmt.Errorf("git remote add: %v", err) | return fmt.Errorf("git remote add: %v", err) | ||||
| } | } | ||||
| return initRepoCommit(tmpDir, repo, repo.Owner) | |||||
| return initRepoCommit(tmpDir, repo, repo.Owner, templateRepo.DefaultBranch) | |||||
| } | } | ||||
| func generateGitContent(ctx models.DBContext, repo, templateRepo, generateRepo *models.Repository) (err error) { | func generateGitContent(ctx models.DBContext, repo, templateRepo, generateRepo *models.Repository) (err error) { | ||||
| @@ -204,7 +205,7 @@ func generateGitContent(ctx models.DBContext, repo, templateRepo, generateRepo * | |||||
| return fmt.Errorf("getRepositoryByID: %v", err) | return fmt.Errorf("getRepositoryByID: %v", err) | ||||
| } | } | ||||
| repo.DefaultBranch = "master" | |||||
| repo.DefaultBranch = templateRepo.DefaultBranch | |||||
| if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { | if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { | ||||
| return fmt.Errorf("updateRepository: %v", err) | return fmt.Errorf("updateRepository: %v", err) | ||||
| } | } | ||||
| @@ -98,7 +98,7 @@ func prepareRepoCommit(ctx models.DBContext, repo *models.Repository, tmpDir, re | |||||
| } | } | ||||
| // initRepoCommit temporarily changes with work directory. | // initRepoCommit temporarily changes with work directory. | ||||
| func initRepoCommit(tmpPath string, repo *models.Repository, u *models.User) (err error) { | |||||
| func initRepoCommit(tmpPath string, repo *models.Repository, u *models.User, defaultBranch string) (err error) { | |||||
| commitTimeStr := time.Now().Format(time.RFC3339) | commitTimeStr := time.Now().Format(time.RFC3339) | ||||
| sig := u.NewGitSig() | sig := u.NewGitSig() | ||||
| @@ -145,7 +145,11 @@ func initRepoCommit(tmpPath string, repo *models.Repository, u *models.User) (er | |||||
| return fmt.Errorf("git commit: %v", err) | return fmt.Errorf("git commit: %v", err) | ||||
| } | } | ||||
| if stdout, err := git.NewCommand("push", "origin", "master"). | |||||
| if len(defaultBranch) == 0 { | |||||
| defaultBranch = "master" | |||||
| } | |||||
| if stdout, err := git.NewCommand("push", "origin", "master:"+defaultBranch). | |||||
| SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). | SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)). | ||||
| RunInDirWithEnv(tmpPath, models.InternalPushingEnvironment(u, repo)); err != nil { | RunInDirWithEnv(tmpPath, models.InternalPushingEnvironment(u, repo)); err != nil { | ||||
| log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) | log.Error("Failed to push back to master: Stdout: %s\nError: %v", stdout, err) | ||||
| @@ -190,7 +194,7 @@ func initRepository(ctx models.DBContext, repoPath string, u *models.User, repo | |||||
| } | } | ||||
| // Apply changes and commit. | // Apply changes and commit. | ||||
| if err = initRepoCommit(tmpDir, repo, u); err != nil { | |||||
| if err = initRepoCommit(tmpDir, repo, u, opts.DefaultBranch); err != nil { | |||||
| return fmt.Errorf("initRepoCommit: %v", err) | return fmt.Errorf("initRepoCommit: %v", err) | ||||
| } | } | ||||
| } | } | ||||
| @@ -206,6 +210,10 @@ func initRepository(ctx models.DBContext, repoPath string, u *models.User, repo | |||||
| } | } | ||||
| repo.DefaultBranch = "master" | repo.DefaultBranch = "master" | ||||
| if len(opts.DefaultBranch) > 0 { | |||||
| repo.DefaultBranch = opts.DefaultBranch | |||||
| } | |||||
| if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { | if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { | ||||
| return fmt.Errorf("updateRepository: %v", err) | return fmt.Errorf("updateRepository: %v", err) | ||||
| } | } | ||||
| @@ -112,6 +112,8 @@ type CreateRepoOption struct { | |||||
| License string `json:"license"` | License string `json:"license"` | ||||
| // Readme of the repository to create | // Readme of the repository to create | ||||
| Readme string `json:"readme"` | Readme string `json:"readme"` | ||||
| // DefaultBranch of the repository (used when initializes and in template) | |||||
| DefaultBranch string `json:"default_branch" binding:"GitRefName;MaxSize(100)"` | |||||
| } | } | ||||
| // EditRepoOption options when editing a repository's properties | // EditRepoOption options when editing a repository's properties | ||||
| @@ -218,14 +218,15 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR | |||||
| opt.Readme = "Default" | opt.Readme = "Default" | ||||
| } | } | ||||
| repo, err := repo_service.CreateRepository(ctx.User, owner, models.CreateRepoOptions{ | repo, err := repo_service.CreateRepository(ctx.User, owner, models.CreateRepoOptions{ | ||||
| Name: opt.Name, | |||||
| Description: opt.Description, | |||||
| IssueLabels: opt.IssueLabels, | |||||
| Gitignores: opt.Gitignores, | |||||
| License: opt.License, | |||||
| Readme: opt.Readme, | |||||
| IsPrivate: opt.Private, | |||||
| AutoInit: opt.AutoInit, | |||||
| Name: opt.Name, | |||||
| Description: opt.Description, | |||||
| IssueLabels: opt.IssueLabels, | |||||
| Gitignores: opt.Gitignores, | |||||
| License: opt.License, | |||||
| Readme: opt.Readme, | |||||
| IsPrivate: opt.Private, | |||||
| AutoInit: opt.AutoInit, | |||||
| DefaultBranch: opt.DefaultBranch, | |||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| if models.IsErrRepoAlreadyExist(err) { | if models.IsErrRepoAlreadyExist(err) { | ||||
| @@ -221,14 +221,15 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||||
| } | } | ||||
| } else { | } else { | ||||
| repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ | repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ | ||||
| Name: form.RepoName, | |||||
| Description: form.Description, | |||||
| Gitignores: form.Gitignores, | |||||
| IssueLabels: form.IssueLabels, | |||||
| License: form.License, | |||||
| Readme: form.Readme, | |||||
| IsPrivate: form.Private || setting.Repository.ForcePrivate, | |||||
| AutoInit: form.AutoInit, | |||||
| Name: form.RepoName, | |||||
| Description: form.Description, | |||||
| Gitignores: form.Gitignores, | |||||
| IssueLabels: form.IssueLabels, | |||||
| License: form.License, | |||||
| Readme: form.Readme, | |||||
| IsPrivate: form.Private || setting.Repository.ForcePrivate, | |||||
| DefaultBranch: form.DefaultBranch, | |||||
| AutoInit: form.AutoInit, | |||||
| }) | }) | ||||
| if err == nil { | if err == nil { | ||||
| log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name) | log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name) | ||||
| @@ -162,6 +162,10 @@ | |||||
| <label>{{.i18n.Tr "repo.auto_init"}}</label> | <label>{{.i18n.Tr "repo.auto_init"}}</label> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="inline field"> | |||||
| <label for="default_branch">{{.i18n.Tr "repo.default_branch"}}</label> | |||||
| <input id="default_branch" name="default_branch" value="{{.default_branch}}" placeholder="master"> | |||||
| </div> | |||||
| </div> | </div> | ||||
| <br/> | <br/> | ||||
| @@ -52,7 +52,7 @@ git init | |||||
| git add README.md | git add README.md | ||||
| git commit -m "first commit" | git commit -m "first commit" | ||||
| git remote add origin <span class="clone-url">{{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}</span> | git remote add origin <span class="clone-url">{{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}</span> | ||||
| git push -u origin master</code></pre> | |||||
| git push -u origin {{if ne .Repository.DefaultBranch "master"}}master:{{.Repository.DefaultBranch}}{{else}}master{{end}}</code></pre> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="ui divider"></div> | <div class="ui divider"></div> | ||||
| @@ -61,7 +61,7 @@ git push -u origin master</code></pre> | |||||
| <h3>{{.i18n.Tr "repo.push_exist_repo"}}</h3> | <h3>{{.i18n.Tr "repo.push_exist_repo"}}</h3> | ||||
| <div class="markdown"> | <div class="markdown"> | ||||
| <pre><code>git remote add origin <span class="clone-url">{{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}</span> | <pre><code>git remote add origin <span class="clone-url">{{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}</span> | ||||
| git push -u origin master</code></pre> | |||||
| git push -u origin {{.Repository.DefaultBranch}}</code></pre> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{end}} | {{end}} | ||||
| @@ -10600,6 +10600,11 @@ | |||||
| "type": "boolean", | "type": "boolean", | ||||
| "x-go-name": "AutoInit" | "x-go-name": "AutoInit" | ||||
| }, | }, | ||||
| "default_branch": { | |||||
| "description": "DefaultBranch of the repository (used when initializes and in template)", | |||||
| "type": "string", | |||||
| "x-go-name": "DefaultBranch" | |||||
| }, | |||||
| "description": { | "description": { | ||||
| "description": "Description of the repository to create", | "description": "Description of the repository to create", | ||||
| "type": "string", | "type": "string", | ||||