From 0d4460db68d2d10105f4695f46084c2a03dca7d4 Mon Sep 17 00:00:00 2001 From: Dmitry Sharshakov Date: Mon, 10 Jul 2023 16:38:10 +0300 Subject: [PATCH 1/5] Add support for forking single branch Fixes #25117 Add UI for choosing branch to fork Change default branch on single-branch forks --- options/locale/locale_en-US.ini | 2 ++ routers/web/repo/pull.go | 22 +++++++++++++++++++--- services/forms/repo_form.go | 2 ++ services/repository/fork.go | 23 +++++++++++++++++------ templates/repo/pulls/fork.tmpl | 20 ++++++++++++++++++++ 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index c4c9d32e1d4ac..df3765b585977 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -935,6 +935,8 @@ fork_from = Fork From already_forked = You've already forked %s fork_to_different_account = Fork to a different account fork_visibility_helper = The visibility of a forked repository cannot be changed. +fork_branch = Branch to be cloned to the fork +all_branches = All branches use_template = Use this template clone_in_vsc = Clone in VS Code download_zip = Download ZIP diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 1b68ef352a4ef..6cdc1be00813a 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -176,6 +176,21 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository { ctx.Data["ContextUser"] = orgs[0] } + branches, err := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{ + RepoID: ctx.Repo.Repository.ID, + ListOptions: db.ListOptions{ + ListAll: true, + }, + IsDeletedBranch: util.OptionalBoolFalse, + // Add it as the first option + ExcludeBranchNames: []string{forkRepo.DefaultBranch}, + }) + if err != nil { + ctx.ServerError("FindBranchNames", err) + return nil + } + ctx.Data["Branches"] = append([]string{forkRepo.DefaultBranch}, branches...) + return forkRepo } @@ -258,9 +273,10 @@ func ForkPost(ctx *context.Context) { } repo, err := repo_service.ForkRepository(ctx, ctx.Doer, ctxUser, repo_service.ForkRepoOptions{ - BaseRepo: forkRepo, - Name: form.RepoName, - Description: form.Description, + BaseRepo: forkRepo, + Name: form.RepoName, + Description: form.Description, + SingleBranch: form.ForkSingleBranch, }) if err != nil { ctx.Data["Err_RepoName"] = true diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 8108a55f7a35d..247f5ea0514c8 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -50,6 +50,8 @@ type CreateRepoForm struct { Avatar bool Labels bool TrustModel string + + ForkSingleBranch string } // Validate validates the fields diff --git a/services/repository/fork.go b/services/repository/fork.go index 59aa173373314..86d2df2387eec 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -44,9 +44,10 @@ func (err ErrForkAlreadyExist) Unwrap() error { // ForkRepoOptions contains the fork repository options type ForkRepoOptions struct { - BaseRepo *repo_model.Repository - Name string - Description string + BaseRepo *repo_model.Repository + Name string + Description string + SingleBranch string } // ForkRepository forks a repository @@ -70,6 +71,10 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork } } + defaultBranch := opts.BaseRepo.DefaultBranch + if opts.SingleBranch != "" { + defaultBranch = opts.SingleBranch + } repo := &repo_model.Repository{ OwnerID: owner.ID, Owner: owner, @@ -77,7 +82,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork Name: opts.Name, LowerName: strings.ToLower(opts.Name), Description: opts.Description, - DefaultBranch: opts.BaseRepo.DefaultBranch, + DefaultBranch: defaultBranch, IsPrivate: opts.BaseRepo.IsPrivate || opts.BaseRepo.Owner.Visibility == structs.VisibleTypePrivate, IsEmpty: opts.BaseRepo.IsEmpty, IsFork: true, @@ -134,9 +139,15 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork needsRollback = true + var cloneCmd *git.Command + if opts.SingleBranch != "" { + cloneCmd = git.NewCommand(txCtx, "clone", "--bare", "--single-branch", "--branch") + cloneCmd = cloneCmd.AddDynamicArguments(opts.SingleBranch) + } else { + cloneCmd = git.NewCommand(txCtx, "clone", "--bare") + } repoPath := repo_model.RepoPath(owner.Name, repo.Name) - if stdout, _, err := git.NewCommand(txCtx, - "clone", "--bare").AddDynamicArguments(oldRepoPath, repoPath). + if stdout, _, err := cloneCmd.AddDynamicArguments(oldRepoPath, repoPath). SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", opts.BaseRepo.FullName(), repo.FullName())). RunStdBytes(&git.RunOpts{Timeout: 10 * time.Minute}); err != nil { log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err) diff --git a/templates/repo/pulls/fork.tmpl b/templates/repo/pulls/fork.tmpl index 525858c6aa391..3759c747f4a8c 100644 --- a/templates/repo/pulls/fork.tmpl +++ b/templates/repo/pulls/fork.tmpl @@ -51,6 +51,26 @@ {{.locale.Tr "repo.fork_visibility_helper"}} +
+ + +
From f1f0c68edbbbc77539c19eaf55944dd4adf277f0 Mon Sep 17 00:00:00 2001 From: Dmitry Sharshakov Date: Mon, 25 Sep 2023 09:10:25 +0300 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Denys Konovalov --- templates/repo/pulls/fork.tmpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/repo/pulls/fork.tmpl b/templates/repo/pulls/fork.tmpl index f0b5245853d28..5ffc40e4520c9 100644 --- a/templates/repo/pulls/fork.tmpl +++ b/templates/repo/pulls/fork.tmpl @@ -52,16 +52,16 @@ {{.locale.Tr "repo.fork_visibility_helper"}}
- +