cmd

package
v0.9.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2020 License: GPL-3.0 Imports: 33 Imported by: 0

Documentation

Overview

Package cmd registers cobra commands for CLI tool. Some commands use an "app" build tag to speed up compilation while developing by ignoring UX specific dependencies (systray, webview)

Index

Constants

This section is empty.

Variables

View Source
var AddCmd = &cobra.Command{
	Use:   "add",
	Short: "Add a new task via command line",
	Long: `Define a new sync task using two URI and a direction.

Endpoint URI support the following schemes: 
 - router: Direct connexion to Cells server running on the same machine
 - fs:     Path to a local folder
 - s3:     S3 compliant
 - memdb:  In-memory DB for testing purposes

Direction can be:
 - Bi:     Bidirectionnal sync between two endpoints
 - Left:   Changes are only propagated from right to left
 - Right:  Changes are only propagated from left to right

Example
 - LeftUri : "router:///personal/admin/folder"
 - RightUri: "fs:///Users/name/Pydio/folder"
 - Direction: "Bi"

`,
	Run: func(cmd *cobra.Command, args []string) {

		t := &config.Task{
			Uuid: uuid.New(),
		}
		var e error
		l := &promptui.Prompt{Label: "Left endpoint URI"}
		r := &promptui.Prompt{Label: "Right endpoint URI"}
		s := promptui.Select{Label: "Sync Direction", Items: []string{"Bi", "Left", "Right"}}
		t.LeftURI, e = l.Run()
		if e != nil {
			exit(e)
		}
		t.RightURI, e = r.Run()
		if e != nil {
			exit(e)
		}
		_, t.Direction, e = s.Run()
		if e != nil {
			exit(e)
		}

		config.Default().Tasks = append(config.Default().Tasks, t)
		er := config.Save()
		if er != nil {
			exit(er)
		}

	},
}

AddCmd adds a task to the config via the command line

View Source
var AutoTestCmd = &cobra.Command{
	Use:   "autotest",
	Short: "Basic unidirectional sync between two local folders (under your temporary directory)",
	Run: func(cmd *cobra.Command, args []string) {

		tmpDir := os.TempDir()
		syncId := uuid.New()
		leftDir := filepath.Join(tmpDir, syncId, "left")
		os.MkdirAll(leftDir, 0777)
		rightDir := filepath.Join(tmpDir, syncId, "right")
		os.MkdirAll(rightDir, 0777)

		if !autoTestSkipClean {
			defer func() {
				fmt.Println("Cleaning resources after test (" + filepath.Join(tmpDir, syncId) + ")")
				os.RemoveAll(filepath.Join(tmpDir, syncId))
			}()
		}

		left, e := filesystem.NewFSClient(leftDir, model.EndpointOptions{})
		if e != nil {
			log.Fatal("cannot init left dir " + leftDir)
		}

		if e := ioutil.WriteFile(filepath.Join(leftDir, "basic-file.txt"), []byte("hello world"), 0755); e != nil {
			log.Fatal("cannot write a file for testing on left " + leftDir)
		}

		right, e := filesystem.NewFSClient(rightDir, model.EndpointOptions{})
		if e != nil {
			log.Fatal("cannot init right dir " + rightDir)
		}

		statusChan := make(chan model.Status)
		doneChan := make(chan interface{})
		waitChan := make(chan bool, 1)
		var err error

		syncTask := task.NewSync(left, right, model.DirectionRight)
		syncTask.SkipTargetChecks = true
		syncTask.Start(context.Background(), false)
		syncTask.SetupEventsChan(statusChan, doneChan, nil)

		go func() {
			defer func() {
				close(waitChan)
			}()
			for {
				select {
				case status := <-statusChan:
					fmt.Println("Task Status Received: ", status)
				case p := <-doneChan:
					if patch, ok := p.(merger.Patch); ok {
						fmt.Println("Patch Processing Finished")
						fmt.Println(patch.Stats())

						if patch.Size() == 0 {
							err = fmt.Errorf("processed patch has size 0, this is not normal")
							return
						}
						if data, e := ioutil.ReadFile(filepath.Join(rightDir, "basic-file.txt")); e != nil {
							err = fmt.Errorf("cannot read right file %v", e)
						} else if string(data) != "hello world" {
							err = fmt.Errorf("right file does not have proper content: %v", string(data))
						}
					} else {
						err = fmt.Errorf("doneChan did not send a patch")
					}
					return
				case <-time.After(30 * time.Second):
					err = fmt.Errorf("breaking test after 30s, this is not normal")
					return
				}
			}
		}()
		syncTask.Run(context.Background(), false, true)
		<-waitChan
		syncTask.Shutdown()
		if err != nil {
			log.Fatal(err)
		}
	},
}

AutoTestCmd performs a simple test of a unidirectional sync between two local folders (created inside TmpDir)

View Source
var CaptureCmd = &cobra.Command{
	Use:   "capture",
	Short: "Capture snapshots inside JSON file - do not perform any actual tasks",
	Run: func(cmd *cobra.Command, args []string) {

		if captureTarget == "" {
			log.Fatal("Please provide a target folder for storing JSON files")
		}

		ctx := servicecontext.WithServiceName(context.Background(), "supervisor")
		ctx = servicecontext.WithServiceColor(ctx, servicecontext.ServiceColorRest)

		conf := config.Default()
		if len(conf.Tasks) > 0 {
			for _, t := range conf.Tasks {

				leftEndpoint, err := endpoint.EndpointFromURI(t.LeftURI, t.RightURI)
				if err != nil {
					log.Fatal(err.Error())
				}
				rightEndpoint, err := endpoint.EndpointFromURI(t.RightURI, t.LeftURI)
				if err != nil {
					log.Fatal(err.Error())
				}

				var dir model.DirectionType
				switch t.Direction {
				case "Bi":
					dir = model.DirectionBi
				case "Left":
					dir = model.DirectionLeft
				case "Right":
					dir = model.DirectionRight
				default:
					log.Fatal("unsupported direction type, please use one of Bi, Left, Right")
				}

				syncTask := task.NewSync(leftEndpoint, rightEndpoint, dir)
				configPath := filepath.Join(config.SyncClientDataDir(), t.Uuid)
				syncTask.SetSnapshotFactory(endpoint.NewSnapshotFactory(configPath, leftEndpoint, rightEndpoint))
				e := syncTask.Capture(ctx, captureTarget)
				if e != nil {
					log.Fatal(e)
				} else {
					fmt.Println("Captured snapshots inside " + captureTarget)
				}

			}
		}

	},
}

CaptureCmd captures snapshots inside JSON file - do not perform any actual tasks

View Source
var DeleteCmd = &cobra.Command{
	Use:   "delete",
	Short: "Delete existing sync via command line",
	Run: func(cmd *cobra.Command, args []string) {
		tS := promptui.Select{Label: "Select Sync to Edit", Items: config.Default().Items()}
		i, _, e := tS.Run()
		if e != nil {
			exit(e)
		}
		tasks := config.Default().Tasks
		last := len(tasks) - 1
		lastTask := tasks[last]
		tasks[last] = tasks[i]
		tasks[i] = lastTask
		tasks = tasks[:last]
		config.Default().Tasks = tasks
		er := config.Save()
		if er != nil {
			exit(er)
		}

	},
}

DeleteCmd removes a task via the command line.

View Source
var EditCmd = &cobra.Command{
	Use:   "edit",
	Short: "Exit existing sync via command line",
	Run: func(cmd *cobra.Command, args []string) {
		tS := promptui.Select{Label: "Select Sync to Edit", Items: config.Default().Items()}
		i, _, e := tS.Run()
		if e != nil {
			exit(e)
		}

		task := config.Default().Tasks[i]
		l := &promptui.Prompt{Label: "Left endpoint URI", Default: task.LeftURI}
		r := &promptui.Prompt{Label: "Right endpoint URI", Default: task.RightURI}
		s := promptui.Select{Label: "Sync Direction", Items: []string{"Bi", "Left", "Right"}}
		task.LeftURI, e = l.Run()
		if e != nil {
			exit(e)
		}
		task.RightURI, e = r.Run()
		if e != nil {
			exit(e)
		}
		_, task.Direction, e = s.Run()
		if e != nil {
			exit(e)
		}
		er := config.Save()
		if er != nil {
			exit(er)
		}
	},
}

EditCmd edits a task via the command line

View Source
var RootCmd = &cobra.Command{
	Use:   os.Args[0],
	Short: "Cells Sync desktop client",
	Long: `Cells Sync desktop client.

Realtime, bidirectional synchronization tool for Pydio Cells server. 
Launching without command is the same as './cells-sync start' on Mac and Windows. 
`,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		log.Init()
		handleSignals()
	},
	Run: func(cmd *cobra.Command, args []string) {
		if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
			StartCmd.PreRun(cmd, args)
			StartCmd.Run(cmd, args)
		} else {
			cmd.Usage()
		}
	},
}

RootCmd is the Cobra root command

View Source
var ServiceCmd = &cobra.Command{
	Use:   "service",
	Short: "Manage service: install,uninstall,stop,start,restart",
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			log.Fatal("please provide one of install,uninstall,stop,start,restart,status")
		}
		if args[0] == "status" {
			s, e := config.Status()
			if e != nil {
				log.Fatal("Cannot get service status: ", e)
			}
			fmt.Print("Service status : ")
			switch s {
			case service.StatusUnknown:
				fmt.Println("Unknown")
			case service.StatusRunning:
				fmt.Println("Running")
			case service.StatusStopped:
				fmt.Println("Stopped")
			}
			return
		}
		if !config.AllowedServiceCmd(args[0]) {
			log.Fatal(fmt.Errorf("Valid actions are: %q\n", service.ControlAction))
		}
		if err := config.ControlAppService(config.ServiceCmd(args[0])); err != nil {
			log.Fatal(err)
		}
	},
}

ServiceCmd provides access to the service install, uninstall, start, stop commands.

View Source
var StartCmd = &cobra.Command{
	Use:   "start",
	Short: "Start Cells Sync and fork a process for starting system tray",
	PreRun: func(cmd *cobra.Command, args []string) {
		logs := config.Default().Logs
		os.MkdirAll(logs.Folder, 0755)
		log.RegisterWriteSyncer(zapcore.AddSync(&lumberjack.Logger{
			Filename:   filepath.Join(logs.Folder, "sync.log"),
			MaxAge:     logs.MaxAgeDays,
			MaxSize:    logs.MaxFilesSize,
			MaxBackups: logs.MaxFilesNumber,
		}))
	},
	Run: func(cmd *cobra.Command, args []string) {
		s := control.NewSupervisor(startNoUi)
		s.Serve()
	},
}

StartCmd starts the client.

View Source
var SystrayCmd = &cobra.Command{
	Use:   "systray",
	Short: "Launch Systray",
	Run: func(cmd *cobra.Command, args []string) {
		tray.Run(url)
	},
}

SystrayCmd starts the System Tray

View Source
var VersionCmd = &cobra.Command{
	Use:   "version",
	Short: "Display version",
	Run: func(cmd *cobra.Command, args []string) {
		common.PrintVersion()
	},
}

VersionCmd displays the current binary version

View Source
var WebviewCmd = &cobra.Command{
	Use:   "webview",
	Short: "Launch WebView",
	Run: func(cmd *cobra.Command, args []string) {
		lang := i18n.JsonLang()
		if lang != "" {
			url += "?lang=" + lang
		}
		w := webview.New(webview.Settings{
			Width:     900,
			Height:    600,
			Resizable: true,
			Title:     i18n.T("application.title"),
			URL:       url,
			Debug:     true,
			ExternalInvokeCallback: func(w webview.WebView, data string) {
				switch data {
				case "DOMContentLoaded":
					w.Bind("linkOpener", &LinkOpener{})
					break
				}
			},
		})

		w.Run()
	},
}

WebviewCmd opens a webview pointing to the http server URL.

Functions

This section is empty.

Types

type LinkOpener

type LinkOpener struct{}

LinkOpener is bound to JS inside the webview

func (*LinkOpener) Open

func (w *LinkOpener) Open(url string)

Open opens an url (http or file) using OS stuff.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL