summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-12-05 01:24:48 +0300
committerIbrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>2018-12-05 01:24:48 +0300
commit357761313b00cb5799b2971631c4adfb2daaa98e (patch)
tree24d56318bf578160c150b01c8e8f9ae06bc6da7b
parentqueue converted to first in first out principle (diff)
downloadgitbatch-357761313b00cb5799b2971631c4adfb2daaa98e.tar.gz
added sorting
-rw-r--r--README.md6
-rw-r--r--pkg/git/repository-sort.go59
-rw-r--r--pkg/git/repository.go10
-rw-r--r--pkg/gui/gui-util.go25
-rw-r--r--pkg/gui/keybindings.go16
-rw-r--r--pkg/gui/mainview.go2
6 files changed, 114 insertions, 4 deletions
diff --git a/README.md b/README.md
index ba70ce8..0d42830 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
[![Build Status](https://travis-ci.com/isacikgoz/gitbatch.svg?branch=master)](https://travis-ci.com/isacikgoz/gitbatch) [![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](/LICENSE) [![Go Report Card](https://goreportcard.com/badge/github.com/isacikgoz/gitbatch)](https://goreportcard.com/report/github.com/isacikgoz/gitbatch)
## gitbatch
-Aim of this tool to make your local repositories synchronized with remotes easily. Since my daily work is tied to many repositories I often end up walking on many directories and manually pulling updates etc. To make this routine more elegant, I created a simple tool to handle this job. I really enjoy working on this project and I hope it will be a useful tool.
+Aim of this tool to make your local repositories synchronized with remotes easily. Inspired from lazygit and I build this according to my needs; Since my daily work is tied to many repositories I often end up walking on many directories and manually pulling updates etc. To make this routine faster, I created a simple tool to handle this job. I really enjoy working on this project and I hope it will be a useful tool.
**Disclaimer**
- Authentication required repositories are **not supported** using ssh is recommended if you need to authenticate to fetch/pull
@@ -77,8 +77,8 @@ run the `gitbatch` command from the parent of your git repositories. For start-u
## Further goals
- add testing
- select all feature
-- arrange repositories to an order e.g. alphabetic, last modified, etc.
-- shift keys, i.e. **s** for iterate **alt + s** for reverse iteration (partially implemented)
+- arrange repositories to an order e.g. alphabetic, last modified, etc. ✔
+- shift keys, i.e. **s** for iterate **alt + s** for reverse iteration ✔
- recursive repository search from the filesystem
- full src-d/go-git integration (*having some performance issues*)
- implement config file to pre-define repo locations or some settings
diff --git a/pkg/git/repository-sort.go b/pkg/git/repository-sort.go
new file mode 100644
index 0000000..04cd9e7
--- /dev/null
+++ b/pkg/git/repository-sort.go
@@ -0,0 +1,59 @@
+package git
+
+import (
+ "unicode"
+)
+
+// Alphabetical slice is the re-ordered *RepoEntity slice that sorted according
+// to alphabetical order (A-Z)
+type Alphabetical []*RepoEntity
+
+// Len is the interface implementation for Alphabetical sorting function
+func (s Alphabetical) Len() int { return len(s) }
+
+// Swap is the interface implementation for Alphabetical sorting function
+func (s Alphabetical) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// Less is the interface implementation for Alphabetical sorting function
+func (s Alphabetical) Less(i, j int) bool {
+ iRunes := []rune(s[i].Name)
+ jRunes := []rune(s[j].Name)
+
+ max := len(iRunes)
+ if max > len(jRunes) {
+ max = len(jRunes)
+ }
+
+ for idx := 0; idx < max; idx++ {
+ ir := iRunes[idx]
+ jr := jRunes[idx]
+
+ lir := unicode.ToLower(ir)
+ ljr := unicode.ToLower(jr)
+
+ if lir != ljr {
+ return lir < ljr
+ }
+
+ // the lowercase runes are the same, so compare the original
+ if ir != jr {
+ return ir < jr
+ }
+ }
+ return false
+}
+
+// LastModified slice is the re-ordered *RepoEntity slice that sorted according
+// to last modified date of the repository directory
+type LastModified []*RepoEntity
+
+// Len is the interface implementation for LastModified sorting function
+func (s LastModified) Len() int { return len(s) }
+
+// Swap is the interface implementation for LastModified sorting function
+func (s LastModified) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// Less is the interface implementation for LastModified sorting function
+func (s LastModified) Less(i, j int) bool {
+ return s[i].ModTime.Unix() > s[j].ModTime.Unix()
+}
diff --git a/pkg/git/repository.go b/pkg/git/repository.go
index 73aebdf..6918371 100644
--- a/pkg/git/repository.go
+++ b/pkg/git/repository.go
@@ -2,6 +2,7 @@ package git
import (
"errors"
+ "time"
"os"
"github.com/isacikgoz/gitbatch/pkg/helpers"
@@ -16,6 +17,7 @@ type RepoEntity struct {
RepoID string
Name string
AbsPath string
+ ModTime time.Time
Repository git.Repository
Branch *Branch
Branches []*Branch
@@ -65,6 +67,7 @@ func InitializeRepository(directory string) (entity *RepoEntity, err error) {
entity = &RepoEntity{RepoID: helpers.RandomString(8),
Name: fileInfo.Name(),
AbsPath: directory,
+ ModTime: fileInfo.ModTime(),
Repository: *r,
State: Available,
}
@@ -156,11 +159,18 @@ func (entity *RepoEntity) Merge() error {
// fetch/pull/merge operations
func (entity *RepoEntity) Refresh() error {
var err error
+ // error can be ignored since the file already exists when app is loading
+ file, _ := os.Open(entity.AbsPath)
+ fileInfo, err := file.Stat()
+ if err != nil {
+ return err
+ }
r, err := git.PlainOpen(entity.AbsPath)
if err != nil {
return err
}
entity.Repository = *r
+ entity.ModTime = fileInfo.ModTime()
if err := entity.loadLocalBranches(); err != nil {
return err
}
diff --git a/pkg/gui/gui-util.go b/pkg/gui/gui-util.go
index c09ae6c..d3f0934 100644
--- a/pkg/gui/gui-util.go
+++ b/pkg/gui/gui-util.go
@@ -1,6 +1,8 @@
package gui
import (
+ "sort"
+
"github.com/isacikgoz/gitbatch/pkg/git"
"github.com/isacikgoz/gitbatch/pkg/helpers"
"github.com/jroimartin/gocui"
@@ -107,3 +109,26 @@ func writeRightHandSide(v *gocui.View, text string, cx, cy int) error {
v.SetCursor(cx, cy)
return nil
}
+
+// sortByName sorts the repositories by A to Z order
+func (gui *Gui) sortByName(g *gocui.Gui, v *gocui.View) error {
+ sort.Sort(git.Alphabetical(gui.State.Repositories))
+ gui.refreshAfterSort(g)
+ return nil
+}
+
+// sortByMod sorts the repositories according to last modifed date
+// the top element will be the last modified
+func (gui *Gui) sortByMod(g *gocui.Gui, v *gocui.View) error {
+ sort.Sort(git.LastModified(gui.State.Repositories))
+ gui.refreshAfterSort(g)
+ return nil
+}
+
+// utility function that refreshes main and side views after that
+func (gui *Gui) refreshAfterSort(g *gocui.Gui) error {
+ gui.refreshMain(g)
+ entity := gui.getSelectedRepository()
+ gui.refreshViews(g, entity)
+ return nil
+}
diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go
index f224bc3..3a96221 100644
--- a/pkg/gui/keybindings.go
+++ b/pkg/gui/keybindings.go
@@ -150,6 +150,22 @@ func (gui *Gui) generateKeybindings() error {
Description: "Add to queue",
Vital: true,
}, {
+ View: mainViewFeature.Name,
+ Key: 'n',
+ Modifier: gocui.ModNone,
+ Handler: gui.sortByName,
+ Display: "n",
+ Description: "Sort repositories by Name",
+ Vital: false,
+ }, {
+ View: mainViewFeature.Name,
+ Key: 'm',
+ Modifier: gocui.ModNone,
+ Handler: gui.sortByMod,
+ Display: "m",
+ Description: "Sort repositories by Modification date",
+ Vital: false,
+ }, {
View: commitDiffViewFeature.Name,
Key: 'c',
Modifier: gocui.ModNone,
diff --git a/pkg/gui/mainview.go b/pkg/gui/mainview.go
index e9bd1f3..6911c69 100644
--- a/pkg/gui/mainview.go
+++ b/pkg/gui/mainview.go
@@ -93,7 +93,7 @@ func (gui *Gui) getSelectedRepository() *git.RepoEntity {
return gui.State.Repositories[cy+oy]
}
-// marking repostiry is simply adding the repostirory into the queue. the
+// marking repository is simply adding the repostirory into the queue. the
// function does take its current state into account before adding it
func (gui *Gui) markRepository(g *gocui.Gui, v *gocui.View) error {
r := gui.getSelectedRepository()