mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
feat(repo): sync forks on the server, wire forks into clones, validate set-default
repo sync OWNER/REPO, run where no Git remote points to the repository,
now updates it on the server: a fork's branch fast-forwards to its
parent's through merge-upstream, and a pull mirror fetches its source.
repo fork reports an existing fork ("! bob/x already exists") instead of
a raw HTTP 409, refuses to fork a repository into its own owner, and
gains --fork-name, --clone (Git flags after --) and --remote, which adds
the fork as origin and renames the old origin to upstream.
repo clone passes Git flags after --, and takes --upstream-remote-name
and --no-upstream for forks. Clones report what they set up.
repo set-default checks that the repository exists before saving it,
prints the saved repository with --view, removes it with --unset, and
reports the change.
Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
13 files changed
+599
-98
No files matched your search
@@ -184,13 +184,67 @@ func (s Repositories) Delete(ctx context.Context, repo string) error {
|
||||
})
|
||||
}
|
||||
|
||||
// Fork creates a fork for the current user or selected organization.
|
||||
func (s Repositories) Fork(ctx context.Context, repo, org string) (Repository, error) {
|
||||
// ForkOptions places a fork: under Organization instead of the account, and named Name instead
|
||||
// of the forked repository's name.
|
||||
type ForkOptions struct{ Organization, Name string }
|
||||
|
||||
// Fork forks repo for the account or the organization. When that owner already has a fork of
|
||||
// repo, Fork returns it and reports that it existed.
|
||||
func (s Repositories) Fork(ctx context.Context, repo string, opts ForkOptions) (Repository, bool, error) {
|
||||
var options gitea.CreateForkOption
|
||||
if org != "" {
|
||||
options.Organization = &org
|
||||
if opts.Organization != "" {
|
||||
options.Organization = &opts.Organization
|
||||
}
|
||||
return repoConvert(ctx, s.Client, repo, repositoryFrom, func(ctx context.Context, c *gitea.Client, owner, name string) (*gitea.Repository, *gitea.Response, error) {
|
||||
if opts.Name != "" {
|
||||
options.Name = &opts.Name
|
||||
}
|
||||
fork, err := repoConvert(ctx, s.Client, repo, repositoryFrom, func(ctx context.Context, c *gitea.Client, owner, name string) (*gitea.Repository, *gitea.Response, error) {
|
||||
return c.Repositories.CreateFork(ctx, owner, name, options)
|
||||
})
|
||||
apiErr, ok := errors.AsType[*transport.APIError](err)
|
||||
if !ok || apiErr.Status != http.StatusConflict || !strings.Contains(apiErr.Message, "already forked") {
|
||||
return fork, false, err
|
||||
}
|
||||
owner := opts.Organization
|
||||
if owner == "" {
|
||||
if owner, err = CurrentAccount(ctx, s.Client); err != nil {
|
||||
return Repository{}, false, err
|
||||
}
|
||||
}
|
||||
forks, listErr := listAll(func(page int) ([]*gitea.Repository, error) {
|
||||
return repoCall(ctx, s.Client, repo, func(ctx context.Context, c *gitea.Client, owner, name string) ([]*gitea.Repository, *gitea.Response, error) {
|
||||
return c.Repositories.ListForks(ctx, owner, name, gitea.ListForksOptions{ListOptions: listOptions(50, page)})
|
||||
})
|
||||
})
|
||||
if listErr != nil {
|
||||
return Repository{}, false, listErr
|
||||
}
|
||||
for _, existing := range forks {
|
||||
if existing.Owner != nil && strings.EqualFold(existing.Owner.UserName, owner) {
|
||||
// The fork list omits the parent that a fork's own record has.
|
||||
fork, err := s.View(ctx, existing.FullName)
|
||||
return fork, err == nil, err
|
||||
}
|
||||
}
|
||||
return Repository{}, false, apiErr
|
||||
}
|
||||
|
||||
// MergeUpstream fast-forwards branch of the fork repo to its parent's branch on the server. It
|
||||
// returns how Gitea updated the branch: "fast-forward", or "up-to-date" when there was nothing to do.
|
||||
func (s Repositories) MergeUpstream(ctx context.Context, repo, branch string) (string, error) {
|
||||
result, err := repoCall(ctx, s.Client, repo, func(ctx context.Context, c *gitea.Client, owner, name string) (*gitea.MergeUpstreamResponse, *gitea.Response, error) {
|
||||
return c.Repositories.MergeUpstream(ctx, owner, name, gitea.MergeUpstreamRequest{Branch: branch, FfOnly: true})
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.MergeStyle, nil
|
||||
}
|
||||
|
||||
// MirrorSync asks the server to update the pull mirror repo from its source; the update runs in
|
||||
// the background.
|
||||
func (s Repositories) MirrorSync(ctx context.Context, repo string) error {
|
||||
return repoDo(ctx, s.Client, repo, func(ctx context.Context, c *gitea.Client, owner, name string) (*gitea.Response, error) {
|
||||
return c.Repositories.MirrorSync(ctx, owner, name)
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user