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
+73
-12
@@ -51,22 +51,83 @@ func (a *application) repoCommand() *cobra.Command {
|
||||
Long: `Work with Gitea repositories: list and view them, create, fork, clone and migrate them, keep
|
||||
local branches and forks in sync, and change their settings.`,
|
||||
}
|
||||
group.AddCommand(a.repoListCommand(), a.repoViewCommand(), a.repositorySyncCommand())
|
||||
group.AddCommand(&cobra.Command{Use: "set-default [repository]", Short: "Save the selected repository in local Git configuration", Annotations: textOutput("set-default configures Git"), Args: usageArgs(cobra.MaximumNArgs(1)), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := a.repositoryArgument(args); err != nil {
|
||||
return err
|
||||
}
|
||||
target, err := a.resolve(cmd.Context(), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = a.git(cmd.Context(), "config", "--local", "tea.repository", target.Host+"/"+target.Repo)
|
||||
return err
|
||||
}})
|
||||
group.AddCommand(a.repoListCommand(), a.repoViewCommand(), a.repositorySyncCommand(), a.repoSetDefaultCommand())
|
||||
a.addRepositoryMutations(group)
|
||||
return group
|
||||
}
|
||||
|
||||
func (a *application) repoSetDefaultCommand() *cobra.Command {
|
||||
var view, unset bool
|
||||
command := &cobra.Command{
|
||||
Use: "set-default [<repository>]",
|
||||
Short: "Set the default repository for this clone",
|
||||
Long: `Set the repository that tea commands use in the current Git clone, instead of the one found through
|
||||
its Git remotes. It is saved as tea.repository in the clone's Git configuration.
|
||||
|
||||
Without an argument, the repository that tea selects now is saved.`,
|
||||
Example: `# Make tea commands in this clone use the fork's parent
|
||||
$ tea repo set-default alice/project
|
||||
|
||||
# Show the saved repository
|
||||
$ tea repo set-default --view
|
||||
|
||||
# Go back to the repository of the Git remotes
|
||||
$ tea repo set-default --unset`,
|
||||
Annotations: map[string]string{"tea.arguments": repositoryArguments, "tea.text": "set-default configures Git"},
|
||||
Args: usageArgs(cobra.MaximumNArgs(1)),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
switch {
|
||||
case view && unset:
|
||||
return clierr.Wrap(clierr.Usage, errors.New("--view and --unset cannot be combined"))
|
||||
case (view || unset) && len(args) > 0:
|
||||
return clierr.Wrap(clierr.Usage, errors.New("--view and --unset take no repository"))
|
||||
}
|
||||
ctx := cmd.Context()
|
||||
if inside, _ := a.gitProbe().Output(ctx, a.options.cwd, false, "rev-parse", "--is-inside-work-tree"); inside != "true" {
|
||||
return clierr.Wrap(clierr.Usage, errors.New("set-default must run inside a Git clone"))
|
||||
}
|
||||
saved, _ := a.gitProbe().Output(ctx, a.options.cwd, false, "config", "--local", "--get", "tea.repository")
|
||||
switch {
|
||||
case view && saved == "":
|
||||
_, err := fmt.Fprintln(cmd.ErrOrStderr(), "no default repository is set for this clone")
|
||||
return err
|
||||
case view:
|
||||
_, err := fmt.Fprintln(cmd.OutOrStdout(), terminal.SafeLine(saved))
|
||||
return err
|
||||
case unset && saved == "":
|
||||
a.warn(cmd, "No default repository is set for this clone")
|
||||
return nil
|
||||
case unset:
|
||||
if _, err := a.git(ctx, "config", "--local", "--unset", "tea.repository"); err != nil {
|
||||
return err
|
||||
}
|
||||
a.done(cmd, "Removed the default repository %s from this clone", saved)
|
||||
return nil
|
||||
}
|
||||
if err := a.repositoryArgument(args); err != nil {
|
||||
return err
|
||||
}
|
||||
t, err := a.resolve(ctx, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
item, err := (services.Repositories{Client: t.client}).View(ctx, t.Repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := a.git(ctx, "config", "--local", "tea.repository", t.Host+"/"+item.FullName); err != nil {
|
||||
return err
|
||||
}
|
||||
a.done(cmd, "Set %s as the default repository for this clone", item.FullName)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
command.Flags().BoolVarP(&view, "view", "v", false, "Print the saved default repository")
|
||||
command.Flags().BoolVarP(&unset, "unset", "u", false, "Remove the saved default repository")
|
||||
command.ValidArgsFunction = a.completeRepos()
|
||||
return command
|
||||
}
|
||||
|
||||
func (a *application) repoListCommand() *cobra.Command {
|
||||
var opts services.RepositoryListOptions
|
||||
list := &cobra.Command{
|
||||
|
||||
Reference in new issue
Block a user