func (c *Pull) Run(ctx *cli.Context) error { dir, err := os.Getwd() if err != nil { return errwrap.Wrapf("Failed to fetch current working dir: {{err}}", err) } vc, err := vcs.GetVCS(dir) if err != nil { return errwrap.Wrapf("Failed to setup VCS: {{err}}", err) } remote := ctx.Args().First() if remote == "" { remote, err = vc.DefaultRemote() if err != nil { return errwrap.Wrapf("Failed to determine default remote: {{err}}", err) } } err = vc.Pull(remote) if err != nil { if err == vcs.ErrNoRemoteTimeData { c.Printf("Remote '%s' has no time data (yet), nothing to pull\n", remote) return nil } return errwrap.Wrapf("Failed to pull time data: {{err}}", err) } c.Println("Time data was pulled successfully") return nil }
func TestApp_RunAsSubcommandParseFlags(t *testing.T) { var context *cli.Context a := cli.NewApp() a.Commands = []cli.Command{ { Name: "foo", Action: func(c *cli.Context) { context = c }, Flags: []cli.Flag{ cli.StringFlag{ Name: "lang", Value: "english", Usage: "language for the greeting", }, }, Before: func(_ *cli.Context) error { return nil }, }, } a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) expect(t, context.Args().Get(0), "abcd") expect(t, context.String("lang"), "spanish") }
func (c *Punch) Run(ctx *cli.Context) error { dir, err := os.Getwd() if err != nil { return errwrap.Wrapf("Failed to fetch current working dir: {{err}}", err) } var input string if isatty.IsTerminal(os.Stdin.Fd()) { c.Println("Reading input from argument...") input = ctx.Args().First() } else { c.Println("Reading input from Stdin...") bytes, err := ioutil.ReadAll(os.Stdin) if err != nil { return errwrap.Wrapf("Failed to read time from Stdin: {{err}}", err) } input = string(bytes) } if input == "" { return fmt.Errorf("Please provide the time you spent as the first argument") } t, err := time.ParseDuration(input) if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to parse provided argument '%s' as a valid duration (e.g 1h2m10s): {{err}}", input), err) } //write the vcs vc, err := vcs.GetVCS(dir) if err != nil { return errwrap.Wrapf("Failed to setup VCS: {{err}}", err) } c.Printf("Persisting %s to version control...", t) err = vc.Persist(t) if err != nil { return errwrap.Wrapf("Failed to log time into VCS: {{err}}", err) } c.Println("Done!") return nil }
func (c *Sum) Run(ctx *cli.Context) error { dir, err := os.Getwd() if err != nil { return errwrap.Wrapf("Failed to fetch current working dir: {{err}}", err) } //write the vcs vc, err := vcs.GetVCS(dir) if err != nil { return errwrap.Wrapf("Failed to setup VCS: {{err}}", err) } //retrieve commits through piped stdin or arguments commits := []string{} if !isatty.IsTerminal(os.Stdin.Fd()) { scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { commits = append(commits, scanner.Text()) } if err := scanner.Err(); err != nil { c.Println(err) } } else { if ctx.Args().First() != "" { commits = append(commits, ctx.Args().First()) } commits = append(commits, ctx.Args().Tail()...) } if len(commits) == 0 { return fmt.Errorf("Please provide at least one commit through STDIN or as an argument.") } //map time data from the vcs list := []vcs.TimeData{} for _, c := range commits { data, err := vc.Show(c) if err != nil { if err == vcs.ErrNoCommitTimeData { //ignore if a commit has no time attached continue } return errwrap.Wrapf(fmt.Sprintf("Failed to show time notes for '%s': {{err}}", c), err) } list = append(list, data) } //reduce to output var total time.Duration for _, data := range list { total += data.Total() } fmt.Fprintln(os.Stdout, total) return nil }
func (c *Status) Run(ctx *cli.Context) error { dir, err := os.Getwd() if err != nil { return errwrap.Wrapf("Failed to fetch current working dir: {{err}}", err) } vc, err := vcs.GetVCS(dir) if err != nil { return errwrap.Wrapf("Failed to setup VCS: {{err}}", err) } sysdir, err := daemon.SystemTimeglassPath() if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to get system config path: {{err}}"), err) } conf, err := config.ReadConfig(vc.Root(), sysdir) if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to read configuration: {{err}}"), err) } client := NewClient() //fetch information on overall daemon c.Printf("Fetching daemon info...") dinfo, err := client.Info() if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to fetch daemon info: {{err}}"), err) } curr, _ := strconv.Atoi(strings.Replace(dinfo["version"].(string), ".", "", 2)) recent, _ := strconv.Atoi(strings.Replace(dinfo["newest_version"].(string), ".", "", 2)) if curr != 0 && recent > curr { c.Println("A new version is available, please upgrade: https://github.com/timeglass/glass/releases") } //fetch information on the timer specific to this directory c.Printf("Fetching timer info...") timer, err := client.ReadTimer(vc.Root()) if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to fetch timer: {{err}}"), err) } if reason := timer.HasFailed(); reason != "" { c.Printf("Timer has failed: %s", reason) } else { if timer.IsPaused() { c.Printf("Timer is currently: PAUSED") } else { c.Printf("Timer is currently: RUNNING") } } tmpls := ctx.String("template") if ctx.Bool("commit-template") { tmpls = conf.CommitMessage } //we got some template specified if tmpls != "" { //parse temlate and only report error if we're talking to a human tmpl, err := template.New("commit-msg").Parse(tmpls) if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to parse commit_message: '%s' in configuration as a text/template: {{err}}", conf.CommitMessage), err) } //execute template and write to stdout err = tmpl.Execute(os.Stdout, timer.Time()) if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to execute commit_message: template for time '%s': {{err}}", timer.Time()), err) } } else { //just print c.Printf("Timer reads: %s", timer.Time()) } return nil }
func (c *Push) Run(ctx *cli.Context) error { dir, err := os.Getwd() if err != nil { return errwrap.Wrapf("Failed to fetch current working dir: {{err}}", err) } sysdir, err := daemon.SystemTimeglassPath() if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to get system config path: {{err}}"), err) } conf, err := config.ReadConfig(dir, sysdir) if err != nil { return errwrap.Wrapf(fmt.Sprintf("Failed to read configuration: {{err}}"), err) } //hooks require us require us to check the refs that are pushed over stdin //to prevent inifinte push loop refs := "" if !isatty.IsTerminal(os.Stdin.Fd()) { bytes, err := ioutil.ReadAll(os.Stdin) if err != nil { return errwrap.Wrapf("Failed to read from stdin: {{err}}", err) } refs = string(bytes) //when `glass push` triggers the pre-push hook it will not //provide any refs on stdin //this probalby means means there is nothing left to push and //we return here to prevent recursive push if refs == "" { return nil } //configuration can explicitly request not to push time data automatically //on hook usage if !conf.AutoPush { return nil } } vc, err := vcs.GetVCS(dir) if err != nil { return errwrap.Wrapf("Failed to setup VCS: {{err}}", err) } remote := ctx.Args().First() if remote == "" { remote, err = vc.DefaultRemote() if err != nil { return errwrap.Wrapf("Failed to determine default remote: {{err}}", err) } } err = vc.Push(remote, refs) if err != nil { if err == vcs.ErrNoLocalTimeData { c.Printf("Local clone has no time data (yet), nothing to push to '%s'. Start a timer and commit changes to record local time data.\n", remote) return nil } return errwrap.Wrapf("Failed to push time data: {{err}}", err) } return nil }