reorganize package for a more idomatic go

Michael Muré created

Change summary

bug/bug.go                             | 21 ++++---
bug/comment.go                         |  4 
bug/interface.go                       |  6 +-
bug/operation.go                       |  6 +-
bug/operation_pack.go                  |  6 +-
cache/bug_cache.go                     |  6 +-
cache/bug_excerpt.go                   |  6 +-
cache/repo_cache.go                    |  9 +-
commands/ls.go                         |  8 +-
commands/show.go                       |  8 +-
commands/webui.go                      |  6 +-
graphql/gqlgen.yml                     | 12 ++--
graphql/graph/gen_graph.go             | 28 +++++-----
graphql/resolvers/mutation.go          |  6 +-
graphql/resolvers/operations.go        |  2 
misc/random_bugs/create_random_bugs.go |  2 
operations/add_comment.go              | 10 +-
operations/create.go                   | 10 +-
operations/create_test.go              |  0 
operations/label_change.go             |  0 
operations/operations.go               |  0 
operations/set_status.go               |  0 
operations/set_title.go                |  0 
repository/git.go                      | 59 +++++++++++-----------
repository/mock_repo.go                | 71 ++++++++++++++-------------
repository/repo.go                     | 31 ++++++-----
repository/tree_entry.go               |  6 +-
repository/tree_entry_test.go          |  6 +-
termui/bug_table.go                    | 35 +++++++------
termui/msg_popup.go                    |  4 
termui/show_bug.go                     | 47 +++++++++---------
tests/bug_actions_test.go              |  2 
tests/operation_iterator_test.go       |  2 
util/colors/colors.go                  |  2 
util/git/hash.go                       |  2 
util/lamport/lamport.go                | 28 +++++-----
util/lamport/lamport_test.go           |  6 +-
util/lamport/persisted_lamport.go      | 32 ++++++------
util/process/process.go                |  6 +-
util/text/left_padded.go               |  2 
util/text/text.go                      | 30 +----------
util/text/text_test.go                 |  6 +-
42 files changed, 259 insertions(+), 274 deletions(-)

Detailed changes

bug/bug.go 🔗

@@ -6,7 +6,8 @@ import (
 	"strings"
 
 	"github.com/MichaelMure/git-bug/repository"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
+	"github.com/MichaelMure/git-bug/util/lamport"
 )
 
 const bugsRefPattern = "refs/bugs/"
@@ -34,14 +35,14 @@ type Bug struct {
 	// A Lamport clock is a logical clock that allow to order event
 	// inside a distributed system.
 	// It must be the first field in this struct due to https://github.com/golang/go/issues/599
-	createTime util.LamportTime
-	editTime   util.LamportTime
+	createTime lamport.Time
+	editTime   lamport.Time
 
 	// Id used as unique identifier
 	id string
 
-	lastCommit util.Hash
-	rootPack   util.Hash
+	lastCommit git.Hash
+	rootPack   git.Hash
 
 	// all the committed operations
 	packs []OperationPack
@@ -173,10 +174,10 @@ func readBug(repo repository.Repo, ref string) (*Bug, error) {
 
 		if bug.rootPack == "" {
 			bug.rootPack = rootEntry.Hash
-			bug.createTime = util.LamportTime(createTime)
+			bug.createTime = lamport.Time(createTime)
 		}
 
-		bug.editTime = util.LamportTime(editTime)
+		bug.editTime = lamport.Time(editTime)
 
 		// Update the clocks
 		if err := repo.CreateWitness(bug.createTime); err != nil {
@@ -446,7 +447,7 @@ func (bug *Bug) Commit(repo repository.Repo) error {
 func makeMediaTree(pack OperationPack) []repository.TreeEntry {
 	var tree []repository.TreeEntry
 	counter := 0
-	added := make(map[util.Hash]interface{})
+	added := make(map[git.Hash]interface{})
 
 	for _, ops := range pack.Operations {
 		for _, file := range ops.Files() {
@@ -576,12 +577,12 @@ func (bug *Bug) HumanId() string {
 }
 
 // CreateLamportTime return the Lamport time of creation
-func (bug *Bug) CreateLamportTime() util.LamportTime {
+func (bug *Bug) CreateLamportTime() lamport.Time {
 	return bug.createTime
 }
 
 // EditLamportTime return the Lamport time of the last edit
-func (bug *Bug) EditLamportTime() util.LamportTime {
+func (bug *Bug) EditLamportTime() lamport.Time {
 	return bug.editTime
 }
 

bug/comment.go 🔗

@@ -1,7 +1,7 @@
 package bug
 
 import (
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 	"github.com/dustin/go-humanize"
 	"time"
 )
@@ -10,7 +10,7 @@ import (
 type Comment struct {
 	Author  Person
 	Message string
-	Files   []util.Hash
+	Files   []git.Hash
 
 	// Creation time of the comment.
 	// Should be used only for human display, never for ordering as we can't rely on it in a distributed system.

bug/interface.go 🔗

@@ -2,7 +2,7 @@ package bug
 
 import (
 	"github.com/MichaelMure/git-bug/repository"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/lamport"
 )
 
 type Interface interface {
@@ -41,10 +41,10 @@ type Interface interface {
 	Compile() Snapshot
 
 	// CreateLamportTime return the Lamport time of creation
-	CreateLamportTime() util.LamportTime
+	CreateLamportTime() lamport.Time
 
 	// EditLamportTime return the Lamport time of the last edit
-	EditLamportTime() util.LamportTime
+	EditLamportTime() lamport.Time
 }
 
 func bugFromInterface(bug Interface) *Bug {

bug/operation.go 🔗

@@ -1,7 +1,7 @@
 package bug
 
 import (
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 	"time"
 )
 
@@ -28,7 +28,7 @@ type Operation interface {
 	// Apply the operation to a Snapshot to create the final state
 	Apply(snapshot Snapshot) Snapshot
 	// Files return the files needed by this operation
-	Files() []util.Hash
+	Files() []git.Hash
 
 	// TODO: data validation (ex: a title is a single line)
 	// Validate() bool
@@ -66,6 +66,6 @@ func (op OpBase) GetUnixTime() int64 {
 }
 
 // Files return the files needed by this operation
-func (op OpBase) Files() []util.Hash {
+func (op OpBase) Files() []git.Hash {
 	return nil
 }

bug/operation_pack.go 🔗

@@ -5,7 +5,7 @@ import (
 	"encoding/gob"
 
 	"github.com/MichaelMure/git-bug/repository"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 )
 
 // OperationPack represent an ordered set of operation to apply
@@ -18,7 +18,7 @@ type OperationPack struct {
 	Operations []Operation
 
 	// Private field so not serialized by gob
-	commitHash util.Hash
+	commitHash git.Hash
 }
 
 // ParseOperationPack will deserialize an OperationPack from raw bytes
@@ -68,7 +68,7 @@ func (opp *OperationPack) IsValid() bool {
 
 // Write will serialize and store the OperationPack as a git blob and return
 // its hash
-func (opp *OperationPack) Write(repo repository.Repo) (util.Hash, error) {
+func (opp *OperationPack) Write(repo repository.Repo) (git.Hash, error) {
 	data, err := opp.Serialize()
 
 	if err != nil {

cache/bug_cache.go 🔗

@@ -4,8 +4,8 @@ import (
 	"io"
 
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/bug/operations"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/operations"
+	"github.com/MichaelMure/git-bug/util/git"
 )
 
 type BugCache struct {
@@ -40,7 +40,7 @@ func (c *BugCache) AddComment(message string) error {
 	return c.notifyUpdated()
 }
 
-func (c *BugCache) AddCommentWithFiles(message string, files []util.Hash) error {
+func (c *BugCache) AddCommentWithFiles(message string, files []git.Hash) error {
 	author, err := bug.GetUser(c.repoCache.repo)
 	if err != nil {
 		return err

cache/bug_excerpt.go 🔗

@@ -4,7 +4,7 @@ import (
 	"encoding/gob"
 
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/lamport"
 )
 
 // BugExcerpt hold a subset of the bug values to be able to sort and filter bugs
@@ -12,8 +12,8 @@ import (
 type BugExcerpt struct {
 	Id string
 
-	CreateLamportTime util.LamportTime
-	EditLamportTime   util.LamportTime
+	CreateLamportTime lamport.Time
+	EditLamportTime   lamport.Time
 	CreateUnixTime    int64
 	EditUnixTime      int64
 

cache/repo_cache.go 🔗

@@ -13,9 +13,10 @@ import (
 	"strings"
 
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/bug/operations"
+	"github.com/MichaelMure/git-bug/operations"
 	"github.com/MichaelMure/git-bug/repository"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
+	"github.com/MichaelMure/git-bug/util/process"
 )
 
 type RepoCache struct {
@@ -262,7 +263,7 @@ func (c *RepoCache) NewBug(title string, message string) (*BugCache, error) {
 
 // NewBugWithFiles create a new bug with attached files for the message
 // The new bug is written in the repository (commit)
-func (c *RepoCache) NewBugWithFiles(title string, message string, files []util.Hash) (*BugCache, error) {
+func (c *RepoCache) NewBugWithFiles(title string, message string, files []git.Hash) (*BugCache, error) {
 	author, err := bug.GetUser(c.repo)
 	if err != nil {
 		return nil, err
@@ -382,7 +383,7 @@ func repoIsAvailable(repo repository.Repo) error {
 			return err
 		}
 
-		if util.ProcessIsRunning(pid) {
+		if process.IsRunning(pid) {
 			return fmt.Errorf("the repository you want to access is already locked by the process pid %d", pid)
 		}
 

commands/ls.go 🔗

@@ -5,7 +5,7 @@ import (
 
 	"github.com/MichaelMure/git-bug/bug"
 	"github.com/MichaelMure/git-bug/cache"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/colors"
 	"github.com/spf13/cobra"
 )
 
@@ -61,10 +61,10 @@ func runLsBug(cmd *cobra.Command, args []string) error {
 		authorFmt := fmt.Sprintf("%-15.15s", author.Name)
 
 		fmt.Printf("%s %s\t%s\t%s\t%s\n",
-			util.Cyan(b.HumanId()),
-			util.Yellow(snapshot.Status),
+			colors.Cyan(b.HumanId()),
+			colors.Yellow(snapshot.Status),
 			titleFmt,
-			util.Magenta(authorFmt),
+			colors.Magenta(authorFmt),
 			snapshot.Summary(),
 		)
 	}

commands/show.go 🔗

@@ -6,7 +6,7 @@ import (
 	"strings"
 
 	"github.com/MichaelMure/git-bug/cache"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/colors"
 	"github.com/spf13/cobra"
 )
 
@@ -42,13 +42,13 @@ func runShowBug(cmd *cobra.Command, args []string) error {
 
 	// Header
 	fmt.Printf("[%s] %s %s\n\n",
-		util.Yellow(snapshot.Status),
-		util.Cyan(snapshot.HumanId()),
+		colors.Yellow(snapshot.Status),
+		colors.Cyan(snapshot.HumanId()),
 		snapshot.Title,
 	)
 
 	fmt.Printf("%s opened this issue %s\n\n",
-		util.Magenta(firstComment.Author.Name),
+		colors.Magenta(firstComment.Author.Name),
 		firstComment.FormatTime(),
 	)
 

commands/webui.go 🔗

@@ -14,7 +14,7 @@ import (
 
 	"github.com/MichaelMure/git-bug/graphql"
 	"github.com/MichaelMure/git-bug/repository"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 	"github.com/MichaelMure/git-bug/webui"
 	"github.com/gorilla/mux"
 	"github.com/phayes/freeport"
@@ -111,7 +111,7 @@ func newGitFileHandler(repo repository.Repo) http.Handler {
 }
 
 func (gfh *gitFileHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
-	hash := util.Hash(mux.Vars(r)["hash"])
+	hash := git.Hash(mux.Vars(r)["hash"])
 
 	if !hash.IsValid() {
 		http.Error(rw, "invalid git hash", http.StatusBadRequest)
@@ -122,7 +122,7 @@ func (gfh *gitFileHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
 	// This can be a problem for big files. There might be a way around
 	// that by implementing a io.ReadSeeker that would read and discard
 	// data when a seek is called.
-	data, err := gfh.repo.ReadData(util.Hash(hash))
+	data, err := gfh.repo.ReadData(git.Hash(hash))
 	if err != nil {
 		http.Error(rw, err.Error(), http.StatusInternalServerError)
 		return

graphql/gqlgen.yml 🔗

@@ -18,16 +18,16 @@ models:
   Label:
     model: github.com/MichaelMure/git-bug/bug.Label
   Hash:
-    model: github.com/MichaelMure/git-bug/util.Hash
+    model: github.com/MichaelMure/git-bug/util/git.Hash
   Operation:
     model: github.com/MichaelMure/git-bug/bug.Operation
   CreateOperation:
-    model: github.com/MichaelMure/git-bug/bug/operations.CreateOperation
+    model: github.com/MichaelMure/git-bug/operations.CreateOperation
   SetTitleOperation:
-    model: github.com/MichaelMure/git-bug/bug/operations.SetTitleOperation
+    model: github.com/MichaelMure/git-bug/operations.SetTitleOperation
   AddCommentOperation:
-    model: github.com/MichaelMure/git-bug/bug/operations.AddCommentOperation
+    model: github.com/MichaelMure/git-bug/operations.AddCommentOperation
   SetStatusOperation:
-    model: github.com/MichaelMure/git-bug/bug/operations.SetStatusOperation
+    model: github.com/MichaelMure/git-bug/operations.SetStatusOperation
   LabelChangeOperation:
-    model: github.com/MichaelMure/git-bug/bug/operations.LabelChangeOperation
+    model: github.com/MichaelMure/git-bug/operations.LabelChangeOperation

graphql/graph/gen_graph.go 🔗

@@ -10,9 +10,9 @@ import (
 	time "time"
 
 	bug "github.com/MichaelMure/git-bug/bug"
-	operations "github.com/MichaelMure/git-bug/bug/operations"
 	models "github.com/MichaelMure/git-bug/graphql/models"
-	util "github.com/MichaelMure/git-bug/util"
+	operations "github.com/MichaelMure/git-bug/operations"
+	git "github.com/MichaelMure/git-bug/util/git"
 	graphql "github.com/vektah/gqlgen/graphql"
 	introspection "github.com/vektah/gqlgen/neelance/introspection"
 	query "github.com/vektah/gqlgen/neelance/query"
@@ -42,8 +42,8 @@ type Resolvers interface {
 
 	LabelChangeOperation_date(ctx context.Context, obj *operations.LabelChangeOperation) (time.Time, error)
 
-	Mutation_newBug(ctx context.Context, repoRef *string, title string, message string, files []util.Hash) (bug.Snapshot, error)
-	Mutation_addComment(ctx context.Context, repoRef *string, prefix string, message string, files []util.Hash) (bug.Snapshot, error)
+	Mutation_newBug(ctx context.Context, repoRef *string, title string, message string, files []git.Hash) (bug.Snapshot, error)
+	Mutation_addComment(ctx context.Context, repoRef *string, prefix string, message string, files []git.Hash) (bug.Snapshot, error)
 	Mutation_changeLabels(ctx context.Context, repoRef *string, prefix string, added []string, removed []string) (bug.Snapshot, error)
 	Mutation_open(ctx context.Context, repoRef *string, prefix string) (bug.Snapshot, error)
 	Mutation_close(ctx context.Context, repoRef *string, prefix string) (bug.Snapshot, error)
@@ -90,8 +90,8 @@ type LabelChangeOperationResolver interface {
 	Date(ctx context.Context, obj *operations.LabelChangeOperation) (time.Time, error)
 }
 type MutationResolver interface {
-	NewBug(ctx context.Context, repoRef *string, title string, message string, files []util.Hash) (bug.Snapshot, error)
-	AddComment(ctx context.Context, repoRef *string, prefix string, message string, files []util.Hash) (bug.Snapshot, error)
+	NewBug(ctx context.Context, repoRef *string, title string, message string, files []git.Hash) (bug.Snapshot, error)
+	AddComment(ctx context.Context, repoRef *string, prefix string, message string, files []git.Hash) (bug.Snapshot, error)
 	ChangeLabels(ctx context.Context, repoRef *string, prefix string, added []string, removed []string) (bug.Snapshot, error)
 	Open(ctx context.Context, repoRef *string, prefix string) (bug.Snapshot, error)
 	Close(ctx context.Context, repoRef *string, prefix string) (bug.Snapshot, error)
@@ -146,11 +146,11 @@ func (s shortMapper) LabelChangeOperation_date(ctx context.Context, obj *operati
 	return s.r.LabelChangeOperation().Date(ctx, obj)
 }
 
-func (s shortMapper) Mutation_newBug(ctx context.Context, repoRef *string, title string, message string, files []util.Hash) (bug.Snapshot, error) {
+func (s shortMapper) Mutation_newBug(ctx context.Context, repoRef *string, title string, message string, files []git.Hash) (bug.Snapshot, error) {
 	return s.r.Mutation().NewBug(ctx, repoRef, title, message, files)
 }
 
-func (s shortMapper) Mutation_addComment(ctx context.Context, repoRef *string, prefix string, message string, files []util.Hash) (bug.Snapshot, error) {
+func (s shortMapper) Mutation_addComment(ctx context.Context, repoRef *string, prefix string, message string, files []git.Hash) (bug.Snapshot, error) {
 	return s.r.Mutation().AddComment(ctx, repoRef, prefix, message, files)
 }
 
@@ -1356,7 +1356,7 @@ func (ec *executionContext) _Mutation_newBug(ctx context.Context, field graphql.
 		}
 	}
 	args["message"] = arg2
-	var arg3 []util.Hash
+	var arg3 []git.Hash
 	if tmp, ok := field.Args["files"]; ok {
 		var err error
 		var rawIf1 []interface{}
@@ -1365,7 +1365,7 @@ func (ec *executionContext) _Mutation_newBug(ctx context.Context, field graphql.
 				rawIf1 = tmp1
 			}
 		}
-		arg3 = make([]util.Hash, len(rawIf1))
+		arg3 = make([]git.Hash, len(rawIf1))
 		for idx1 := range rawIf1 {
 			err = (&arg3[idx1]).UnmarshalGQL(rawIf1[idx1])
 		}
@@ -1382,7 +1382,7 @@ func (ec *executionContext) _Mutation_newBug(ctx context.Context, field graphql.
 	rctx.PushField(field.Alias)
 	defer rctx.Pop()
 	resTmp, err := ec.ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) {
-		return ec.resolvers.Mutation_newBug(ctx, args["repoRef"].(*string), args["title"].(string), args["message"].(string), args["files"].([]util.Hash))
+		return ec.resolvers.Mutation_newBug(ctx, args["repoRef"].(*string), args["title"].(string), args["message"].(string), args["files"].([]git.Hash))
 	})
 	if err != nil {
 		ec.Error(ctx, err)
@@ -1432,7 +1432,7 @@ func (ec *executionContext) _Mutation_addComment(ctx context.Context, field grap
 		}
 	}
 	args["message"] = arg2
-	var arg3 []util.Hash
+	var arg3 []git.Hash
 	if tmp, ok := field.Args["files"]; ok {
 		var err error
 		var rawIf1 []interface{}
@@ -1441,7 +1441,7 @@ func (ec *executionContext) _Mutation_addComment(ctx context.Context, field grap
 				rawIf1 = tmp1
 			}
 		}
-		arg3 = make([]util.Hash, len(rawIf1))
+		arg3 = make([]git.Hash, len(rawIf1))
 		for idx1 := range rawIf1 {
 			err = (&arg3[idx1]).UnmarshalGQL(rawIf1[idx1])
 		}
@@ -1458,7 +1458,7 @@ func (ec *executionContext) _Mutation_addComment(ctx context.Context, field grap
 	rctx.PushField(field.Alias)
 	defer rctx.Pop()
 	resTmp, err := ec.ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) {
-		return ec.resolvers.Mutation_addComment(ctx, args["repoRef"].(*string), args["prefix"].(string), args["message"].(string), args["files"].([]util.Hash))
+		return ec.resolvers.Mutation_addComment(ctx, args["repoRef"].(*string), args["prefix"].(string), args["message"].(string), args["files"].([]git.Hash))
 	})
 	if err != nil {
 		ec.Error(ctx, err)

graphql/resolvers/mutation.go 🔗

@@ -5,7 +5,7 @@ import (
 
 	"github.com/MichaelMure/git-bug/bug"
 	"github.com/MichaelMure/git-bug/cache"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 )
 
 type mutationResolver struct {
@@ -20,7 +20,7 @@ func (r mutationResolver) getRepo(repoRef *string) (*cache.RepoCache, error) {
 	return r.cache.DefaultRepo()
 }
 
-func (r mutationResolver) NewBug(ctx context.Context, repoRef *string, title string, message string, files []util.Hash) (bug.Snapshot, error) {
+func (r mutationResolver) NewBug(ctx context.Context, repoRef *string, title string, message string, files []git.Hash) (bug.Snapshot, error) {
 	repo, err := r.getRepo(repoRef)
 	if err != nil {
 		return bug.Snapshot{}, err
@@ -57,7 +57,7 @@ func (r mutationResolver) Commit(ctx context.Context, repoRef *string, prefix st
 	return *snap, nil
 }
 
-func (r mutationResolver) AddComment(ctx context.Context, repoRef *string, prefix string, message string, files []util.Hash) (bug.Snapshot, error) {
+func (r mutationResolver) AddComment(ctx context.Context, repoRef *string, prefix string, message string, files []git.Hash) (bug.Snapshot, error) {
 	repo, err := r.getRepo(repoRef)
 	if err != nil {
 		return bug.Snapshot{}, err

graphql/resolvers/operations.go 🔗

@@ -6,8 +6,8 @@ import (
 	"time"
 
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/bug/operations"
 	"github.com/MichaelMure/git-bug/graphql/models"
+	"github.com/MichaelMure/git-bug/operations"
 )
 
 type addCommentOperationResolver struct{}

misc/random_bugs/create_random_bugs.go 🔗

@@ -6,7 +6,7 @@ import (
 	"time"
 
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/bug/operations"
+	"github.com/MichaelMure/git-bug/operations"
 	"github.com/MichaelMure/git-bug/repository"
 	"github.com/icrowley/fake"
 )

bug/operations/add_comment.go → operations/add_comment.go 🔗

@@ -2,7 +2,7 @@ package operations
 
 import (
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 )
 
 // AddCommentOperation will add a new comment in the bug
@@ -13,7 +13,7 @@ type AddCommentOperation struct {
 	bug.OpBase
 	Message string
 	// TODO: change for a map[string]util.hash to store the filename ?
-	files []util.Hash
+	files []git.Hash
 }
 
 func (op AddCommentOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
@@ -29,11 +29,11 @@ func (op AddCommentOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
 	return snapshot
 }
 
-func (op AddCommentOperation) Files() []util.Hash {
+func (op AddCommentOperation) Files() []git.Hash {
 	return op.files
 }
 
-func NewAddCommentOp(author bug.Person, message string, files []util.Hash) AddCommentOperation {
+func NewAddCommentOp(author bug.Person, message string, files []git.Hash) AddCommentOperation {
 	return AddCommentOperation{
 		OpBase:  bug.NewOpBase(bug.AddCommentOp, author),
 		Message: message,
@@ -46,7 +46,7 @@ func Comment(b bug.Interface, author bug.Person, message string) {
 	CommentWithFiles(b, author, message, nil)
 }
 
-func CommentWithFiles(b bug.Interface, author bug.Person, message string, files []util.Hash) {
+func CommentWithFiles(b bug.Interface, author bug.Person, message string, files []git.Hash) {
 	addCommentOp := NewAddCommentOp(author, message, files)
 	b.Append(addCommentOp)
 }

bug/operations/create.go → operations/create.go 🔗

@@ -2,7 +2,7 @@ package operations
 
 import (
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 )
 
 // CreateOperation define the initial creation of a bug
@@ -13,7 +13,7 @@ type CreateOperation struct {
 	bug.OpBase
 	Title   string
 	Message string
-	files   []util.Hash
+	files   []git.Hash
 }
 
 func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
@@ -30,11 +30,11 @@ func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
 	return snapshot
 }
 
-func (op CreateOperation) Files() []util.Hash {
+func (op CreateOperation) Files() []git.Hash {
 	return op.files
 }
 
-func NewCreateOp(author bug.Person, title, message string, files []util.Hash) CreateOperation {
+func NewCreateOp(author bug.Person, title, message string, files []git.Hash) CreateOperation {
 	return CreateOperation{
 		OpBase:  bug.NewOpBase(bug.CreateOp, author),
 		Title:   title,
@@ -48,7 +48,7 @@ func Create(author bug.Person, title, message string) (*bug.Bug, error) {
 	return CreateWithFiles(author, title, message, nil)
 }
 
-func CreateWithFiles(author bug.Person, title, message string, files []util.Hash) (*bug.Bug, error) {
+func CreateWithFiles(author bug.Person, title, message string, files []git.Hash) (*bug.Bug, error) {
 	newBug := bug.NewBug()
 	createOp := NewCreateOp(author, title, message, files)
 	newBug.Append(createOp)

repository/git.go 🔗

@@ -11,7 +11,8 @@ import (
 	"path"
 	"strings"
 
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
+	"github.com/MichaelMure/git-bug/util/lamport"
 )
 
 const createClockFile = "/.git/git-bug/create-clock"
@@ -23,8 +24,8 @@ var ErrNotARepo = errors.New("not a git repository")
 // GitRepo represents an instance of a (local) git repository.
 type GitRepo struct {
 	Path        string
-	createClock *util.PersistedLamport
-	editClock   *util.PersistedLamport
+	createClock *lamport.Persisted
+	editClock   *lamport.Persisted
 }
 
 // Run the given git command with the given I/O reader/writers, returning an error if it fails.
@@ -175,16 +176,16 @@ func (repo *GitRepo) PushRefs(remote string, refSpec string) (string, error) {
 }
 
 // StoreData will store arbitrary data and return the corresponding hash
-func (repo *GitRepo) StoreData(data []byte) (util.Hash, error) {
+func (repo *GitRepo) StoreData(data []byte) (git.Hash, error) {
 	var stdin = bytes.NewReader(data)
 
 	stdout, err := repo.runGitCommandWithStdin(stdin, "hash-object", "--stdin", "-w")
 
-	return util.Hash(stdout), err
+	return git.Hash(stdout), err
 }
 
 // ReadData will attempt to read arbitrary data from the given hash
-func (repo *GitRepo) ReadData(hash util.Hash) ([]byte, error) {
+func (repo *GitRepo) ReadData(hash git.Hash) ([]byte, error) {
 	var stdout bytes.Buffer
 	var stderr bytes.Buffer
 
@@ -198,7 +199,7 @@ func (repo *GitRepo) ReadData(hash util.Hash) ([]byte, error) {
 }
 
 // StoreTree will store a mapping key-->Hash as a Git tree
-func (repo *GitRepo) StoreTree(entries []TreeEntry) (util.Hash, error) {
+func (repo *GitRepo) StoreTree(entries []TreeEntry) (git.Hash, error) {
 	buffer := prepareTreeEntries(entries)
 
 	stdout, err := repo.runGitCommandWithStdin(&buffer, "mktree")
@@ -207,22 +208,22 @@ func (repo *GitRepo) StoreTree(entries []TreeEntry) (util.Hash, error) {
 		return "", err
 	}
 
-	return util.Hash(stdout), nil
+	return git.Hash(stdout), nil
 }
 
 // StoreCommit will store a Git commit with the given Git tree
-func (repo *GitRepo) StoreCommit(treeHash util.Hash) (util.Hash, error) {
+func (repo *GitRepo) StoreCommit(treeHash git.Hash) (git.Hash, error) {
 	stdout, err := repo.runGitCommand("commit-tree", string(treeHash))
 
 	if err != nil {
 		return "", err
 	}
 
-	return util.Hash(stdout), nil
+	return git.Hash(stdout), nil
 }
 
 // StoreCommitWithParent will store a Git commit with the given Git tree
-func (repo *GitRepo) StoreCommitWithParent(treeHash util.Hash, parent util.Hash) (util.Hash, error) {
+func (repo *GitRepo) StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error) {
 	stdout, err := repo.runGitCommand("commit-tree", string(treeHash),
 		"-p", string(parent))
 
@@ -230,11 +231,11 @@ func (repo *GitRepo) StoreCommitWithParent(treeHash util.Hash, parent util.Hash)
 		return "", err
 	}
 
-	return util.Hash(stdout), nil
+	return git.Hash(stdout), nil
 }
 
 // UpdateRef will create or update a Git reference
-func (repo *GitRepo) UpdateRef(ref string, hash util.Hash) error {
+func (repo *GitRepo) UpdateRef(ref string, hash git.Hash) error {
 	_, err := repo.runGitCommand("update-ref", ref, string(hash))
 
 	return err
@@ -276,7 +277,7 @@ func (repo *GitRepo) CopyRef(source string, dest string) error {
 }
 
 // ListCommits will return the list of commit hashes of a ref, in chronological order
-func (repo *GitRepo) ListCommits(ref string) ([]util.Hash, error) {
+func (repo *GitRepo) ListCommits(ref string) ([]git.Hash, error) {
 	stdout, err := repo.runGitCommand("rev-list", "--first-parent", "--reverse", ref)
 
 	if err != nil {
@@ -285,9 +286,9 @@ func (repo *GitRepo) ListCommits(ref string) ([]util.Hash, error) {
 
 	split := strings.Split(stdout, "\n")
 
-	casted := make([]util.Hash, len(split))
+	casted := make([]git.Hash, len(split))
 	for i, line := range split {
-		casted[i] = util.Hash(line)
+		casted[i] = git.Hash(line)
 	}
 
 	return casted, nil
@@ -295,7 +296,7 @@ func (repo *GitRepo) ListCommits(ref string) ([]util.Hash, error) {
 }
 
 // ListEntries will return the list of entries in a Git tree
-func (repo *GitRepo) ListEntries(hash util.Hash) ([]TreeEntry, error) {
+func (repo *GitRepo) ListEntries(hash git.Hash) ([]TreeEntry, error) {
 	stdout, err := repo.runGitCommand("ls-tree", string(hash))
 
 	if err != nil {
@@ -306,25 +307,25 @@ func (repo *GitRepo) ListEntries(hash util.Hash) ([]TreeEntry, error) {
 }
 
 // FindCommonAncestor will return the last common ancestor of two chain of commit
-func (repo *GitRepo) FindCommonAncestor(hash1 util.Hash, hash2 util.Hash) (util.Hash, error) {
+func (repo *GitRepo) FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error) {
 	stdout, err := repo.runGitCommand("merge-base", string(hash1), string(hash2))
 
 	if err != nil {
 		return "", nil
 	}
 
-	return util.Hash(stdout), nil
+	return git.Hash(stdout), nil
 }
 
 // GetTreeHash return the git tree hash referenced in a commit
-func (repo *GitRepo) GetTreeHash(commit util.Hash) (util.Hash, error) {
+func (repo *GitRepo) GetTreeHash(commit git.Hash) (git.Hash, error) {
 	stdout, err := repo.runGitCommand("rev-parse", string(commit)+"^{tree}")
 
 	if err != nil {
 		return "", nil
 	}
 
-	return util.Hash(stdout), nil
+	return git.Hash(stdout), nil
 }
 
 // AddRemote add a new remote to the repository
@@ -337,19 +338,19 @@ func (repo *GitRepo) AddRemote(name string, url string) error {
 
 func (repo *GitRepo) createClocks() {
 	createPath := path.Join(repo.Path, createClockFile)
-	repo.createClock = util.NewPersistedLamport(createPath)
+	repo.createClock = lamport.NewPersisted(createPath)
 
 	editPath := path.Join(repo.Path, editClockFile)
-	repo.editClock = util.NewPersistedLamport(editPath)
+	repo.editClock = lamport.NewPersisted(editPath)
 }
 
 func (repo *GitRepo) LoadClocks() error {
-	createClock, err := util.LoadPersistedLamport(repo.GetPath() + createClockFile)
+	createClock, err := lamport.LoadPersisted(repo.GetPath() + createClockFile)
 	if err != nil {
 		return err
 	}
 
-	editClock, err := util.LoadPersistedLamport(repo.GetPath() + editClockFile)
+	editClock, err := lamport.LoadPersisted(repo.GetPath() + editClockFile)
 	if err != nil {
 		return err
 	}
@@ -373,18 +374,18 @@ func (repo *GitRepo) WriteClocks() error {
 	return nil
 }
 
-func (repo *GitRepo) CreateTimeIncrement() (util.LamportTime, error) {
+func (repo *GitRepo) CreateTimeIncrement() (lamport.Time, error) {
 	return repo.createClock.Increment()
 }
 
-func (repo *GitRepo) EditTimeIncrement() (util.LamportTime, error) {
+func (repo *GitRepo) EditTimeIncrement() (lamport.Time, error) {
 	return repo.editClock.Increment()
 }
 
-func (repo *GitRepo) CreateWitness(time util.LamportTime) error {
+func (repo *GitRepo) CreateWitness(time lamport.Time) error {
 	return repo.createClock.Witness(time)
 }
 
-func (repo *GitRepo) EditWitness(time util.LamportTime) error {
+func (repo *GitRepo) EditWitness(time lamport.Time) error {
 	return repo.editClock.Witness(time)
 }

repository/mock_repo.go 🔗

@@ -4,32 +4,33 @@ import (
 	"crypto/sha1"
 	"fmt"
 
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
+	"github.com/MichaelMure/git-bug/util/lamport"
 )
 
 // mockRepoForTest defines an instance of Repo that can be used for testing.
 type mockRepoForTest struct {
-	blobs       map[util.Hash][]byte
-	trees       map[util.Hash]string
-	commits     map[util.Hash]commit
-	refs        map[string]util.Hash
-	createClock util.LamportClock
-	editClock   util.LamportClock
+	blobs       map[git.Hash][]byte
+	trees       map[git.Hash]string
+	commits     map[git.Hash]commit
+	refs        map[string]git.Hash
+	createClock lamport.Clock
+	editClock   lamport.Clock
 }
 
 type commit struct {
-	treeHash util.Hash
-	parent   util.Hash
+	treeHash git.Hash
+	parent   git.Hash
 }
 
 func NewMockRepoForTest() Repo {
 	return &mockRepoForTest{
-		blobs:       make(map[util.Hash][]byte),
-		trees:       make(map[util.Hash]string),
-		commits:     make(map[util.Hash]commit),
-		refs:        make(map[string]util.Hash),
-		createClock: util.NewLamportClock(),
-		editClock:   util.NewLamportClock(),
+		blobs:       make(map[git.Hash][]byte),
+		trees:       make(map[git.Hash]string),
+		commits:     make(map[git.Hash]commit),
+		refs:        make(map[string]git.Hash),
+		createClock: lamport.NewClock(),
+		editClock:   lamport.NewClock(),
 	}
 }
 
@@ -61,14 +62,14 @@ func (r *mockRepoForTest) FetchRefs(remote string, refSpec string) (string, erro
 	return "", nil
 }
 
-func (r *mockRepoForTest) StoreData(data []byte) (util.Hash, error) {
+func (r *mockRepoForTest) StoreData(data []byte) (git.Hash, error) {
 	rawHash := sha1.Sum(data)
-	hash := util.Hash(fmt.Sprintf("%x", rawHash))
+	hash := git.Hash(fmt.Sprintf("%x", rawHash))
 	r.blobs[hash] = data
 	return hash, nil
 }
 
-func (r *mockRepoForTest) ReadData(hash util.Hash) ([]byte, error) {
+func (r *mockRepoForTest) ReadData(hash git.Hash) ([]byte, error) {
 	data, ok := r.blobs[hash]
 
 	if !ok {
@@ -78,27 +79,27 @@ func (r *mockRepoForTest) ReadData(hash util.Hash) ([]byte, error) {
 	return data, nil
 }
 
-func (r *mockRepoForTest) StoreTree(entries []TreeEntry) (util.Hash, error) {
+func (r *mockRepoForTest) StoreTree(entries []TreeEntry) (git.Hash, error) {
 	buffer := prepareTreeEntries(entries)
 	rawHash := sha1.Sum(buffer.Bytes())
-	hash := util.Hash(fmt.Sprintf("%x", rawHash))
+	hash := git.Hash(fmt.Sprintf("%x", rawHash))
 	r.trees[hash] = buffer.String()
 
 	return hash, nil
 }
 
-func (r *mockRepoForTest) StoreCommit(treeHash util.Hash) (util.Hash, error) {
+func (r *mockRepoForTest) StoreCommit(treeHash git.Hash) (git.Hash, error) {
 	rawHash := sha1.Sum([]byte(treeHash))
-	hash := util.Hash(fmt.Sprintf("%x", rawHash))
+	hash := git.Hash(fmt.Sprintf("%x", rawHash))
 	r.commits[hash] = commit{
 		treeHash: treeHash,
 	}
 	return hash, nil
 }
 
-func (r *mockRepoForTest) StoreCommitWithParent(treeHash util.Hash, parent util.Hash) (util.Hash, error) {
+func (r *mockRepoForTest) StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error) {
 	rawHash := sha1.Sum([]byte(treeHash + parent))
-	hash := util.Hash(fmt.Sprintf("%x", rawHash))
+	hash := git.Hash(fmt.Sprintf("%x", rawHash))
 	r.commits[hash] = commit{
 		treeHash: treeHash,
 		parent:   parent,
@@ -106,7 +107,7 @@ func (r *mockRepoForTest) StoreCommitWithParent(treeHash util.Hash, parent util.
 	return hash, nil
 }
 
-func (r *mockRepoForTest) UpdateRef(ref string, hash util.Hash) error {
+func (r *mockRepoForTest) UpdateRef(ref string, hash git.Hash) error {
 	r.refs[ref] = hash
 	return nil
 }
@@ -139,8 +140,8 @@ func (r *mockRepoForTest) ListRefs(refspec string) ([]string, error) {
 	return keys, nil
 }
 
-func (r *mockRepoForTest) ListCommits(ref string) ([]util.Hash, error) {
-	var hashes []util.Hash
+func (r *mockRepoForTest) ListCommits(ref string) ([]git.Hash, error) {
+	var hashes []git.Hash
 
 	hash := r.refs[ref]
 
@@ -151,14 +152,14 @@ func (r *mockRepoForTest) ListCommits(ref string) ([]util.Hash, error) {
 			break
 		}
 
-		hashes = append([]util.Hash{hash}, hashes...)
+		hashes = append([]git.Hash{hash}, hashes...)
 		hash = commit.parent
 	}
 
 	return hashes, nil
 }
 
-func (r *mockRepoForTest) ListEntries(hash util.Hash) ([]TreeEntry, error) {
+func (r *mockRepoForTest) ListEntries(hash git.Hash) ([]TreeEntry, error) {
 	var data string
 
 	data, ok := r.trees[hash]
@@ -181,11 +182,11 @@ func (r *mockRepoForTest) ListEntries(hash util.Hash) ([]TreeEntry, error) {
 	return readTreeEntries(data)
 }
 
-func (r *mockRepoForTest) FindCommonAncestor(hash1 util.Hash, hash2 util.Hash) (util.Hash, error) {
+func (r *mockRepoForTest) FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error) {
 	panic("implement me")
 }
 
-func (r *mockRepoForTest) GetTreeHash(commit util.Hash) (util.Hash, error) {
+func (r *mockRepoForTest) GetTreeHash(commit git.Hash) (git.Hash, error) {
 	panic("implement me")
 }
 
@@ -197,20 +198,20 @@ func (r *mockRepoForTest) WriteClocks() error {
 	return nil
 }
 
-func (r *mockRepoForTest) CreateTimeIncrement() (util.LamportTime, error) {
+func (r *mockRepoForTest) CreateTimeIncrement() (lamport.Time, error) {
 	return r.createClock.Increment(), nil
 }
 
-func (r *mockRepoForTest) EditTimeIncrement() (util.LamportTime, error) {
+func (r *mockRepoForTest) EditTimeIncrement() (lamport.Time, error) {
 	return r.editClock.Increment(), nil
 }
 
-func (r *mockRepoForTest) CreateWitness(time util.LamportTime) error {
+func (r *mockRepoForTest) CreateWitness(time lamport.Time) error {
 	r.createClock.Witness(time)
 	return nil
 }
 
-func (r *mockRepoForTest) EditWitness(time util.LamportTime) error {
+func (r *mockRepoForTest) EditWitness(time lamport.Time) error {
 	r.editClock.Witness(time)
 	return nil
 }

repository/repo.go 🔗

@@ -5,7 +5,8 @@ import (
 	"bytes"
 	"strings"
 
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
+	"github.com/MichaelMure/git-bug/util/lamport"
 )
 
 // Repo represents a source code repository.
@@ -29,22 +30,22 @@ type Repo interface {
 	PushRefs(remote string, refSpec string) (string, error)
 
 	// StoreData will store arbitrary data and return the corresponding hash
-	StoreData(data []byte) (util.Hash, error)
+	StoreData(data []byte) (git.Hash, error)
 
 	// ReadData will attempt to read arbitrary data from the given hash
-	ReadData(hash util.Hash) ([]byte, error)
+	ReadData(hash git.Hash) ([]byte, error)
 
 	// StoreTree will store a mapping key-->Hash as a Git tree
-	StoreTree(mapping []TreeEntry) (util.Hash, error)
+	StoreTree(mapping []TreeEntry) (git.Hash, error)
 
 	// StoreCommit will store a Git commit with the given Git tree
-	StoreCommit(treeHash util.Hash) (util.Hash, error)
+	StoreCommit(treeHash git.Hash) (git.Hash, error)
 
 	// StoreCommit will store a Git commit with the given Git tree
-	StoreCommitWithParent(treeHash util.Hash, parent util.Hash) (util.Hash, error)
+	StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error)
 
 	// UpdateRef will create or update a Git reference
-	UpdateRef(ref string, hash util.Hash) error
+	UpdateRef(ref string, hash git.Hash) error
 
 	// ListRefs will return a list of Git ref matching the given refspec
 	ListRefs(refspec string) ([]string, error)
@@ -56,28 +57,28 @@ type Repo interface {
 	CopyRef(source string, dest string) error
 
 	// ListCommits will return the list of tree hashes of a ref, in chronological order
-	ListCommits(ref string) ([]util.Hash, error)
+	ListCommits(ref string) ([]git.Hash, error)
 
 	// ListEntries will return the list of entries in a Git tree
-	ListEntries(hash util.Hash) ([]TreeEntry, error)
+	ListEntries(hash git.Hash) ([]TreeEntry, error)
 
 	// FindCommonAncestor will return the last common ancestor of two chain of commit
-	FindCommonAncestor(hash1 util.Hash, hash2 util.Hash) (util.Hash, error)
+	FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error)
 
 	// GetTreeHash return the git tree hash referenced in a commit
-	GetTreeHash(commit util.Hash) (util.Hash, error)
+	GetTreeHash(commit git.Hash) (git.Hash, error)
 
 	LoadClocks() error
 
 	WriteClocks() error
 
-	CreateTimeIncrement() (util.LamportTime, error)
+	CreateTimeIncrement() (lamport.Time, error)
 
-	EditTimeIncrement() (util.LamportTime, error)
+	EditTimeIncrement() (lamport.Time, error)
 
-	CreateWitness(time util.LamportTime) error
+	CreateWitness(time lamport.Time) error
 
-	EditWitness(time util.LamportTime) error
+	EditWitness(time lamport.Time) error
 }
 
 func prepareTreeEntries(entries []TreeEntry) bytes.Buffer {

repository/tree_entry.go 🔗

@@ -4,12 +4,12 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 )
 
 type TreeEntry struct {
 	ObjectType ObjectType
-	Hash       util.Hash
+	Hash       git.Hash
 	Name       string
 }
 
@@ -34,7 +34,7 @@ func ParseTreeEntry(line string) (TreeEntry, error) {
 		return TreeEntry{}, err
 	}
 
-	hash := util.Hash(fields[2])
+	hash := git.Hash(fields[2])
 	name := strings.Join(fields[3:], "")
 
 	return TreeEntry{

repository/tree_entry_test.go 🔗

@@ -1,15 +1,15 @@
 package repository
 
 import (
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/git"
 	"testing"
 )
 
 func TestTreeEntryFormat(t *testing.T) {
 
 	entries := []TreeEntry{
-		{Blob, util.Hash("a85730cf5287d40a1e32d3a671ba2296c73387cb"), "name"},
-		{Tree, util.Hash("a85730cf5287d40a1e32d3a671ba2296c73387cb"), "name"},
+		{Blob, git.Hash("a85730cf5287d40a1e32d3a671ba2296c73387cb"), "name"},
+		{Tree, git.Hash("a85730cf5287d40a1e32d3a671ba2296c73387cb"), "name"},
 	}
 
 	for _, entry := range entries {

termui/bug_table.go 🔗

@@ -6,7 +6,8 @@ import (
 
 	"github.com/MichaelMure/git-bug/bug"
 	"github.com/MichaelMure/git-bug/cache"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/colors"
+	"github.com/MichaelMure/git-bug/util/text"
 	"github.com/dustin/go-humanize"
 	"github.com/jroimartin/gocui"
 )
@@ -296,18 +297,18 @@ func (bt *bugTable) render(v *gocui.View, maxX int) {
 			person = create.Author
 		}
 
-		id := util.LeftPaddedString(snap.HumanId(), columnWidths["id"], 2)
-		status := util.LeftPaddedString(snap.Status.String(), columnWidths["status"], 2)
-		title := util.LeftPaddedString(snap.Title, columnWidths["title"], 2)
-		author := util.LeftPaddedString(person.Name, columnWidths["author"], 2)
-		summary := util.LeftPaddedString(snap.Summary(), columnWidths["summary"], 2)
-		lastEdit := util.LeftPaddedString(humanize.Time(snap.LastEditTime()), columnWidths["lastEdit"], 2)
+		id := text.LeftPaddedString(snap.HumanId(), columnWidths["id"], 2)
+		status := text.LeftPaddedString(snap.Status.String(), columnWidths["status"], 2)
+		title := text.LeftPaddedString(snap.Title, columnWidths["title"], 2)
+		author := text.LeftPaddedString(person.Name, columnWidths["author"], 2)
+		summary := text.LeftPaddedString(snap.Summary(), columnWidths["summary"], 2)
+		lastEdit := text.LeftPaddedString(humanize.Time(snap.LastEditTime()), columnWidths["lastEdit"], 2)
 
 		fmt.Fprintf(v, "%s %s %s %s %s %s\n",
-			util.Cyan(id),
-			util.Yellow(status),
+			colors.Cyan(id),
+			colors.Yellow(status),
 			title,
-			util.Magenta(author),
+			colors.Magenta(author),
 			summary,
 			lastEdit,
 		)
@@ -317,12 +318,12 @@ func (bt *bugTable) render(v *gocui.View, maxX int) {
 func (bt *bugTable) renderHeader(v *gocui.View, maxX int) {
 	columnWidths := bt.getColumnWidths(maxX)
 
-	id := util.LeftPaddedString("ID", columnWidths["id"], 2)
-	status := util.LeftPaddedString("STATUS", columnWidths["status"], 2)
-	title := util.LeftPaddedString("TITLE", columnWidths["title"], 2)
-	author := util.LeftPaddedString("AUTHOR", columnWidths["author"], 2)
-	summary := util.LeftPaddedString("SUMMARY", columnWidths["summary"], 2)
-	lastEdit := util.LeftPaddedString("LAST EDIT", columnWidths["lastEdit"], 2)
+	id := text.LeftPaddedString("ID", columnWidths["id"], 2)
+	status := text.LeftPaddedString("STATUS", columnWidths["status"], 2)
+	title := text.LeftPaddedString("TITLE", columnWidths["title"], 2)
+	author := text.LeftPaddedString("AUTHOR", columnWidths["author"], 2)
+	summary := text.LeftPaddedString("SUMMARY", columnWidths["summary"], 2)
+	lastEdit := text.LeftPaddedString("LAST EDIT", columnWidths["lastEdit"], 2)
 
 	fmt.Fprintf(v, "\n")
 	fmt.Fprintf(v, "%s %s %s %s %s %s\n", id, status, title, author, summary, lastEdit)
@@ -433,7 +434,7 @@ func (bt *bugTable) pull(g *gocui.Gui, v *gocui.View) error {
 				})
 			} else {
 				fmt.Fprintf(&buffer, "%s%s: %s",
-					beginLine, util.Cyan(merge.Bug.HumanId()), merge.Status,
+					beginLine, colors.Cyan(merge.Bug.HumanId()), merge.Status,
 				)
 
 				beginLine = "\n"

termui/msg_popup.go 🔗

@@ -3,7 +3,7 @@ package termui
 import (
 	"fmt"
 
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/util/text"
 	"github.com/jroimartin/gocui"
 )
 
@@ -45,7 +45,7 @@ func (ep *msgPopup) layout(g *gocui.Gui) error {
 	maxX, maxY := g.Size()
 
 	width := minInt(60, maxX)
-	wrapped, lines := util.TextWrap(ep.message, width-2)
+	wrapped, lines := text.Wrap(ep.message, width-2)
 	height := minInt(lines+1, maxY-3)
 	x0 := (maxX - width) / 2
 	y0 := (maxY - height) / 2

termui/show_bug.go 🔗

@@ -5,9 +5,10 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/MichaelMure/git-bug/bug/operations"
 	"github.com/MichaelMure/git-bug/cache"
-	"github.com/MichaelMure/git-bug/util"
+	"github.com/MichaelMure/git-bug/operations"
+	"github.com/MichaelMure/git-bug/util/colors"
+	"github.com/MichaelMure/git-bug/util/text"
 	"github.com/jroimartin/gocui"
 )
 
@@ -209,13 +210,13 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 	sb.mainSelectableView = nil
 
 	bugHeader := fmt.Sprintf("[%s] %s\n\n[%s] %s opened this bug on %s",
-		util.Cyan(snap.HumanId()),
-		util.Bold(snap.Title),
-		util.Yellow(snap.Status),
-		util.Magenta(snap.Author.Name),
+		colors.Cyan(snap.HumanId()),
+		colors.Bold(snap.Title),
+		colors.Yellow(snap.Status),
+		colors.Magenta(snap.Author.Name),
 		snap.CreatedAt.Format(timeLayout),
 	)
-	bugHeader, lines := util.TextWrap(bugHeader, maxX)
+	bugHeader, lines := text.Wrap(bugHeader, maxX)
 
 	v, err := sb.createOpView(g, showBugHeaderView, x0, y0, maxX+1, lines, false)
 	if err != nil {
@@ -235,7 +236,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 
 		case operations.CreateOperation:
 			create := op.(operations.CreateOperation)
-			content, lines := util.TextWrapPadded(create.Message, maxX, 4)
+			content, lines := text.WrapLeftPadded(create.Message, maxX, 4)
 
 			v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true)
 			if err != nil {
@@ -247,13 +248,13 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 		case operations.AddCommentOperation:
 			comment := op.(operations.AddCommentOperation)
 
-			message, _ := util.TextWrapPadded(comment.Message, maxX, 4)
+			message, _ := text.WrapLeftPadded(comment.Message, maxX, 4)
 			content := fmt.Sprintf("%s commented on %s\n\n%s",
-				util.Magenta(comment.Author.Name),
+				colors.Magenta(comment.Author.Name),
 				comment.Time().Format(timeLayout),
 				message,
 			)
-			content, lines = util.TextWrap(content, maxX)
+			content, lines = text.Wrap(content, maxX)
 
 			v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true)
 			if err != nil {
@@ -266,11 +267,11 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 			setTitle := op.(operations.SetTitleOperation)
 
 			content := fmt.Sprintf("%s changed the title to %s on %s",
-				util.Magenta(setTitle.Author.Name),
-				util.Bold(setTitle.Title),
+				colors.Magenta(setTitle.Author.Name),
+				colors.Bold(setTitle.Title),
 				setTitle.Time().Format(timeLayout),
 			)
-			content, lines := util.TextWrap(content, maxX)
+			content, lines := text.Wrap(content, maxX)
 
 			v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true)
 			if err != nil {
@@ -283,11 +284,11 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 			setStatus := op.(operations.SetStatusOperation)
 
 			content := fmt.Sprintf("%s %s the bug on %s",
-				util.Magenta(setStatus.Author.Name),
-				util.Bold(setStatus.Status.Action()),
+				colors.Magenta(setStatus.Author.Name),
+				colors.Bold(setStatus.Status.Action()),
 				setStatus.Time().Format(timeLayout),
 			)
-			content, lines := util.TextWrap(content, maxX)
+			content, lines := text.Wrap(content, maxX)
 
 			v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true)
 			if err != nil {
@@ -301,12 +302,12 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 
 			var added []string
 			for _, label := range labelChange.Added {
-				added = append(added, util.Bold("\""+label+"\""))
+				added = append(added, colors.Bold("\""+label+"\""))
 			}
 
 			var removed []string
 			for _, label := range labelChange.Removed {
-				removed = append(removed, util.Bold("\""+label+"\""))
+				removed = append(removed, colors.Bold("\""+label+"\""))
 			}
 
 			var action bytes.Buffer
@@ -332,11 +333,11 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error {
 			}
 
 			content := fmt.Sprintf("%s %s on %s",
-				util.Magenta(labelChange.Author.Name),
+				colors.Magenta(labelChange.Author.Name),
 				action.String(),
 				labelChange.Time().Format(timeLayout),
 			)
-			content, lines := util.TextWrap(content, maxX)
+			content, lines := text.Wrap(content, maxX)
 
 			v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true)
 			if err != nil {
@@ -402,9 +403,9 @@ func (sb *showBug) renderSidebar(g *gocui.Gui, sideView *gocui.View) error {
 	}
 
 	labels := strings.Join(labelStr, "\n")
-	labels, lines := util.TextWrapPadded(labels, maxX, 2)
+	labels, lines := text.WrapLeftPadded(labels, maxX, 2)
 
-	content := fmt.Sprintf("%s\n\n%s", util.Bold("Labels"), labels)
+	content := fmt.Sprintf("%s\n\n%s", colors.Bold("Labels"), labels)
 
 	v, err := sb.createSideView(g, "sideLabels", x0, y0, maxX, lines+2)
 	if err != nil {

tests/bug_actions_test.go 🔗

@@ -7,7 +7,7 @@ import (
 	"testing"
 
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/bug/operations"
+	"github.com/MichaelMure/git-bug/operations"
 	"github.com/MichaelMure/git-bug/repository"
 )
 

tests/operation_iterator_test.go 🔗

@@ -2,7 +2,7 @@ package tests
 
 import (
 	"github.com/MichaelMure/git-bug/bug"
-	"github.com/MichaelMure/git-bug/bug/operations"
+	"github.com/MichaelMure/git-bug/operations"
 	"github.com/MichaelMure/git-bug/repository"
 	"testing"
 )

util/colors.go → util/colors/colors.go 🔗

@@ -1,4 +1,4 @@
-package util
+package colors
 
 import "github.com/fatih/color"
 

util/lamport.go → util/lamport/lamport.go 🔗

@@ -25,47 +25,47 @@
 
 */
 
-package util
+package lamport
 
 import (
 	"sync/atomic"
 )
 
-// LamportClock is a thread safe implementation of a lamport clock. It
+// Clock is a thread safe implementation of a lamport clock. It
 // uses efficient atomic operations for all of its functions, falling back
 // to a heavy lock only if there are enough CAS failures.
-type LamportClock struct {
+type Clock struct {
 	counter uint64
 }
 
-// LamportTime is the value of a LamportClock.
-type LamportTime uint64
+// Time is the value of a Clock.
+type Time uint64
 
-func NewLamportClock() LamportClock {
-	return LamportClock{
+func NewClock() Clock {
+	return Clock{
 		counter: 1,
 	}
 }
 
-func NewLamportClockWithTime(time uint64) LamportClock {
-	return LamportClock{
+func NewClockWithTime(time uint64) Clock {
+	return Clock{
 		counter: time,
 	}
 }
 
 // Time is used to return the current value of the lamport clock
-func (l *LamportClock) Time() LamportTime {
-	return LamportTime(atomic.LoadUint64(&l.counter))
+func (l *Clock) Time() Time {
+	return Time(atomic.LoadUint64(&l.counter))
 }
 
 // Increment is used to return the value of the lamport clock and increment it afterwards
-func (l *LamportClock) Increment() LamportTime {
-	return LamportTime(atomic.AddUint64(&l.counter, 1) - 1)
+func (l *Clock) Increment() Time {
+	return Time(atomic.AddUint64(&l.counter, 1) - 1)
 }
 
 // Witness is called to update our local clock if necessary after
 // witnessing a clock value received from another process
-func (l *LamportClock) Witness(v LamportTime) {
+func (l *Clock) Witness(v Time) {
 WITNESS:
 	// If the other value is old, we do not need to do anything
 	cur := atomic.LoadUint64(&l.counter)

util/lamport_test.go → util/lamport/lamport_test.go 🔗

@@ -25,14 +25,14 @@
 
 */
 
-package util
+package lamport
 
 import (
 	"testing"
 )
 
-func TestLamportClock(t *testing.T) {
-	l := &LamportClock{}
+func TestClock(t *testing.T) {
+	l := &Clock{}
 
 	if l.Time() != 0 {
 		t.Fatalf("bad time value")

util/persisted_lamport.go → util/lamport/persisted_lamport.go 🔗

@@ -1,4 +1,4 @@
-package util
+package lamport
 
 import (
 	"fmt"
@@ -7,21 +7,21 @@ import (
 	"path/filepath"
 )
 
-type PersistedLamport struct {
-	LamportClock
+type Persisted struct {
+	Clock
 	filePath string
 }
 
-func NewPersistedLamport(filePath string) *PersistedLamport {
-	clock := &PersistedLamport{
-		LamportClock: NewLamportClock(),
-		filePath:     filePath,
+func NewPersisted(filePath string) *Persisted {
+	clock := &Persisted{
+		Clock:    NewClock(),
+		filePath: filePath,
 	}
 	return clock
 }
 
-func LoadPersistedLamport(filePath string) (*PersistedLamport, error) {
-	clock := &PersistedLamport{
+func LoadPersisted(filePath string) (*Persisted, error) {
+	clock := &Persisted{
 		filePath: filePath,
 	}
 
@@ -33,18 +33,18 @@ func LoadPersistedLamport(filePath string) (*PersistedLamport, error) {
 	return clock, nil
 }
 
-func (c *PersistedLamport) Increment() (LamportTime, error) {
-	time := c.LamportClock.Increment()
+func (c *Persisted) Increment() (Time, error) {
+	time := c.Clock.Increment()
 	return time, c.Write()
 }
 
-func (c *PersistedLamport) Witness(time LamportTime) error {
+func (c *Persisted) Witness(time Time) error {
 	// TODO: rework so that we write only when the clock was actually updated
-	c.LamportClock.Witness(time)
+	c.Clock.Witness(time)
 	return c.Write()
 }
 
-func (c *PersistedLamport) read() error {
+func (c *Persisted) read() error {
 	content, err := ioutil.ReadFile(c.filePath)
 	if err != nil {
 		return err
@@ -61,12 +61,12 @@ func (c *PersistedLamport) read() error {
 		return fmt.Errorf("could not read the clock")
 	}
 
-	c.LamportClock = NewLamportClockWithTime(value)
+	c.Clock = NewClockWithTime(value)
 
 	return nil
 }
 
-func (c *PersistedLamport) Write() error {
+func (c *Persisted) Write() error {
 	dir := filepath.Dir(c.filePath)
 	err := os.MkdirAll(dir, 0777)
 	if err != nil {

util/process.go → util/process/process.go 🔗

@@ -1,12 +1,12 @@
-package util
+package process
 
 import (
 	"os"
 	"syscall"
 )
 
-// ProcessIsRunning tell is a process is running
-func ProcessIsRunning(pid int) bool {
+// IsRunning tell is a process is running
+func IsRunning(pid int) bool {
 	// never return no error in a unix system
 	process, err := os.FindProcess(pid)
 

util/text.go → util/text/text.go 🔗

@@ -1,41 +1,19 @@
-package util
+package text
 
 import (
 	"bytes"
 	"strings"
 )
 
-func WordWrap(text string, lineWidth int) (string, int) {
-	words := strings.Fields(strings.TrimSpace(text))
-	if len(words) == 0 {
-		return "", 1
-	}
-	lines := 1
-	wrapped := words[0]
-	spaceLeft := lineWidth - len(wrapped)
-	for _, word := range words[1:] {
-		if len(word)+1 > spaceLeft {
-			wrapped += "\n" + word
-			spaceLeft = lineWidth - len(word)
-			lines++
-		} else {
-			wrapped += " " + word
-			spaceLeft -= 1 + len(word)
-		}
-	}
-
-	return wrapped, lines
-}
-
 // Wrap a text for an exact line size
 // Handle properly terminal color escape code
-func TextWrap(text string, lineWidth int) (string, int) {
-	return TextWrapPadded(text, lineWidth, 0)
+func Wrap(text string, lineWidth int) (string, int) {
+	return WrapLeftPadded(text, lineWidth, 0)
 }
 
 // Wrap a text for an exact line size with a left padding
 // Handle properly terminal color escape code
-func TextWrapPadded(text string, lineWidth int, leftPad int) (string, int) {
+func WrapLeftPadded(text string, lineWidth int, leftPad int) (string, int) {
 	var textBuffer bytes.Buffer
 	var lineBuffer bytes.Buffer
 	nbLine := 1

util/text_test.go → util/text/text_test.go 🔗

@@ -1,11 +1,11 @@
-package util
+package text
 
 import (
 	"strings"
 	"testing"
 )
 
-func TestTextWrap(t *testing.T) {
+func TestWrap(t *testing.T) {
 	cases := []struct {
 		Input, Output string
 		Lim           int
@@ -92,7 +92,7 @@ func TestTextWrap(t *testing.T) {
 	}
 
 	for i, tc := range cases {
-		actual, lines := TextWrap(tc.Input, tc.Lim)
+		actual, lines := Wrap(tc.Input, tc.Lim)
 		if actual != tc.Output {
 			t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s`\n\nActual Output:\n\n`%s`",
 				i, tc.Input, tc.Output, actual)