From b4547c56f3c28f0d03ee9437ec93c0e6fb6e0331 Mon Sep 17 00:00:00 2001 From: Ibrahim Serdar Acikgoz Date: Fri, 4 Jan 2019 03:24:46 +0300 Subject: huge refactor, package layour re-organized --- app/app.go | 111 +++++++ app/config.go | 123 ++++++++ app/files.go | 92 ++++++ app/quick.go | 50 ++++ core/command/cmd-add.go | 89 ++++++ core/command/cmd-commit.go | 92 ++++++ core/command/cmd-config.go | 106 +++++++ core/command/cmd-diff.go | 90 ++++++ core/command/cmd-fetch.go | 163 ++++++++++ core/command/cmd-merge.go | 39 +++ core/command/cmd-pull.go | 141 +++++++++ core/command/cmd-reset.go | 136 +++++++++ core/command/cmd-status.go | 94 ++++++ core/command/cmd.go | 98 ++++++ core/command/file.go | 92 ++++++ core/errors/util-errors.go | 59 ++++ core/git/authentication.go | 30 ++ core/git/branch.go | 209 +++++++++++++ core/git/commit.go | 179 +++++++++++ core/git/random.go | 18 ++ core/git/random_test.go | 11 + core/git/remote.go | 80 +++++ core/git/remotebranch.go | 90 ++++++ core/git/repository.go | 222 ++++++++++++++ core/git/sort.go | 59 ++++ core/git/stash.go | 127 ++++++++ core/job/job-queue.go | 127 ++++++++ core/job/job.go | 79 +++++ core/load/load.go | 92 ++++++ gui/authenticationview.go | 188 ++++++++++++ gui/commitview.go | 189 ++++++++++++ gui/controlsview.go | 36 +++ gui/diffview.go | 127 ++++++++ gui/errorview.go | 36 +++ gui/gui.go | 211 +++++++++++++ gui/keybindings.go | 675 ++++++++++++++++++++++++++++++++++++++++++ gui/mainview.go | 302 +++++++++++++++++++ gui/sideviews.go | 232 +++++++++++++++ gui/stagedview.go | 73 +++++ gui/stashview.go | 84 ++++++ gui/statusview.go | 162 ++++++++++ gui/unstagedview.go | 66 +++++ gui/util-common.go | 198 +++++++++++++ gui/util-textstyle.go | 186 ++++++++++++ main.go | 2 +- pkg/app/app.go | 111 ------- pkg/app/config.go | 123 -------- pkg/app/files.go | 92 ------ pkg/app/quick.go | 49 --- pkg/git/authentication.go | 30 -- pkg/git/branch.go | 159 ---------- pkg/git/cmd-add.go | 88 ------ pkg/git/cmd-commit.go | 91 ------ pkg/git/cmd-config.go | 105 ------- pkg/git/cmd-diff.go | 89 ------ pkg/git/cmd-fetch.go | 162 ---------- pkg/git/cmd-merge.go | 39 --- pkg/git/cmd-pull.go | 139 --------- pkg/git/cmd-reset.go | 135 --------- pkg/git/cmd-rev-list.go | 42 --- pkg/git/cmd-stash.go | 118 -------- pkg/git/cmd-status.go | 92 ------ pkg/git/cmd.go | 138 --------- pkg/git/commit.go | 142 --------- pkg/git/file.go | 52 ---- pkg/git/job-queue.go | 126 -------- pkg/git/job.go | 74 ----- pkg/git/remote.go | 80 ----- pkg/git/remotebranch.go | 90 ------ pkg/git/repository.go | 222 -------------- pkg/git/util-errors.go | 59 ---- pkg/git/util-load.go | 89 ------ pkg/git/util-random.go | 18 -- pkg/git/util-random_test.go | 11 - pkg/git/util-sort.go | 98 ------ pkg/gui/authenticationview.go | 186 ------------ pkg/gui/commitview.go | 189 ------------ pkg/gui/controlsview.go | 36 --- pkg/gui/diffview.go | 129 -------- pkg/gui/errorview.go | 36 --- pkg/gui/gui.go | 209 ------------- pkg/gui/keybindings.go | 675 ------------------------------------------ pkg/gui/mainview.go | 300 ------------------- pkg/gui/sideviews.go | 231 --------------- pkg/gui/stagedview.go | 73 ----- pkg/gui/stashview.go | 84 ------ pkg/gui/statusview.go | 164 ---------- pkg/gui/unstagedview.go | 66 ----- pkg/gui/util-common.go | 198 ------------- pkg/gui/util-textstyle.go | 185 ------------ 90 files changed, 5664 insertions(+), 5625 deletions(-) create mode 100644 app/app.go create mode 100644 app/config.go create mode 100644 app/files.go create mode 100644 app/quick.go create mode 100644 core/command/cmd-add.go create mode 100644 core/command/cmd-commit.go create mode 100644 core/command/cmd-config.go create mode 100644 core/command/cmd-diff.go create mode 100644 core/command/cmd-fetch.go create mode 100644 core/command/cmd-merge.go create mode 100644 core/command/cmd-pull.go create mode 100644 core/command/cmd-reset.go create mode 100644 core/command/cmd-status.go create mode 100644 core/command/cmd.go create mode 100644 core/command/file.go create mode 100644 core/errors/util-errors.go create mode 100644 core/git/authentication.go create mode 100644 core/git/branch.go create mode 100644 core/git/commit.go create mode 100644 core/git/random.go create mode 100644 core/git/random_test.go create mode 100644 core/git/remote.go create mode 100644 core/git/remotebranch.go create mode 100644 core/git/repository.go create mode 100644 core/git/sort.go create mode 100644 core/git/stash.go create mode 100644 core/job/job-queue.go create mode 100644 core/job/job.go create mode 100644 core/load/load.go create mode 100644 gui/authenticationview.go create mode 100644 gui/commitview.go create mode 100644 gui/controlsview.go create mode 100644 gui/diffview.go create mode 100644 gui/errorview.go create mode 100644 gui/gui.go create mode 100644 gui/keybindings.go create mode 100644 gui/mainview.go create mode 100644 gui/sideviews.go create mode 100644 gui/stagedview.go create mode 100644 gui/stashview.go create mode 100644 gui/statusview.go create mode 100644 gui/unstagedview.go create mode 100644 gui/util-common.go create mode 100644 gui/util-textstyle.go delete mode 100644 pkg/app/app.go delete mode 100644 pkg/app/config.go delete mode 100644 pkg/app/files.go delete mode 100644 pkg/app/quick.go delete mode 100644 pkg/git/authentication.go delete mode 100644 pkg/git/branch.go delete mode 100644 pkg/git/cmd-add.go delete mode 100644 pkg/git/cmd-commit.go delete mode 100644 pkg/git/cmd-config.go delete mode 100644 pkg/git/cmd-diff.go delete mode 100644 pkg/git/cmd-fetch.go delete mode 100644 pkg/git/cmd-merge.go delete mode 100644 pkg/git/cmd-pull.go delete mode 100644 pkg/git/cmd-reset.go delete mode 100644 pkg/git/cmd-rev-list.go delete mode 100644 pkg/git/cmd-stash.go delete mode 100644 pkg/git/cmd-status.go delete mode 100644 pkg/git/cmd.go delete mode 100644 pkg/git/commit.go delete mode 100644 pkg/git/file.go delete mode 100644 pkg/git/job-queue.go delete mode 100644 pkg/git/job.go delete mode 100644 pkg/git/remote.go delete mode 100644 pkg/git/remotebranch.go delete mode 100644 pkg/git/repository.go delete mode 100644 pkg/git/util-errors.go delete mode 100644 pkg/git/util-load.go delete mode 100644 pkg/git/util-random.go delete mode 100644 pkg/git/util-random_test.go delete mode 100644 pkg/git/util-sort.go delete mode 100644 pkg/gui/authenticationview.go delete mode 100644 pkg/gui/commitview.go delete mode 100644 pkg/gui/controlsview.go delete mode 100644 pkg/gui/diffview.go delete mode 100644 pkg/gui/errorview.go delete mode 100644 pkg/gui/gui.go delete mode 100644 pkg/gui/keybindings.go delete mode 100644 pkg/gui/mainview.go delete mode 100644 pkg/gui/sideviews.go delete mode 100644 pkg/gui/stagedview.go delete mode 100644 pkg/gui/stashview.go delete mode 100644 pkg/gui/statusview.go delete mode 100644 pkg/gui/unstagedview.go delete mode 100644 pkg/gui/util-common.go delete mode 100644 pkg/gui/util-textstyle.go diff --git a/app/app.go b/app/app.go new file mode 100644 index 0000000..b8eebc8 --- /dev/null +++ b/app/app.go @@ -0,0 +1,111 @@ +package app + +import ( + "os" + + "github.com/isacikgoz/gitbatch/gui" + log "github.com/sirupsen/logrus" +) + +// The App struct is responsible to hold app-wide related entities. Currently +// it has only the gui.Gui pointer for interface entity. +type App struct { + Gui *gui.Gui + Config *SetupConfig +} + +// SetupConfig is an assembler data to initiate a setup +type SetupConfig struct { + Directories []string + LogLevel string + Depth int + QuickMode bool + Mode string +} + +// Setup will handle pre-required operations. It is designed to be a wrapper for +// main method right now. +func Setup(setupConfig *SetupConfig) (*App, error) { + // initiate the app and give it initial values + app := &App{} + if len(setupConfig.Directories) <= 0 { + d, _ := os.Getwd() + setupConfig.Directories = []string{d} + } + + appConfig, err := overrideDefaults(setupConfig) + if err != nil { + return nil, err + } + + setLogLevel(appConfig.LogLevel) + directories := generateDirectories(appConfig.Directories, appConfig.Depth) + + if appConfig.QuickMode { + x := appConfig.Mode == "fetch" + y := appConfig.Mode == "pull" + if x == y { + log.Error("Unrecognized quick mode: " + appConfig.Mode) + os.Exit(1) + } + quick(directories, appConfig.Depth, appConfig.Mode) + os.Exit(0) + } + + // create a gui.Gui struct and set it as App's gui + app.Gui, err = gui.NewGui(appConfig.Mode, directories) + if err != nil { + // the error types and handling is not considered yet + return nil, err + } + // hopefull everything went smooth as butter + log.Trace("App configuration completed") + return app, nil +} + +// Close function will handle if any cleanup is required. e.g. closing streams +// or cleaning temproray files so on and so forth +func (app *App) Close() error { + return nil +} + +// set the level of logging it is fatal by default +func setLogLevel(logLevel string) { + switch logLevel { + case "trace": + log.SetLevel(log.TraceLevel) + case "debug": + log.SetLevel(log.DebugLevel) + case "info": + log.SetLevel(log.InfoLevel) + case "warn": + log.SetLevel(log.WarnLevel) + case "error": + log.SetLevel(log.ErrorLevel) + default: + log.SetLevel(log.FatalLevel) + } + log.WithFields(log.Fields{ + "level": logLevel, + }).Trace("logging level has been set") +} + +func overrideDefaults(setupConfig *SetupConfig) (appConfig *SetupConfig, err error) { + appConfig, err = LoadConfiguration() + if len(setupConfig.Directories) > 0 { + appConfig.Directories = setupConfig.Directories + } + if len(setupConfig.LogLevel) > 0 { + appConfig.LogLevel = setupConfig.LogLevel + } + if setupConfig.Depth > 0 { + appConfig.Depth = setupConfig.Depth + } + if setupConfig.QuickMode { + appConfig.QuickMode = setupConfig.QuickMode + } + if len(setupConfig.Mode) > 0 { + appConfig.Mode = setupConfig.Mode + } + return appConfig, err +} diff --git a/app/config.go b/app/config.go new file mode 100644 index 0000000..57c2e6e --- /dev/null +++ b/app/config.go @@ -0,0 +1,123 @@ +package app + +import ( + "os" + "path/filepath" + "runtime" + + log "github.com/sirupsen/logrus" + "github.com/spf13/viper" +) + +// 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{"."} + logLevelKey = "loglevel" + logLevelKeyDefault = "error" + qucikKey = "quick" + qucikKeyDefault = false + recursionKey = "recursion" + recursionKeyDefault = 1 +) + +// LoadConfiguration returns a Config struct is filled +func LoadConfiguration() (*SetupConfig, 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 + } + var directories []string + if len(viper.GetStringSlice(pathsKey)) <= 0 { + d, _ := os.Getwd() + directories = []string{d} + } else { + directories = viper.GetStringSlice(pathsKey) + } + config := &SetupConfig{ + Directories: directories, + LogLevel: viper.GetString(logLevelKey), + Depth: viper.GetInt(recursionKey), + QuickMode: viper.GetBool(qucikKey), + Mode: viper.GetString(modeKey), + } + return config, nil +} + +// set default configuration parameters +func setDefaults() error { + viper.SetDefault(logLevelKey, logLevelKeyDefault) + viper.SetDefault(qucikKey, qucikKeyDefault) + viper.SetDefault(recursionKey, recursionKeyDefault) + 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 { + err := viper.WriteConfig() + return err +} + +// 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 +} diff --git a/app/files.go b/app/files.go new file mode 100644 index 0000000..1ec05cd --- /dev/null +++ b/app/files.go @@ -0,0 +1,92 @@ +package app + +import ( + "io/ioutil" + "os" + "path/filepath" + + log "github.com/sirupsen/logrus" +) + +// generateDirectories returns poosible git repositories to pipe into git pkg's +// load function +func generateDirectories(dirs []string, depth int) []string { + gitDirs := make([]string, 0) + for i := 0; i <= depth; i++ { + nonrepos, repos := walkRecursive(dirs, gitDirs) + dirs = nonrepos + gitDirs = repos + } + return gitDirs +} + +// returns given values, first search directories and second stands for possible +// git repositories. Call this func from a "for i := 0; i= len(search) { + continue + } + // find possible repositories and remaining ones, b slice is possible ones + a, b, err := seperateDirectories(search[i]) + if err != nil { + log.WithFields(log.Fields{ + "directory": search[i], + }).WithError(err).Trace("Can't read directory") + continue + } + // since we started to search let's get rid of it and remove from search + // array + search[i] = search[len(search)-1] + search = search[:len(search)-1] + // lets append what we have found to continue recursion + search = append(search, a...) + appendant = append(appendant, b...) + } + return search, appendant +} + +// seperateDirectories is to find all the files in given path. This method +// does not check if the given file is a valid git repositories +func seperateDirectories(directory string) ([]string, []string, error) { + dirs := make([]string, 0) + gitDirs := make([]string, 0) + files, err := ioutil.ReadDir(directory) + // can we read the directory? + if err != nil { + log.WithFields(log.Fields{ + "directory": directory, + }).Trace("Can't read directory") + return nil, nil, nil + } + for _, f := range files { + repo := directory + string(os.PathSeparator) + f.Name() + file, err := os.Open(repo) + // if we cannot open it, simply continue to iteration and don't consider + if err != nil { + log.WithFields(log.Fields{ + "file": file, + "directory": repo, + }).WithError(err).Trace("Failed to open file in the directory") + file.Close() + continue + } + dir, err := filepath.Abs(file.Name()) + if err != nil { + file.Close() + continue + } + // with this approach, we ignore submodule or sub repositoreis in a git repository + ff, err := os.Open(dir + string(os.PathSeparator) + ".git") + if err != nil { + dirs = append(dirs, dir) + } else { + gitDirs = append(gitDirs, dir) + } + ff.Close() + file.Close() + + } + return dirs, gitDirs, nil +} diff --git a/app/quick.go b/app/quick.go new file mode 100644 index 0000000..005c033 --- /dev/null +++ b/app/quick.go @@ -0,0 +1,50 @@ +package app + +import ( + "fmt" + "sync" + "time" + + "github.com/isacikgoz/gitbatch/core/command" + "github.com/isacikgoz/gitbatch/core/git" +) + +func quick(directories []string, depth int, mode string) { + var wg sync.WaitGroup + start := time.Now() + for _, dir := range directories { + wg.Add(1) + go func(d string, mode string) { + defer wg.Done() + err := operate(d, mode) + if err != nil { + fmt.Printf("%s: %s\n", d, err.Error()) + } else { + fmt.Printf("%s: successful\n", d) + } + }(dir, mode) + } + wg.Wait() + elapsed := time.Since(start) + fmt.Printf("%d repositories finished in: %s\n", len(directories), elapsed) +} + +func operate(directory, mode string) error { + r, err := git.FastInitializeRepo(directory) + if err != nil { + return err + } + switch mode { + case "fetch": + return command.Fetch(r, command.FetchOptions{ + RemoteName: "origin", + Progress: true, + }) + case "pull": + return command.Pull(r, command.PullOptions{ + RemoteName: "origin", + Progress: true, + }) + } + return nil +} diff --git a/core/command/cmd-add.go b/core/command/cmd-add.go new file mode 100644 index 0000000..2addb23 --- /dev/null +++ b/core/command/cmd-add.go @@ -0,0 +1,89 @@ +package command + +import ( + "errors" + + "github.com/isacikgoz/gitbatch/core/git" + log "github.com/sirupsen/logrus" +) + +var ( + addCmdMode string + + addCommand = "add" + addCmdModeLegacy = "git" + addCmdModeNative = "go-git" +) + +// AddOptions defines the rules for "git add" command +type AddOptions struct { + // Update + Update bool + // Force + Force bool + // DryRun + DryRun bool +} + +// Add is a wrapper function for "git add" command +func Add(e *git.RepoEntity, file *File, option AddOptions) error { + addCmdMode = addCmdModeNative + if option.Update || option.Force || option.DryRun { + addCmdMode = addCmdModeLegacy + } + switch addCmdMode { + case addCmdModeLegacy: + err := addWithGit(e, file, option) + return err + case addCmdModeNative: + err := addWithGoGit(e, file) + return err + } + return errors.New("Unhandled add operation") +} + +// AddAll function is the wrapper of "git add ." command +func AddAll(e *git.RepoEntity, option AddOptions) error { + args := make([]string, 0) + args = append(args, addCommand) + if option.DryRun { + args = append(args, "--dry-run") + } + args = append(args, ".") + out, err := GenericGitCommandWithOutput(e.AbsPath, args) + if err != nil { + log.Warn("Error while add command") + return errors.New(out + "\n" + err.Error()) + } + return nil +} + +func addWithGit(e *git.RepoEntity, file *File, option AddOptions) error { + args := make([]string, 0) + args = append(args, addCommand) + args = append(args, file.Name) + if option.Update { + args = append(args, "--update") + } + if option.Force { + args = append(args, "--force") + } + if option.DryRun { + args = append(args, "--dry-run") + } + out, err := GenericGitCommandWithOutput(e.AbsPath, args) + if err != nil { + log.Warn("Error while add command") + return errors.New(out + "\n" + err.Error()) + } + return nil +} + +func addWithGoGit(e *git.RepoEntity, file *File) error { + w, err := e.Repository.Worktree() + if err != nil { + return err + } + _, err = w.Add(file.Name) + return nil +} diff --git a/core/command/cmd-commit.go b/core/command/cmd-commit.go new file mode 100644 index 0000000..d81942e --- /dev/null +++ b/core/command/cmd-commit.go @@ -0,0 +1,92 @@ +package command + +import ( + "errors" + "time" + + "github.com/isacikgoz/gitbatch/core/git" + log "github.com/sirupsen/logrus" + gogit "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing/object" +) + +var ( + commitCmdMode string + + commitCommand = "commit" + commitCmdModeLegacy = "git" + commitCmdModeNative = "go-git" +) + +// CommitOptions defines the rules for commit operation +type CommitOptions struct { + // CommitMsg + CommitMsg string + // User + User string + // Email + Email string +} + +// CommitCommand defines which commit command to use. +func CommitCommand(e *git.RepoEntity, options CommitOptions) (err error) { + // here we configure commit operation + // default mode is go-git (this may be configured) + commitCmdMode = commitCmdModeNative + + switch commitCmdMode { + case commitCmdModeLegacy: + return commitWithGit(e, options) + case commitCmdModeNative: + return commitWithGoGit(e, options) + } + return errors.New("Unhandled commit operation") +} + +// commitWithGit is simply a bare git commit -m command which is flexible +func commitWithGit(e *git.RepoEntity, options CommitOptions) (err error) { + args := make([]string, 0) + args = append(args, commitCommand) + args = append(args, "-m") + // parse options to command line arguments + if len(options.CommitMsg) > 0 { + args = append(args, options.CommitMsg) + } + if err := GenericGitCommand(e.AbsPath, args); err != nil { + log.Warn("Error at git command (commit)") + e.Refresh() + return err + } + // till this step everything should be ok + return e.Refresh() +} + +// commitWithGoGit is the primary commit method +func commitWithGoGit(e *git.RepoEntity, options CommitOptions) (err error) { + config, err := e.Repository.Config() + if err != nil { + return err + } + name := config.Raw.Section("user").Option("name") + email := config.Raw.Section("user").Option("email") + opt := &gogit.CommitOptions{ + Author: &object.Signature{ + Name: name, + Email: email, + When: time.Now(), + }, + } + + w, err := e.Repository.Worktree() + if err != nil { + return err + } + + _, err = w.Commit(options.CommitMsg, opt) + if err != nil { + e.Refresh() + return err + } + // till this step everything should be ok + return e.Refresh() +} diff --git a/core/command/cmd-config.go b/core/command/cmd-config.go new file mode 100644 index 0000000..c580ff6 --- /dev/null +++ b/core/command/cmd-config.go @@ -0,0 +1,106 @@ +package command + +import ( + "errors" + + "github.com/isacikgoz/gitbatch/core/git" + log "github.com/sirupsen/logrus" +) + +var ( + configCmdMode string + + configCommand = "config" + configCmdModeLegacy = "git" + configCmdModeNative = "go-git" +) + +// ConfigOptions defines the rules for commit operation +type ConfigOptions struct { + // Section + Section string + // Option + Option string + // Site should be Global or Local + Site ConfigSite +} + +// ConfigSite defines a string type for the site. +type ConfigSite string + +const ( + // ConfigSiteLocal defines a local config. + ConfigSiteLocal ConfigSite = "local" + + // ConfgiSiteGlobal defines a global config. + ConfgiSiteGlobal ConfigSite = "global" +) + +// Config adds or reads config of a repository +func Config(e *git.RepoEntity, options ConfigOptions) (value string, err error) { + // here we configure config operation + // default mode is go-git (this may be configured) + configCmdMode = configCmdModeLegacy + + switch configCmdMode { + case configCmdModeLegacy: + return configWithGit(e, options) + case configCmdModeNative: + return configWithGoGit(e, options) + } + return value, errors.New("Unhandled config operation") +} + +// configWithGit is simply a bare git commit -m command which is flexible +func configWithGit(e *git.RepoEntity, options ConfigOptions) (value string, err error) { + args := make([]string, 0) + args = append(args, configCommand) + if len(string(options.Site)) > 0 { + args = append(args, "--"+string(options.Site)) + } + args = append(args, "--get") + args = append(args, options.Section+"."+options.Option) + // parse options to command line arguments + out, err := GenericGitCommandWithOutput(e.AbsPath, args) + if err != nil { + return out, err + } + // till this step everything should be ok + return out, nil +} + +// commitWithGoGit is the primary commit method +func configWithGoGit(e *git.RepoEntity, options ConfigOptions) (value string, err error) { + // TODO: add global search + config, err := e.Repository.Config() + if err != nil { + return value, err + } + return config.Raw.Section(options.Section).Option(options.Option), nil +} + +// AddConfig adds an entry on the ConfigOptions field. +func AddConfig(e *git.RepoEntity, options ConfigOptions, value string) (err error) { + return addConfigWithGit(e, options, value) + +} + +// addConfigWithGit is simply a bare git config --add