diff options
| author | Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> | 2018-12-09 03:28:31 +0300 |
|---|---|---|
| committer | Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com> | 2018-12-09 03:28:31 +0300 |
| commit | ad96d97d0262df1e1ab3b054b8d2600c8d821d42 (patch) | |
| tree | f79da661cf2d7cdad2fdec1ad8e68e1e518ecab1 | |
| parent | added sync to remote branches with git fetch prune (diff) | |
| download | gitbatch-ad96d97d0262df1e1ab3b054b8d2600c8d821d42.tar.gz | |
added config file option and some minor bugfixes
| -rw-r--r-- | README.md | 8 | ||||
| -rw-r--r-- | main.go | 5 | ||||
| -rw-r--r-- | pkg/app/app.go | 25 | ||||
| -rw-r--r-- | pkg/app/config.go | 96 | ||||
| -rw-r--r-- | pkg/app/files.go | 2 | ||||
| -rw-r--r-- | pkg/git/status.go | 2 | ||||
| -rw-r--r-- | pkg/gui/stagedview.go | 1 | ||||
| -rw-r--r-- | pkg/gui/stashview.go | 1 | ||||
| -rw-r--r-- | pkg/gui/unstagedview.go | 1 |
9 files changed, 127 insertions, 14 deletions
@@ -10,7 +10,6 @@ Aim of this tool to make your local repositories synchronized with remotes easil - [BitBucket Set up an SSH key](https://confluence.atlassian.com/bitbucket/set-up-ssh-for-git-728138079.html) - Feedbacks are welcome. For now, known issues are: - At very low probability app fails to load repositories, try again it will load next time (multithreading problem). - - Sometimes when you scroll too fast while pulling/fetching/merging, some multithreading problem occurs and app crashes (will fix soon). - Colors vary to your terminal theme colors, so if the contrast is not enough on some color decisions; discussions are welcome. Here is the screencast of the app: @@ -46,13 +45,14 @@ For more information; - 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 +- implement config file to pre-define repo locations or some settings ✔ - resolve authentication issues ## Credits -- [go-git](https://github.com/src-d/go-git) for git interface +- [go-git](https://github.com/src-d/go-git) for git interface (partially) - [gocui](https://github.com/jroimartin/gocui) for user interface - [logrus](https://github.com/sirupsen/logrus) for logging -- [lazygit](https://github.com/jesseduffield/lazygit) as app template +- [viper](https://github.com/spf13/viper) for configuration management - [color](https://github.com/fatih/color) for colored text +- [lazygit](https://github.com/jesseduffield/lazygit) as app template and reference - [kingpin](https://github.com/alecthomas/kingpin) for command-line flag&options @@ -11,7 +11,8 @@ import ( var ( // take this as default directory if user does not start app with -d flag currentDir, err = os.Getwd() - dir = kingpin.Flag("directory", "Directory to roam for git repositories.").Default(currentDir).Short('d').String() + dir = kingpin.Flag("directory", "Directory to roam for git repositories").Default(currentDir).Short('d').String() + ignoreConfig = kingpin.Flag("ignore-config", "Ignore config file").Short('i').Bool() repoPattern = kingpin.Flag("pattern", "Pattern to filter repositories").Short('p').String() logLevel = kingpin.Flag("log-level", "Logging level; trace,debug,info,warn,error").Default("error").Short('l').String() ) @@ -22,7 +23,7 @@ func main() { kingpin.Parse() // set the app - app, err := app.Setup(*dir, *repoPattern, *logLevel) + app, err := app.Setup(*dir, *repoPattern, *logLevel, *ignoreConfig) if err != nil { log.Fatal(err) } diff --git a/pkg/app/app.go b/pkg/app/app.go index 624b048..e281abc 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -1,6 +1,8 @@ package app import ( + "os" + "github.com/isacikgoz/gitbatch/pkg/gui" log "github.com/sirupsen/logrus" ) @@ -14,13 +16,30 @@ type App struct { // Setup will handle pre-required operations. It is designed to be a wrapper for // main method right now. -func Setup(directory, repoPattern, logLevel string) (*App, error) { +func Setup(directory, repoPattern, logLevel string, ignoreConfig bool) (*App, error) { // initiate the app and give it initial values app := &App{} - app.Config, _ = LoadConfiguration() setLogLevel(logLevel) var err error - directories := generateDirectories(directory, repoPattern) + app.Config, err = LoadConfiguration() + if err != nil { + // the error types and handling is not considered yer + log.Error(err) + return app, err + } + workingDirectory, _ := os.Getwd() + + directories := make([]string, 0) + if len(app.Config.Directories) <= 0 || ignoreConfig || + (workingDirectory != directory && len(app.Config.Directories) > 0 ){ + directories = generateDirectories(directory, repoPattern) + } else { + for _, dir := range app.Config.Directories { + for _, d := range generateDirectories(dir, repoPattern) { + directories = append(directories, d) + } + } + } // create a gui.Gui struct and set it as App's gui app.Gui, err = gui.NewGui(app.Config.Mode, directories) diff --git a/pkg/app/config.go b/pkg/app/config.go index d34e647..815b5b0 100644 --- a/pkg/app/config.go +++ b/pkg/app/config.go @@ -1,16 +1,112 @@ package app import ( + "os" + "path/filepath" + "runtime" + "github.com/spf13/viper" + log "github.com/sirupsen/logrus" ) +// Config type is the configuration entity of the application type Config struct { Mode string Directories []string } +// config file stuff +var ( + configFileName = "config" + configFileExt = ".yml" + configType = "yaml" + appName = "gitbatch" + + configurationDirectory = filepath.Join(osConfigDirectory(), appName) + configFileAbsPath = filepath.Join(configurationDirectory, configFileName) +) + +// configuration items +var ( + modeKey = "mode" + modeKeyDefault = "fetch" + pathsKey = "paths" + pathsKeyDefault = []string{"."} +) + +// LoadConfiguration returns a Config struct is filled func LoadConfiguration() (*Config, error) { + if err := initializeConfigurationManager(); err != nil { + return nil, err + } + if err := setDefaults(); err != nil { + return nil, err + } + if err := readConfiguration(); err != nil { + return nil, err + } config := &Config{ + Mode: viper.GetString(modeKey), + Directories: viper.GetStringSlice(pathsKey), } return config, nil +} + +// set default configuration parameters +func setDefaults() error { + viper.SetDefault(modeKey, modeKeyDefault) + // viper.SetDefault(pathsKey, pathsKeyDefault) + return nil +} + +// read configuration from file +func readConfiguration() error{ + err := viper.ReadInConfig() // Find and read the config file + if err != nil { // Handle errors reading the config file + // if file does not exist, simply create one + if _, err := os.Stat(configFileAbsPath+configFileExt); os.IsNotExist(err) { + os.MkdirAll(configurationDirectory, 0755) + os.Create(configFileAbsPath+configFileExt) + } else { + return err + } + // let's write defaults + if err := viper.WriteConfig(); err != nil { + return err + } + } + return nil +} + +// write configuration to a file +func writeConfiguration() error{ + if err := viper.WriteConfig(); err != nil { + return err + } + return nil +} + +// initialize the configuration manager +func initializeConfigurationManager() error { + // config viper + viper.AddConfigPath(configurationDirectory) + viper.SetConfigName(configFileName) + viper.SetConfigType(configType) + + return nil +} + +// returns OS dependent config directory +func osConfigDirectory() (osConfigDirectory string) { + switch osname := runtime.GOOS; osname { + case "windows": + osConfigDirectory = os.Getenv("APPDATA") + case "darwin": + osConfigDirectory = os.Getenv("HOME") + "/Library/Application Support" + case "linux": + osConfigDirectory = os.Getenv("HOME") + "/.config" + default: + log.Warn("Operating system couldn't be recognized") + } + return osConfigDirectory }
\ No newline at end of file diff --git a/pkg/app/files.go b/pkg/app/files.go index f6ae947..b210c66 100644 --- a/pkg/app/files.go +++ b/pkg/app/files.go @@ -52,7 +52,7 @@ func filterDirectories(files []os.FileInfo, repoPattern string) []os.FileInfo { var filteredRepos []os.FileInfo for _, f := range files { // it is just a simple filter - if strings.Contains(f.Name(), repoPattern) { + if strings.Contains(f.Name(), repoPattern) && f.Name() != ".git" { filteredRepos = append(filteredRepos, f) } else { continue diff --git a/pkg/git/status.go b/pkg/git/status.go index 51a622b..5644a09 100644 --- a/pkg/git/status.go +++ b/pkg/git/status.go @@ -54,7 +54,7 @@ func (entity *RepoEntity) LoadFiles() ([]*File, error) { for _, file := range fileslist { x := rune(file[0]) y := rune(file[1]) - relativePathRegex := regexp.MustCompile(`[(\w|/|.)]+`) + relativePathRegex := regexp.MustCompile(`[(\w|/|.|\-)]+`) path := relativePathRegex.FindString(file[2:]) files = append(files, &File{ diff --git a/pkg/gui/stagedview.go b/pkg/gui/stagedview.go index bae80bd..91b0df3 100644 --- a/pkg/gui/stagedview.go +++ b/pkg/gui/stagedview.go @@ -17,7 +17,6 @@ func (gui *Gui) openStageView(g *gocui.Gui) error { return err } v.Title = stageViewFeature.Title - v.Wrap = true } entity := gui.getSelectedRepository() if err := refreshStagedView(g, entity); err != nil { diff --git a/pkg/gui/stashview.go b/pkg/gui/stashview.go index 7322328..c9c246e 100644 --- a/pkg/gui/stashview.go +++ b/pkg/gui/stashview.go @@ -17,7 +17,6 @@ func (gui *Gui) openStashView(g *gocui.Gui) error { return err } v.Title = stashViewFeature.Title - v.Wrap = true } entity := gui.getSelectedRepository() if err := refreshStashView(g, entity); err != nil { diff --git a/pkg/gui/unstagedview.go b/pkg/gui/unstagedview.go index ede4844..cf74ce4 100644 --- a/pkg/gui/unstagedview.go +++ b/pkg/gui/unstagedview.go @@ -17,7 +17,6 @@ func (gui *Gui) openUnStagedView(g *gocui.Gui) error { return err } v.Title = unstageViewFeature.Title - v.Wrap = true } entity := gui.getSelectedRepository() if err := refreshUnstagedView(g, entity); err != nil { |
