aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Sharshakov <d3dx12.xx@gmail.com>2023-09-29 04:48:39 +0300
committerGitHub <noreply@github.com>2023-09-29 09:48:39 +0800
commit5e02e3b7ee8294e2ec94968ece9af56bf1aa1534 (patch)
tree038e8619ee6b08b0c9ebd9be183ba190a1bc27f2
parente8840e7e2b6c4eaf6fa78dad49a29709ef35217b (diff)
downloadgitea-5e02e3b7ee8294e2ec94968ece9af56bf1aa1534.tar.gz
gitea-5e02e3b7ee8294e2ec94968ece9af56bf1aa1534.zip
Add support for forking single branch (#25821)
Fixes #25117 Add UI for choosing branch to fork Change default branch on single-branch forks ![image](https://github.com/go-gitea/gitea/assets/19504461/28505f69-a9a2-43a8-8b19-a0cdac3ddc5a) --------- Co-authored-by: Denys Konovalov <kontakt@denyskon.de> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
-rw-r--r--options/locale/locale_en-US.ini2
-rw-r--r--routers/web/repo/pull.go22
-rw-r--r--services/forms/repo_form.go2
-rw-r--r--services/repository/fork.go20
-rw-r--r--templates/repo/pulls/fork.tmpl20
5 files changed, 57 insertions, 9 deletions
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index de25392d88..77e7f2b7de 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -943,6 +943,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
fork_no_valid_owners = This repository can not be forked because there are no valid owners.
use_template = Use this template
clone_in_vsc = Clone in VS Code
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 63dfd0f7b5..6e69811901 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -180,6 +180,21 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
return nil
}
+ 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{ctx.Repo.Repository.DefaultBranch},
+ })
+ if err != nil {
+ ctx.ServerError("FindBranchNames", err)
+ return nil
+ }
+ ctx.Data["Branches"] = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...)
+
return forkRepo
}
@@ -261,9 +276,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 b36c8cc9b6..5df7ec8fd6 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -51,6 +51,8 @@ type CreateRepoForm struct {
Labels bool
ProtectedBranch bool
TrustModel string
+
+ ForkSingleBranch string
}
// Validate validates the fields
diff --git a/services/repository/fork.go b/services/repository/fork.go
index 397e4cb909..d5ab42badd 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,12 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
needsRollback = true
+ cloneCmd := git.NewCommand(txCtx, "clone", "--bare")
+ if opts.SingleBranch != "" {
+ cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(opts.SingleBranch)
+ }
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 57d2269807..94de4d78eb 100644
--- a/templates/repo/pulls/fork.tmpl
+++ b/templates/repo/pulls/fork.tmpl
@@ -51,6 +51,26 @@
</div>
<span class="help">{{ctx.Locale.Tr "repo.fork_visibility_helper"}}</span>
</div>
+ <div class="inline field">
+ <label>{{ctx.Locale.Tr "repo.fork_branch"}}</label>
+ <div class="ui selection dropdown">
+ <input type="hidden" id="fork_single_branch" name="fork_single_branch" value="" required>
+ <span class="text truncated-item-container" data-value="" title="{{ctx.Locale.Tr "repo.all_branches"}}">
+ <span class="truncated-item-name">{{ctx.Locale.Tr "repo.all_branches"}}</span>
+ </span>
+ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
+ <div class="menu">
+ <div class="item truncated-item-container" data-value="" title="{{ctx.Locale.Tr "repo.all_branches"}}">
+ <span class="truncated-item-name">{{ctx.Locale.Tr "repo.all_branches"}}</span>
+ </div>
+ {{range .Branches}}
+ <div class="item truncated-item-container" data-value="{{.}}" title="{{.}}">
+ <span class="truncated-item-name">{{.}}</span>
+ </div>
+ {{end}}
+ </div>
+ </div>
+ </div>
<div class="inline field {{if .Err_Description}}error{{end}}">
<label for="description">{{ctx.Locale.Tr "repo.repo_desc"}}</label>
<textarea id="description" name="description">{{.description}}</textarea>