diff --git a/command/clean.go b/command/clean.go index dd95dc6..948e72c 100644 --- a/command/clean.go +++ b/command/clean.go @@ -34,6 +34,7 @@ Options: -yes Delete time data without asking for confirmation. -terminal-only Only delete terminal time data + -app-only Only delete apps time data -days=0 Delete starting from n days in the past ` return strings.TrimSpace(helpText) @@ -41,11 +42,12 @@ Options: // Run executes clean command with args func (c CleanCmd) Run(args []string) int { - var yes, terminalOnly bool + var yes, terminalOnly, appOnly bool var days int cmdFlags := flag.NewFlagSet("clean", flag.ContinueOnError) cmdFlags.BoolVar(&yes, "yes", false, "") cmdFlags.BoolVar(&terminalOnly, "terminal-only", false, "") + cmdFlags.BoolVar(&appOnly, "app-only", false, "") cmdFlags.IntVar(&days, "days", 0, "") cmdFlags.Usage = func() { c.UI.Output(c.Help()) } if err := cmdFlags.Parse(args); err != nil { @@ -62,7 +64,7 @@ func (c CleanCmd) Run(args []string) int { } if confirm { - if err := project.Clean(util.AfterNow(days), terminalOnly); err != nil { + if err := project.Clean(util.AfterNow(days), terminalOnly, appOnly); err != nil { c.UI.Error(err.Error()) return 1 } diff --git a/command/clean_test.go b/command/clean_test.go index 06e7089..5e72117 100644 --- a/command/clean_test.go +++ b/command/clean_test.go @@ -6,9 +6,11 @@ package command import ( "os" + "path/filepath" "strings" "testing" + "github.com/git-time-metric/gtm/project" "github.com/git-time-metric/gtm/util" "github.com/mitchellh/cli" ) @@ -51,6 +53,37 @@ func TestTerminalOnly(t *testing.T) { } } +func TestAppOnly(t *testing.T) { + repo := util.NewTestRepo(t, false) + defer repo.Remove() + repo.Seed() + os.Chdir(repo.Workdir()) + + repo.SaveFile("browser.app", project.GTMDir, "") + repo.SaveFile("1458496803.event", project.GTMDir, filepath.Join("event", "event.go")) + repo.SaveFile("1458497804.event", project.GTMDir, filepath.Join(project.GTMDir, "browser.app")) + + (InitCmd{UI: new(cli.MockUi)}).Run([]string{}) + + ui := new(cli.MockUi) + c := CleanCmd{UI: ui} + + args := []string{"-app-only", "-yes"} + rc := c.Run(args) + + if rc != 0 { + t.Errorf("gtm clean(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter.String()) + } + + if !repo.FileExists("1458496803.event", project.GTMDir) { + t.Errorf("gtm clean(%+v), want non-app event to not be deleted, but was deleted", args) + } + + if repo.FileExists("1458497804.event", project.GTMDir) { + t.Errorf("gtm clean(%+v), want app event to be deleted, but was found", args) + } +} + func TestCleanInvalidOption(t *testing.T) { ui := new(cli.MockUi) c := CleanCmd{UI: ui} diff --git a/command/record.go b/command/record.go index c0d9559..1cb7375 100644 --- a/command/record.go +++ b/command/record.go @@ -8,6 +8,7 @@ import ( "bytes" "flag" "fmt" + "io/ioutil" "os" "path/filepath" "strings" @@ -50,7 +51,7 @@ func (c RecordCmd) Help() string { helpText := ` Usage: gtm record [options] [/path/file] - Record file or terminal events. + Record file or app events. Options: @@ -58,18 +59,21 @@ Options: -status=false Return total time recorded for event. - -long-duration=false Return total time recorded in long duration format + -long-duration=false Return total time recorded in long duration format. + + -app=false Record an app event. ` return strings.TrimSpace(helpText) } // Run executes record command with args func (c RecordCmd) Run(args []string) int { - var status, terminal, longDuration bool + var status, terminal, longDuration, app bool cmdFlags := flag.NewFlagSet("record", flag.ContinueOnError) cmdFlags.BoolVar(&status, "status", false, "") cmdFlags.BoolVar(&terminal, "terminal", false, "") cmdFlags.BoolVar(&longDuration, "long-duration", false, "") + cmdFlags.BoolVar(&app, "app", false, "") cmdFlags.Usage = func() { c.UI.Output(c.Help()) } if err := cmdFlags.Parse(args); err != nil { return 1 @@ -82,21 +86,20 @@ func (c RecordCmd) Run(args []string) int { var fileToRecord string if terminal { - projPath, err := scm.GitRepoPath() - if err != nil { - // if not found, ignore error - return 0 - } - projPath, err = scm.Workdir(projPath) - if err != nil { - // if not found, ignore error - return 0 - } - fileToRecord = filepath.Join(projPath, ".gtm", "terminal.app") + fileToRecord = "terminal" + app = true } else { fileToRecord = cmdFlags.Args()[0] } + if app { + fileToRecord = c.appToFile(fileToRecord) + } + + if !(0 <= len(fileToRecord)) { + return 0 + } + if err := event.Record(fileToRecord); err != nil && !(err == project.ErrNotInitialized || err == project.ErrFileNotFound) { return 1 } else if err == nil && status { @@ -139,6 +142,33 @@ func (c RecordCmd) Run(args []string) int { return 0 } +// Given an app name creates (if it not was already created) the file ".gtm/{name}.app" +// that we use to track events, and returns the full path +func (c RecordCmd) appToFile(appName string) string { + if !(len(appName) > 0) { + return "" + } + projPath, err := scm.GitRepoPath() + if err != nil { + return "" + } + projPath, err = scm.Workdir(projPath) + if err != nil { + return "" + } + + var file = filepath.Join(projPath, ".gtm", appName+".app") + + if _, err := os.Stat(file); os.IsNotExist(err) { + ioutil.WriteFile( + file, + []byte{}, + 0644) + } + + return file +} + // Synopsis returns help func (c RecordCmd) Synopsis() string { return "Record file and terminal events" diff --git a/command/record_test.go b/command/record_test.go index d8a4f12..036f8bb 100644 --- a/command/record_test.go +++ b/command/record_test.go @@ -235,6 +235,45 @@ func TestRecordTerminalWithStatus(t *testing.T) { t.Errorf("gtm record(%+v), want 1 event file got %d, %s", args, cnt, ui.ErrorWriter.String()) } } + +func TestRecordApp(t *testing.T) { + repo := util.NewTestRepo(t, false) + defer repo.Remove() + repo.Seed() + workdir := repo.Workdir() + os.Chdir(workdir) + + (InitCmd{UI: new(cli.MockUi)}).Run([]string{}) + + ui := new(cli.MockUi) + c := RecordCmd{UI: ui} + + args := []string{"-app", "browser"} + rc := c.Run(args) + + if rc != 0 { + t.Errorf("gtm record(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter) + } + + if _, err := os.Stat(filepath.Join(workdir, ".gtm", "browser.app")); os.IsNotExist(err) { + t.Errorf("gtm record(%+v), want .app file to be created, it was not created", args) + } + + files, err := ioutil.ReadDir(filepath.Join(workdir, ".gtm")) + if err != nil { + t.Fatalf("gtm record(%+v), want error nil got %s", args, err) + } + cnt := 1 + for _, f := range files { + if filepath.Base(f.Name()) == ".event" { + cnt++ + } + } + if cnt != 1 { + t.Errorf("gtm record(%+v), want 1 event file got %d, %s", args, cnt, ui.ErrorWriter.String()) + } +} + func TestRecordInvalidOption(t *testing.T) { ui := new(cli.MockUi) c := RecordCmd{UI: ui} diff --git a/command/report.go b/command/report.go index 928200e..7ebeda7 100644 --- a/command/report.go +++ b/command/report.go @@ -46,6 +46,7 @@ Options: -format=commits Specify report format [summary|project|commits|files|timeline-hours|timeline-commits] (default commits) -full-message=false Include full commit message -terminal-off=false Exclude time spent in terminal (Terminal plug-in is required) + -app-off=false Exclude time spent in apps -force-color=false Always output color even if no terminal is detected, i.e 'gtm report -color | less -R' -testing=false This is used for automated testing to force default test path @@ -76,12 +77,13 @@ Options: // Run executes report command with args func (c ReportCmd) Run(args []string) int { var limit int - var color, terminalOff, fullMessage, testing bool + var color, terminalOff, appOff, fullMessage, testing bool var today, yesterday, thisWeek, lastWeek, thisMonth, lastMonth, thisYear, lastYear, all bool var fromDate, toDate, message, author, tags, format string cmdFlags := flag.NewFlagSet("report", flag.ContinueOnError) cmdFlags.BoolVar(&color, "force-color", false, "") cmdFlags.BoolVar(&terminalOff, "terminal-off", false, "") + cmdFlags.BoolVar(&appOff, "app-off", false, "") cmdFlags.StringVar(&format, "format", "commits", "") cmdFlags.IntVar(&limit, "n", 0, "") cmdFlags.BoolVar(&fullMessage, "full-message", false, "") @@ -222,6 +224,7 @@ func (c ReportCmd) Run(args []string) int { options := report.OutputOptions{ FullMessage: fullMessage, TerminalOff: terminalOff, + AppOff: appOff, Color: color, Limit: limit} diff --git a/command/report_test.go b/command/report_test.go index 0106004..3d1fdb6 100644 --- a/command/report_test.go +++ b/command/report_test.go @@ -256,6 +256,49 @@ func TestReportFiles(t *testing.T) { } } +func TestReportAppsOff(t *testing.T) { + repo := util.NewTestRepo(t, false) + defer repo.Remove() + os.Chdir(repo.Workdir()) + + (InitCmd{UI: new(cli.MockUi)}).Run([]string{}) + + repo.SaveFile("event.go", "event", "") + repo.SaveFile("browser.app", project.GTMDir, "") + repo.SaveFile("1458496803.event", project.GTMDir, filepath.Join("event", "event.go")) + repo.SaveFile("1458496818.event", project.GTMDir, filepath.Join(project.GTMDir, "browser.app")) + + repo.Commit(repo.Stage(filepath.Join("event", "event.go"))) + + // save notes to git repository + (CommitCmd{UI: new(cli.MockUi)}).Run([]string{"-yes"}) + + ui := new(cli.MockUi) + c := ReportCmd{UI: ui} + + // Including apps + args := []string{"-format", "files", "-testing=true"} + rc := c.Run(args) + if rc != 0 { + t.Errorf("gtm report(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter.String()) + } + if !strings.Contains(ui.OutputWriter.String(), "Browser") { + t.Errorf("gtm report(%+v), want 'Browser' got %s, %s", args, ui.OutputWriter.String(), ui.ErrorWriter.String()) + } + + // Excluding apps + ui.OutputWriter.Reset() + ui.ErrorWriter.Reset() + args = []string{"-app-off", "-format", "files", "-testing=true"} + rc = c.Run(args) + if rc != 0 { + t.Errorf("gtm report(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter.String()) + } + if strings.Contains(ui.OutputWriter.String(), "Browser") { + t.Errorf("gtm report(%+v), want not 'Browser' got %s, %s", args, ui.OutputWriter.String(), ui.ErrorWriter.String()) + } +} + func TestReportInvalidOption(t *testing.T) { ui := new(cli.MockUi) c := ReportCmd{UI: ui} diff --git a/command/status.go b/command/status.go index 87abd91..bb6e1e6 100644 --- a/command/status.go +++ b/command/status.go @@ -38,6 +38,8 @@ Options: -terminal-off=false Exclude time spent in terminal (Terminal plug-in is required) + -app-off=false Exclude time spent in apps + -color=false Always output color even if no terminal is detected, i.e 'gtm status -color | less -R' -total-only=false Only display total pending time @@ -53,11 +55,12 @@ Options: // Run executes status command with args func (c StatusCmd) Run(args []string) int { - var color, terminalOff, totalOnly, all, profile, longDuration bool + var color, terminalOff, appOff, totalOnly, all, profile, longDuration bool var tags string cmdFlags := flag.NewFlagSet("status", flag.ContinueOnError) cmdFlags.BoolVar(&color, "color", false, "Always output color even if no terminal is detected. Use this with pagers i.e 'less -R' or 'more -R'") cmdFlags.BoolVar(&terminalOff, "terminal-off", false, "Exclude time spent in terminal (Terminal plugin is required)") + cmdFlags.BoolVar(&appOff, "app-off", false, "Exclude time spent in apps") cmdFlags.BoolVar(&totalOnly, "total-only", false, "Only display total time") cmdFlags.BoolVar(&longDuration, "long-duration", false, "Display total time in long duration format") cmdFlags.StringVar(&tags, "tags", "", "Project tags to show status on") @@ -100,6 +103,7 @@ func (c StatusCmd) Run(args []string) int { TotalOnly: totalOnly, LongDuration: longDuration, TerminalOff: terminalOff, + AppOff: appOff, Color: color} for _, projPath := range projects { diff --git a/command/status_test.go b/command/status_test.go index f024782..434a8ed 100644 --- a/command/status_test.go +++ b/command/status_test.go @@ -6,9 +6,11 @@ package command import ( "os" + "path/filepath" "strings" "testing" + "github.com/git-time-metric/gtm/project" "github.com/git-time-metric/gtm/util" "github.com/mitchellh/cli" ) @@ -51,6 +53,43 @@ func TestStatusTotalOnly(t *testing.T) { } } +func TestStatusAppOff(t *testing.T) { + repo := util.NewTestRepo(t, false) + defer repo.Remove() + repo.Seed() + os.Chdir(repo.Workdir()) + + repo.SaveFile("browser.app", project.GTMDir, "") + repo.SaveFile("1458496803.event", project.GTMDir, filepath.Join("event", "event.go")) + repo.SaveFile("1458497804.event", project.GTMDir, filepath.Join(project.GTMDir, "browser.app")) + + (InitCmd{UI: new(cli.MockUi)}).Run([]string{}) + + ui := new(cli.MockUi) + c := StatusCmd{UI: ui} + + // Including apps + args := []string{""} + rc := c.Run(args) + if rc != 0 { + t.Errorf("gtm status(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter.String()) + } + if !strings.Contains(ui.OutputWriter.String(), "event.go") || !strings.Contains(ui.OutputWriter.String(), "Browser") { + t.Errorf("gtm status(%+v), want 'event.go' and 'Browser' got %s", args, ui.OutputWriter.String()) + } + ui.OutputWriter.Reset() + + // Not including apps + args = []string{"-app-off"} + rc = c.Run(args) + if rc != 0 { + t.Errorf("gtm status(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter.String()) + } + if !strings.Contains(ui.OutputWriter.String(), "event.go") || strings.Contains(ui.OutputWriter.String(), "Browser") { + t.Errorf("gtm status(%+v), want 'event.go' and not 'Browser' got %s", args, ui.OutputWriter.String()) + } +} + func TestStatusInvalidOption(t *testing.T) { ui := new(cli.MockUi) c := StatusCmd{UI: ui} @@ -62,6 +101,6 @@ func TestStatusInvalidOption(t *testing.T) { t.Errorf("gtm status(%+v), want 0 got %d, %s", args, rc, ui.ErrorWriter) } if !strings.Contains(ui.OutputWriter.String(), "Usage:") { - t.Errorf("gtm status(%+v), want 'Usage:' got %d, %s", args, rc, ui.OutputWriter.String()) + t.Errorf("gtm status(%+v), want 'Usage:' got %d, %s", args, rc, ui.OutputWriter.String()) } } diff --git a/note/note.go b/note/note.go index 71cf354..285e6d2 100644 --- a/note/note.go +++ b/note/note.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" + "github.com/git-time-metric/gtm/project" "github.com/git-time-metric/gtm/util" ) @@ -31,6 +32,17 @@ func (n CommitNote) FilterOutTerminal() CommitNote { return CommitNote{Files: fds} } +// FilterOutApp filters out app time from commit note +func (n CommitNote) FilterOutApp() CommitNote { + fds := []FileDetail{} + for _, f := range n.Files { + if !f.IsApp() { + fds = append(fds, f) + } + } + return CommitNote{Files: fds} +} + // Total returns the total time for a commit note func (n CommitNote) Total() int { total := 0 @@ -191,6 +203,18 @@ func (f *FileDetail) IsTerminal() bool { return f.SourceFile == ".gtm/terminal.app" } +// IsApp returns true if file is an app event +func (f *FileDetail) IsApp() bool { + return project.AppEventFileContentRegex.MatchString(f.SourceFile) +} + +// GetAppName returns the name of the App +func (f *FileDetail) GetAppName() string { + name := project.AppEventFileContentRegex.FindStringSubmatch(f.SourceFile)[1] + name = util.UcFirst(name) + return name +} + // FileByTime is list of FileDetails type FileByTime []FileDetail diff --git a/project/project.go b/project/project.go index b7aac11..f3ab0a1 100644 --- a/project/project.go +++ b/project/project.go @@ -26,6 +26,8 @@ var ( ErrNotInitialized = errors.New("Git Time Metric is not initialized") // ErrFileNotFound is raised when record an event for a file that does not exist ErrFileNotFound = errors.New("File does not exist") + // AppEventFileContentRegex regex for app event files + AppEventFileContentRegex = regexp.MustCompile(`\.gtm[\\/](?P.*)\.app`) ) var ( @@ -267,7 +269,7 @@ func Uninitialize() (string, error) { } //Clean removes any event or metrics files from project in the current working directory -func Clean(dr util.DateRange, terminalOnly bool) error { +func Clean(dr util.DateRange, terminalOnly bool, appOnly bool) error { wd, err := os.Getwd() if err != nil { return err @@ -300,16 +302,25 @@ func Clean(dr util.DateRange, terminalOnly bool) error { if !dr.Within(f.ModTime()) { continue } + fp := filepath.Join(gtmPath, f.Name()) - if terminalOnly && strings.HasSuffix(f.Name(), ".event") { + if (terminalOnly || appOnly) && strings.HasSuffix(f.Name(), ".event") { b, err := ioutil.ReadFile(fp) if err != nil { return err } - if !strings.Contains(string(b), "terminal.app") { - continue + + if terminalOnly { + if !strings.Contains(string(b), "terminal.app") { + continue + } + } else if appOnly { + if !AppEventFileContentRegex.MatchString(string(b)) { + continue + } } } + if err := os.Remove(fp); err != nil { return err } diff --git a/project/project_test.go b/project/project_test.go index c1dced0..98b6b52 100644 --- a/project/project_test.go +++ b/project/project_test.go @@ -265,12 +265,29 @@ func TestClean(t *testing.T) { t.Errorf("Want error nil got %s", err) } + // write an app event file + if err := ioutil.WriteFile(filepath.Join(gtmPath, "app.event"), []byte(".gtm/browser.app"), 0644); err != nil { + t.Errorf("Want error nil got %s", err) + } + // lets only delete terminal events - err = Clean(util.AfterNow(0), true) + err = Clean(util.AfterNow(0), true, false) files, err := ioutil.ReadDir(gtmPath) if err != nil { t.Fatalf("Want error nil got %s", err) } + for _, f := range files { + if !(f.Name() == "a.txt" || f.Name() == "a.event" || f.Name() == "b.event" || f.Name() == "app.event") { + t.Errorf("Clean(), want only a.txt, a.event, b.event and app.event got %s", f.Name()) + } + } + + // lets only delete app events + err = Clean(util.AfterNow(0), false, true) + files, err = ioutil.ReadDir(gtmPath) + if err != nil { + t.Fatalf("Want error nil got %s", err) + } for _, f := range files { if !(f.Name() == "a.txt" || f.Name() == "a.event" || f.Name() == "b.event") { t.Errorf("Clean(), want only a.txt, a.event and b.event got %s", f.Name()) @@ -278,7 +295,7 @@ func TestClean(t *testing.T) { } // lets clean all events - err = Clean(util.AfterNow(0), false) + err = Clean(util.AfterNow(0), false, false) files, err = ioutil.ReadDir(gtmPath) if err != nil { t.Fatalf("Want error nil got %s", err) diff --git a/report/query.go b/report/query.go index 9c297a5..4a90311 100644 --- a/report/query.go +++ b/report/query.go @@ -21,7 +21,7 @@ const ( defaultDateFormat = "Mon Jan 02 15:04:05 2006 MST" ) -func retrieveNotes(projects []ProjectCommits, terminalOff, calcStats bool, dateFormat string) commitNoteDetails { +func retrieveNotes(projects []ProjectCommits, terminalOff, appOff, calcStats bool, dateFormat string) commitNoteDetails { notes := commitNoteDetails{} if dateFormat == "" { @@ -48,6 +48,9 @@ func retrieveNotes(projects []ProjectCommits, terminalOff, calcStats bool, dateF if terminalOff { commitNote = commitNote.FilterOutTerminal() } + if appOff { + commitNote = commitNote.FilterOutApp() + } id := n.ID if len(id) > 7 { @@ -162,3 +165,14 @@ func (f *fileEntry) Duration() string { func (f *fileEntry) IsTerminal() bool { return f.Filename == ".gtm/terminal.app" } + +func (f *fileEntry) IsApp() bool { + return project.AppEventFileContentRegex.MatchString(f.Filename) +} + +// GetAppName returns the name of the App +func (f *fileEntry) GetAppName() string { + name := project.AppEventFileContentRegex.FindStringSubmatch(f.Filename)[1] + name = util.UcFirst(name) + return name +} diff --git a/report/report.go b/report/report.go index e3832ce..f19f2fa 100644 --- a/report/report.go +++ b/report/report.go @@ -39,6 +39,7 @@ type OutputOptions struct { LongDuration bool FullMessage bool TerminalOff bool + AppOff bool Color bool Limit int } @@ -58,6 +59,9 @@ func Status(n note.CommitNote, options OutputOptions, projPath ...string) (strin if options.TerminalOff { n = n.FilterOutTerminal() } + if options.AppOff { + n = n.FilterOutApp() + } if options.TotalOnly { if options.LongDuration { @@ -105,7 +109,7 @@ func Status(n note.CommitNote, options OutputOptions, projPath ...string) (strin // CommitSummary returns the commit summary report func CommitSummary(projects []ProjectCommits, options OutputOptions) (string, error) { - notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, false, "Mon Jan 02")) + notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, options.AppOff, false, "Mon Jan 02")) if len(notes) == 0 { return "", nil } @@ -134,7 +138,7 @@ func CommitSummary(projects []ProjectCommits, options OutputOptions) (string, er // ProjectSummary returns the project summary report func ProjectSummary(projects []ProjectCommits, options OutputOptions) (string, error) { - notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, false, "Mon Jan 02")) + notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, options.AppOff, false, "Mon Jan 02")) if len(notes) == 0 { return "", nil } @@ -166,7 +170,7 @@ func ProjectSummary(projects []ProjectCommits, options OutputOptions) (string, e // Commits returns the commits report func Commits(projects []ProjectCommits, options OutputOptions) (string, error) { - notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, true, "")) + notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, options.AppOff, true, "")) if len(notes) == 0 { return "", nil } @@ -195,7 +199,7 @@ func Commits(projects []ProjectCommits, options OutputOptions) (string, error) { // Timeline returns the time spent by hour func Timeline(projects []ProjectCommits, options OutputOptions) (string, error) { - notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, false, "")) + notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, options.AppOff, false, "")) if len(notes) == 0 { return "", nil } @@ -228,7 +232,7 @@ func Timeline(projects []ProjectCommits, options OutputOptions) (string, error) // TimelineCommits returns the number commits by hour func TimelineCommits(projects []ProjectCommits, options OutputOptions) (string, error) { - notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, false, "")) + notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, options.AppOff, false, "")) if len(notes) == 0 { return "", nil } @@ -261,7 +265,7 @@ func TimelineCommits(projects []ProjectCommits, options OutputOptions) (string, // Files returns the files report func Files(projects []ProjectCommits, options OutputOptions) (string, error) { - notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, false, "")) + notes := options.limitNotes(retrieveNotes(projects, options.TerminalOff, options.AppOff, false, "")) if len(notes) == 0 { return "", nil } diff --git a/report/templates.go b/report/templates.go index e8e1891..3cc80bf 100644 --- a/report/templates.go +++ b/report/templates.go @@ -36,8 +36,8 @@ const ( {{- $note.Date }} {{ printf $boldFormat $note.Project }} {{ $note.Author }}{{- printf "\n" }} {{- if $fullMessage}}{{- if $note.Message }}{{- printf "\n"}}{{- $note.Message }}{{- printf "\n"}}{{end}}{{end}} {{- range $i, $f := .Note.Files }} - {{- if $f.IsTerminal }} - {{- FormatDuration $f.TimeSpent | printf "\n%14s" }} {{ Percent $f.TimeSpent $total | printf "%3.0f"}}% [{{ $f.Status }}] Terminal + {{- if $f.IsApp }} + {{- FormatDuration $f.TimeSpent | printf "\n%14s" }} {{ Percent $f.TimeSpent $total | printf "%3.0f"}}% [{{ $f.Status }}] [app] {{$f.GetAppName }} {{- else }} {{- FormatDuration $f.TimeSpent | printf "\n%14s" }} {{ Percent $f.TimeSpent $total | printf "%3.0f"}}% [{{ $f.Status }}] {{$f.ShortenSourceFile 100}} {{- end }} @@ -54,8 +54,8 @@ const ( {{- if .Note.Files }}{{ printf "\n"}}{{end}} {{- $total := .Note.Total }} {{- range $i, $f := .Note.Files }} - {{- if $f.IsTerminal }} - {{- FormatDuration $f.TimeSpent | printf "%14s" }} {{ Percent $f.TimeSpent $total | printf "%3.0f"}}% [{{ $f.Status }}] Terminal + {{- if $f.IsApp }} + {{- FormatDuration $f.TimeSpent | printf "%14s" }} {{ Percent $f.TimeSpent $total | printf "%3.0f"}}% [{{ $f.Status }}] [app] {{$f.GetAppName }} {{- else }} {{- FormatDuration $f.TimeSpent | printf "%14s" }} {{ Percent $f.TimeSpent $total | printf "%3.0f"}}% [{{ $f.Status }}] {{$f.ShortenSourceFile 100}} {{- end }} @@ -97,8 +97,8 @@ const ( filesTpl string = ` {{- $total := .Files.Total }} {{ range $i, $f := .Files }} - {{- if $f.IsTerminal }} - {{- $f.Duration | printf "%14s" }} {{ Percent $f.Seconds $total | printf "%3.0f"}}% Terminal + {{- if $f.IsApp }} + {{- $f.Duration | printf "%14s" }} {{ Percent $f.Seconds $total | printf "%3.0f"}}% [app] {{ $f.GetAppName }} {{- else }} {{- $f.Duration | printf "%14s" }} {{ Percent $f.Seconds $total | printf "%3.0f"}}% {{ $f.Filename }} {{- end }} diff --git a/util/string.go b/util/string.go index 4a80a4a..c4daadc 100644 --- a/util/string.go +++ b/util/string.go @@ -9,6 +9,7 @@ import ( "regexp" "strings" "time" + "unicode" "github.com/hako/durafmt" ) @@ -85,3 +86,11 @@ func Map(vs []string, f func(string) string) []string { } return vsm } + +// UcFirst Uppercase first letter +func UcFirst(str string) string { + for i, v := range str { + return string(unicode.ToUpper(v)) + str[i+1:] + } + return "" +} diff --git a/util/test.go b/util/test.go index c406dd5..38873bf 100644 --- a/util/test.go +++ b/util/test.go @@ -139,6 +139,12 @@ func (t TestRepo) SaveFile(filename, subdir, content string) { CheckFatal(t.test, err) } +// FileExists Checks if a file exists in the repo folder +func (t TestRepo) FileExists(filename, subdir string) bool { + _, err := os.Stat(filepath.Join(subdir, filename)) + return !os.IsNotExist(err) +} + // Clone creates a clone of this repo func (t TestRepo) Clone() TestRepo { path, err := ioutil.TempDir("", "gtm")