mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	Add support for forking single branch (#25821)
Fixes #25117 Add UI for choosing branch to fork Change default branch on single-branch forks  --------- Co-authored-by: Denys Konovalov <kontakt@denyskon.de> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							e8840e7e2b
						
					
				
				
					commit
					5e02e3b7ee
				
			| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|  | ||||
| @@ -264,6 +279,7 @@ func ForkPost(ctx *context.Context) { | ||||
| 		BaseRepo:     forkRepo, | ||||
| 		Name:         form.RepoName, | ||||
| 		Description:  form.Description, | ||||
| 		SingleBranch: form.ForkSingleBranch, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.Data["Err_RepoName"] = true | ||||
|   | ||||
| @@ -51,6 +51,8 @@ type CreateRepoForm struct { | ||||
| 	Labels          bool | ||||
| 	ProtectedBranch bool | ||||
| 	TrustModel      string | ||||
|  | ||||
| 	ForkSingleBranch string | ||||
| } | ||||
|  | ||||
| // Validate validates the fields | ||||
|   | ||||
| @@ -47,6 +47,7 @@ type ForkRepoOptions struct { | ||||
| 	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) | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user