Skip to content

Commit 5e02e3b

Browse files
dssengdenyskonlunnywxiaoguang
authored
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 <[email protected]> Co-authored-by: Lunny Xiao <[email protected]> Co-authored-by: wxiaoguang <[email protected]>
1 parent e8840e7 commit 5e02e3b

File tree

5 files changed

+57
-9
lines changed

5 files changed

+57
-9
lines changed

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,8 @@ fork_from = Fork From
943943
already_forked = You've already forked %s
944944
fork_to_different_account = Fork to a different account
945945
fork_visibility_helper = The visibility of a forked repository cannot be changed.
946+
fork_branch = Branch to be cloned to the fork
947+
all_branches = All branches
946948
fork_no_valid_owners = This repository can not be forked because there are no valid owners.
947949
use_template = Use this template
948950
clone_in_vsc = Clone in VS Code

routers/web/repo/pull.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,21 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
180180
return nil
181181
}
182182

183+
branches, err := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{
184+
RepoID: ctx.Repo.Repository.ID,
185+
ListOptions: db.ListOptions{
186+
ListAll: true,
187+
},
188+
IsDeletedBranch: util.OptionalBoolFalse,
189+
// Add it as the first option
190+
ExcludeBranchNames: []string{ctx.Repo.Repository.DefaultBranch},
191+
})
192+
if err != nil {
193+
ctx.ServerError("FindBranchNames", err)
194+
return nil
195+
}
196+
ctx.Data["Branches"] = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...)
197+
183198
return forkRepo
184199
}
185200

@@ -261,9 +276,10 @@ func ForkPost(ctx *context.Context) {
261276
}
262277

263278
repo, err := repo_service.ForkRepository(ctx, ctx.Doer, ctxUser, repo_service.ForkRepoOptions{
264-
BaseRepo: forkRepo,
265-
Name: form.RepoName,
266-
Description: form.Description,
279+
BaseRepo: forkRepo,
280+
Name: form.RepoName,
281+
Description: form.Description,
282+
SingleBranch: form.ForkSingleBranch,
267283
})
268284
if err != nil {
269285
ctx.Data["Err_RepoName"] = true

services/forms/repo_form.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ type CreateRepoForm struct {
5151
Labels bool
5252
ProtectedBranch bool
5353
TrustModel string
54+
55+
ForkSingleBranch string
5456
}
5557

5658
// Validate validates the fields

services/repository/fork.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ func (err ErrForkAlreadyExist) Unwrap() error {
4444

4545
// ForkRepoOptions contains the fork repository options
4646
type ForkRepoOptions struct {
47-
BaseRepo *repo_model.Repository
48-
Name string
49-
Description string
47+
BaseRepo *repo_model.Repository
48+
Name string
49+
Description string
50+
SingleBranch string
5051
}
5152

5253
// ForkRepository forks a repository
@@ -70,14 +71,18 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
7071
}
7172
}
7273

74+
defaultBranch := opts.BaseRepo.DefaultBranch
75+
if opts.SingleBranch != "" {
76+
defaultBranch = opts.SingleBranch
77+
}
7378
repo := &repo_model.Repository{
7479
OwnerID: owner.ID,
7580
Owner: owner,
7681
OwnerName: owner.Name,
7782
Name: opts.Name,
7883
LowerName: strings.ToLower(opts.Name),
7984
Description: opts.Description,
80-
DefaultBranch: opts.BaseRepo.DefaultBranch,
85+
DefaultBranch: defaultBranch,
8186
IsPrivate: opts.BaseRepo.IsPrivate || opts.BaseRepo.Owner.Visibility == structs.VisibleTypePrivate,
8287
IsEmpty: opts.BaseRepo.IsEmpty,
8388
IsFork: true,
@@ -134,9 +139,12 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
134139

135140
needsRollback = true
136141

142+
cloneCmd := git.NewCommand(txCtx, "clone", "--bare")
143+
if opts.SingleBranch != "" {
144+
cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(opts.SingleBranch)
145+
}
137146
repoPath := repo_model.RepoPath(owner.Name, repo.Name)
138-
if stdout, _, err := git.NewCommand(txCtx,
139-
"clone", "--bare").AddDynamicArguments(oldRepoPath, repoPath).
147+
if stdout, _, err := cloneCmd.AddDynamicArguments(oldRepoPath, repoPath).
140148
SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", opts.BaseRepo.FullName(), repo.FullName())).
141149
RunStdBytes(&git.RunOpts{Timeout: 10 * time.Minute}); err != nil {
142150
log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err)

templates/repo/pulls/fork.tmpl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,26 @@
5151
</div>
5252
<span class="help">{{ctx.Locale.Tr "repo.fork_visibility_helper"}}</span>
5353
</div>
54+
<div class="inline field">
55+
<label>{{ctx.Locale.Tr "repo.fork_branch"}}</label>
56+
<div class="ui selection dropdown">
57+
<input type="hidden" id="fork_single_branch" name="fork_single_branch" value="" required>
58+
<span class="text truncated-item-container" data-value="" title="{{ctx.Locale.Tr "repo.all_branches"}}">
59+
<span class="truncated-item-name">{{ctx.Locale.Tr "repo.all_branches"}}</span>
60+
</span>
61+
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
62+
<div class="menu">
63+
<div class="item truncated-item-container" data-value="" title="{{ctx.Locale.Tr "repo.all_branches"}}">
64+
<span class="truncated-item-name">{{ctx.Locale.Tr "repo.all_branches"}}</span>
65+
</div>
66+
{{range .Branches}}
67+
<div class="item truncated-item-container" data-value="{{.}}" title="{{.}}">
68+
<span class="truncated-item-name">{{.}}</span>
69+
</div>
70+
{{end}}
71+
</div>
72+
</div>
73+
</div>
5474
<div class="inline field {{if .Err_Description}}error{{end}}">
5575
<label for="description">{{ctx.Locale.Tr "repo.repo_desc"}}</label>
5676
<textarea id="description" name="description">{{.description}}</textarea>

0 commit comments

Comments
 (0)