From 6a427373ccb9c88629e9c0fbf3ff7d8679666b6c Mon Sep 17 00:00:00 2001 From: Michael Schenk Date: Fri, 8 Jun 2018 16:08:36 -0500 Subject: [PATCH] refactor active project --- project/active.go | 103 +++++++++++++++++++++++++---------------- project/active_test.go | 45 ++++++++++++++++++ util/test.go | 1 + 3 files changed, 110 insertions(+), 39 deletions(-) create mode 100644 project/active_test.go diff --git a/project/active.go b/project/active.go index bc51a20..a925c57 100644 --- a/project/active.go +++ b/project/active.go @@ -17,72 +17,97 @@ import ( "github.com/git-time-metric/gtm/epoch" ) -var ( - registryFilename = "registry.txt" -) - -// TODO: when should we activate a new project? Always or only when -// the previous active project was been idle for a period of time? - +// SetActive records a project's path as active +// A package level func variable is used for ease of testing. var SetActive = func(path string) error { - x := GetActive() - if x != "" && x != path { - // project has changed but not idle timed out yet + a := active{path: path, lastUpdated: epoch.Now()} + err := a.marshal() + if err != nil { + // FIXME: do not eat error return nil } + return nil +} + +// GetActive returns the current active project's path. +// If not project is active an empty string is returned. +// A package level func variable is used for ease of testing. +var GetActive = func() string { + a := active{} + err := a.unmarshal() + if err != nil { + // FIXME: do not eat error + return "" + } + + if !a.pathExists() { + return "" + } + + if !time.Unix(epoch.Now(), 0).Before( + time.Unix(a.lastUpdated+epoch.IdleProjectTimeout, 0)) { + return "" + } + return a.path +} + +type active struct { + path string + lastUpdated int64 +} + +// ActiveSerializationPath returns the path to serialize the active project to. +// A package level func variable is used for ease of testing. +var ActiveSerializationPath = func() (string, error) { + u, err := user.Current() + if err != nil { + return "", err + } + return filepath.Join(filepath.Join(u.HomeDir, gtmHomeDir), "active-project.txt"), nil +} + +func (a *active) pathExists() bool { + if _, err := os.Stat(a.path); os.IsNotExist(err) { + return false + } + return true +} - f, err := registry() +func (a *active) marshal() error { + f, err := ActiveSerializationPath() if err != nil { return err } if err := ioutil.WriteFile( - f, []byte(fmt.Sprintf("%s,%d", path, epoch.Now())), 0644); err != nil { + f, []byte(fmt.Sprintf("%s,%d", a.path, a.lastUpdated)), 0644); err != nil { return err } return nil } -var GetActive = func() string { - f, err := registry() +func (a *active) unmarshal() error { + f, err := ActiveSerializationPath() if err != nil { - return "" + return err } b, err := ioutil.ReadFile(f) if err != nil { - return "" + return err } parts := strings.Split(string(b), ",") if len(parts) != 2 { - return "" - } - - // does the project path exist - if _, err := os.Stat(parts[0]); os.IsNotExist(err) { - return "" + return err } - if !isActive(parts[1]) { - return "" - } + a.path = parts[0] - return parts[0] -} - -func isActive(timeUpdated string) bool { - x, err := strconv.ParseInt(timeUpdated, 10, 64) + a.lastUpdated, err = strconv.ParseInt(parts[1], 10, 64) if err != nil { - return false + return err } - return time.Unix(epoch.Now(), 0).Before(time.Unix(x+epoch.IdleProjectTimeout, 0)) -} -func registry() (string, error) { - u, err := user.Current() - if err != nil { - return "", err - } - return filepath.Join(filepath.Join(u.HomeDir, gtmHomeDir), registryFilename), nil + return nil } diff --git a/project/active_test.go b/project/active_test.go new file mode 100644 index 0000000..974ca68 --- /dev/null +++ b/project/active_test.go @@ -0,0 +1,45 @@ +package project + +import ( + "io/ioutil" + "os" + "testing" + "time" + + "github.com/git-time-metric/gtm/epoch" + "github.com/git-time-metric/gtm/util" +) + +func TestActiveProject(t *testing.T) { + d, err := ioutil.TempDir("", "") + if err != nil { + t.Errorf("want error nil got error %s", err) + } + defer os.Remove(d) + + SetActive(d) + p := GetActive() + if p != d { + t.Errorf("want project directory %s got %s", d, p) + } + + SetActive("/path/does/not/exist") + p = GetActive() + if p != "" { + t.Errorf("want project directory '' got %s", p) + } + + SetActive(d) + saveNow := util.Now + defer func() { util.Now = saveNow }() + util.Now = func() time.Time { return time.Now().Add(time.Duration(epoch.IdleProjectTimeout) - 10*time.Second) } + p = GetActive() + if p != d { + t.Errorf("want project directory %s got %s", d, p) + } + util.Now = func() time.Time { return time.Now().Add(time.Duration(epoch.IdleProjectTimeout) * time.Second) } + p = GetActive() + if p != "" { + t.Errorf("want project directory '' got %s", p) + } +} diff --git a/util/test.go b/util/test.go index 38f1e07..e0bb132 100644 --- a/util/test.go +++ b/util/test.go @@ -18,6 +18,7 @@ import ( "github.com/libgit2/git2go" ) +// TimeTrackEnable turns on and off profiling var TimeTrackEnable = false //TimeTrack is used for profiling execution time