added push mirror and command (#887)

* added push mirror and command

* reformatted push code to separate from pull mirror

* restructured mirror calls

* fixed typo in long description, changed maxArgs to exactArgs, added edit call for pull mirror

* made url and direction required, passing allow-divergence now warns when used with pull mirror, added separate options struct for both push and pull mirror calls

* add prject url to be specified as argument

Co-authored-by: NikhilMJagtap <nikhil.jagtap@workindia.in>
Co-authored-by: Clement Sam <clementsam75@gmail.com>
This commit is contained in:
Nikhil Jagtap 2021-12-20 23:07:03 +05:30 committed by GitHub
parent e866496799
commit 69fad1fe3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 225 additions and 0 deletions

53
api/mirror.go Normal file
View File

@ -0,0 +1,53 @@
package api
import (
"github.com/xanzy/go-gitlab"
)
type CreatePushMirrorOptions struct {
Url string
Enabled bool
OnlyProtectedBranches bool
KeepDivergentRefs bool
}
type CreatePullMirrorOptions struct {
Url string
Enabled bool
OnlyProtectedBranches bool
}
var CreatePushMirror = func(
client *gitlab.Client,
projectID interface{},
opts *CreatePushMirrorOptions,
) (*gitlab.ProjectMirror, error) {
if client == nil {
client = apiClient.Lab()
}
opt := &gitlab.AddProjectMirrorOptions{
URL: &opts.Url,
Enabled: &opts.Enabled,
OnlyProtectedBranches: &opts.OnlyProtectedBranches,
KeepDivergentRefs: &opts.KeepDivergentRefs,
}
pm, _, err := client.ProjectMirrors.AddProjectMirror(projectID, opt)
return pm, err
}
var CreatePullMirror = func(
client *gitlab.Client,
projectID interface{},
opts *CreatePullMirrorOptions,
) error {
if client == nil {
client = apiClient.Lab()
}
opt := &gitlab.EditProjectOptions{
ImportURL: &opts.Url,
Mirror: &opts.Enabled,
OnlyMirrorProtectedBranches: &opts.OnlyProtectedBranches,
}
_, _, err := client.Projects.EditProject(projectID, opt)
return err
}

View File

@ -0,0 +1,170 @@
package mirror
import (
"errors"
"fmt"
"strings"
"github.com/profclems/glab/api"
"github.com/profclems/glab/commands/cmdutils"
"github.com/profclems/glab/internal/glrepo"
"github.com/profclems/glab/pkg/iostreams"
"github.com/spf13/cobra"
"github.com/xanzy/go-gitlab"
)
type MirrorOptions struct {
URL string
Direction string
Enabled bool
ProtectedBranchesOnly bool
AllowDivergence bool
ProjectID int
IO *iostreams.IOStreams
BaseRepo glrepo.Interface
APIClient func() (*gitlab.Client, error)
httpClient *gitlab.Client
}
func NewCmdMirror(f *cmdutils.Factory) *cobra.Command {
opts := MirrorOptions{
IO: f.IO,
}
var projectMirrorCmd = &cobra.Command{
Use: "mirror [ID | URL | PATH] [flags]",
Short: "Mirror a project/repository",
Long: `Mirrors a project/repository to the specified location using pull or push method.`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var err error
opts.APIClient = f.HttpClient
if len(args) > 0 {
opts.BaseRepo, err = glrepo.FromFullName(args[0])
if err != nil {
return err
}
opts.APIClient = func() (*gitlab.Client, error) {
if opts.httpClient != nil {
return opts.httpClient, nil
}
cfg, err := f.Config()
if err != nil {
return nil, err
}
c, err := api.NewClientWithCfg(opts.BaseRepo.RepoHost(), cfg, false)
if err != nil {
return nil, err
}
opts.httpClient = c.Lab()
return opts.httpClient, nil
}
} else {
opts.BaseRepo, err = f.BaseRepo()
if err != nil {
return err
}
}
if opts.Direction != "pull" && opts.Direction != "push" {
return cmdutils.WrapError(
errors.New("invalid choice for --direction"),
"argument direction value should be pull or push",
)
}
if opts.Direction == "pull" && opts.AllowDivergence {
fmt.Fprintf(
f.IO.StdOut,
"[Warning] allow-divergence flag has no effect for pull mirror and is ignored.\n",
)
}
opts.URL = strings.TrimSpace(opts.URL)
opts.httpClient, err = opts.APIClient()
if err != nil {
return err
}
project, err := opts.BaseRepo.Project(opts.httpClient)
if err != nil {
return err
}
opts.ProjectID = project.ID
return runProjectMirror(&opts)
},
}
projectMirrorCmd.Flags().StringVar(&opts.URL, "url", "", "The target URL to which the repository is mirrored.")
projectMirrorCmd.Flags().StringVar(&opts.Direction, "direction", "pull", "Mirror direction")
projectMirrorCmd.Flags().BoolVar(&opts.Enabled, "enabled", true, "Determines if the mirror is enabled.")
projectMirrorCmd.Flags().BoolVar(&opts.ProtectedBranchesOnly, "protected-branches-only", false, "Determines if only protected branches are mirrored.")
projectMirrorCmd.Flags().BoolVar(&opts.AllowDivergence, "allow-divergence", false, "Determines if divergent refs are skipped.")
_ = projectMirrorCmd.MarkFlagRequired("url")
_ = projectMirrorCmd.MarkFlagRequired("direction")
return projectMirrorCmd
}
func runProjectMirror(opts *MirrorOptions) error {
if opts.Direction == "push" {
return createPushMirror(opts)
} else {
return createPullMirror(opts)
}
}
func createPushMirror(opts *MirrorOptions) error {
var pm *gitlab.ProjectMirror
var err error
var pushOptions = api.CreatePushMirrorOptions{
Url: opts.URL,
Enabled: opts.Enabled,
OnlyProtectedBranches: opts.ProtectedBranchesOnly,
KeepDivergentRefs: opts.AllowDivergence,
}
pm, err = api.CreatePushMirror(
opts.httpClient,
opts.ProjectID,
&pushOptions,
)
if err != nil {
return cmdutils.WrapError(err, "Failed to create Push Mirror")
}
greenCheck := opts.IO.Color().Green("✓")
fmt.Fprintf(
opts.IO.StdOut,
"%s Created Push Mirror for %s (%d) on GitLab at %s (%d)\n",
greenCheck, pm.URL, pm.ID, opts.BaseRepo.FullName(), opts.ProjectID,
)
return err
}
func createPullMirror(opts *MirrorOptions) error {
var pullOptions = api.CreatePullMirrorOptions{
Url: opts.URL,
Enabled: opts.Enabled,
OnlyProtectedBranches: opts.ProtectedBranchesOnly,
}
err := api.CreatePullMirror(
opts.httpClient,
opts.ProjectID,
&pullOptions,
)
if err != nil {
return cmdutils.WrapError(err, "Failed to create Pull Mirror")
}
greenCheck := opts.IO.Color().Green("✓")
fmt.Fprintf(
opts.IO.StdOut,
"%s Created Pull Mirror for %s on GitLab at %s (%d)\n",
greenCheck, opts.URL, opts.BaseRepo.FullName(), opts.ProjectID,
)
return err
}

View File

@ -8,6 +8,7 @@ import (
repoCmdCreate "github.com/profclems/glab/commands/project/create"
repoCmdDelete "github.com/profclems/glab/commands/project/delete"
repoCmdFork "github.com/profclems/glab/commands/project/fork"
repoCmdMirror "github.com/profclems/glab/commands/project/mirror"
repoCmdSearch "github.com/profclems/glab/commands/project/search"
repoCmdView "github.com/profclems/glab/commands/project/view"
@ -30,6 +31,7 @@ func NewCmdRepo(f *cmdutils.Factory) *cobra.Command {
repoCmd.AddCommand(repoCmdFork.NewCmdFork(f, nil))
repoCmd.AddCommand(repoCmdSearch.NewCmdSearch(f))
repoCmd.AddCommand(repoCmdView.NewCmdView(f))
repoCmd.AddCommand(repoCmdMirror.NewCmdMirror(f))
return repoCmd
}