Skip to content

Commit

Permalink
feat: add remove command and update README.md
Browse files Browse the repository at this point in the history
- Added a new `remove` command to remove repositories from `gee.toml` configuration.
- Ensure `remove` command can detect the repository name from the current directory if `.git` is present, or use `--repo` flag to specify the repository name.
- Updated command interface to take `cli.Context` parameter.
- Updated all commands to pass `cli.Context` to their respective Run functions.
- Enhanced README.md:
  - Detailed usage instructions for all commands including the new `remove` command.
  - Clarified the requirement for `gee add` to be run inside a `.git` directory.
  - Highlighted search behavior for `gee.toml` in current and parent directories.
  • Loading branch information
stcrestrada committed May 25, 2024
1 parent cbd5442 commit c9a11cc
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ brews:
homepage: "https://github.com/stcrestrada/gee"
# Template of your app's description.
# Default is empty.
description: "Manage all your git repos simultaneously."
description: "Efficiently Manage Multiple Git Repositories."
# SPDX identifier of your app's license.
# Default is empty.
license: "MIT"
Expand Down
73 changes: 52 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
# Gee: A CLI tool that efficiently manages multiple git repositories simultaneously
# Gee: Efficiently Manage Multiple Git Repositories

It allows you to clone, pull, and check the status of repositories listed in a TOML file, leveraging concurrency for faster operations. Gee utilizes the [gogo](http://godoc.org/github.com/stcrestrada/gogo) library for enhanced functionality.
Gee is a powerful command-line tool designed to help you manage multiple git repositories seamlessly. It allows you to clone, pull, and check the status of repositories listed in a `gee.toml` configuration file, leveraging concurrency for faster operations.

### install
## Features

- **Clone**: Clone multiple repositories listed in the `gee.toml` file.
- **Pull**: Pull changes from the main branch for all repositories.
- **Status**: Check the git status of all repositories.
- **Remove**: Remove repositories from the `gee.toml` configuration.
- **Add**: Add repository to `gee.toml` configuration.

## Installation

Install Gee using Homebrew:
```
brew tap stcrestrada/gee https://github.com/stcrestrada/gee
Expand All @@ -21,46 +30,68 @@ brew upgrade gee
```brew uninstall gee```

### initialize
#### Creates a gee.toml file with all the git directories added to gee.toml
###### Run this command in the directory you want to manage with gee in
#### Create an initial gee.toml configuration file:

```
gee init
```

## Add repos
#### cd into the git directory and run this command, will add repos to gee.toml
### Add Repository
#### Add a repository to the `gee.toml` file. Note that the `gee add` command must be run from inside a `.git` directory:
```
cd path/to/repo
gee add
```

## Git status
### Check Status
#### Check the status of all git directories added to gee.toml
```
gee status
```

## Git pull
##### Pretty cool command. gee pull will pull all git changes as long as you're in the main branch. If you have uncommitted changes in the main branch, gee stashes those changes, pulls down and reapplies the uncommitted changes.
### Pull Changes
##### Pull changes from the main branch for all repositories:
```
gee pull
```

## Git Clone
###### Requires user to manually add remote to gee.toml
### Remove Repository
##### Automatically detect from the current directory:
```
gee remove
```
##### Specify repository name using flag:
```shell
gee remove -r repo_name
```
##### OR
```shell
gee remove --repo repo_name
```


### Clone Repositories
##### Clone all repositories listed in your gee.toml file:
```shell
gee clone
```

#### Example. Please manually add `remote` to gee.toml for gee clone to work.
## Configuration
#### Manually Configure gee.toml
```
[[repos]]
name = "gee"
path = "/Users/stcrestrada/Projects"
remote = "git@github.com:stcrestrada/gee.git"
name = "repo_name"
path = "/path/to/repo"
remote = "https://github.com/user/repo.git"
````
#### Things to consider:
- When manually configuring `gee.toml` make sure that name is the same as the repository name.
- When manually configuring `gee.toml` make sure that path does not include the repository name.
- When manually configuring `gee.toml` make sure that remote is correct to leverage's `gee's` full potential.
- A `gee.toml` can exist in multiple directories. For example if you run `gee create` inside of `/one/project/dev/`, `gee` will only look for `gee.toml` inside `/one/project/dev/`. If `gee command` is run inside `/one/project/` it will look for `gee.toml` inside `/one/project/`, if one does not exist, `gee` will move up to the next parent directory, `/one` and so on until it finds a `gee.toml` file. If no `gee.toml` is found, `gee` will return an error.
### Finding gee.toml
#### Gee searches for gee.toml in the current and parent directories. If no configuration file is found, an error will be returned.
## FAQ and Troubleshooting
### What if Gee cannot find the gee.toml?
#### Ensure that the gee.toml file exists in the current or parent directories. Use gee init to create a new configuration if needed.
## License
#### Gee is licensed under the MIT License. See the LICENSE file for more information.
6 changes: 3 additions & 3 deletions cmd/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ func AddCmd() *cli.Command {
return &cli.Command{
Name: "add",
Usage: "add repo to gee.toml",
Action: func(context *cli.Context) error {
return addCmd.Run()
Action: func(c *cli.Context) error {
return addCmd.Run(c)
},
}
}

func (cmd *AddCommand) Run() error {
func (cmd *AddCommand) Run(c *cli.Context) error {
cwd, err := cmd.GetWorkingDirectory()
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions cmd/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ func CloneCmd() *cli.Command {
Name: "clone",
Usage: "Git clone of all repos in gee.toml",
Action: func(c *cli.Context) error {
return cloneCmd.Run()
return cloneCmd.Run(c)
},
}
}

func (cmd *CloneCommand) Run() error {
func (cmd *CloneCommand) Run(c *cli.Context) error {
ctx, err := cmd.LoadConfiguration()
if err != nil {
return util.NewWarning(err.Error())
Expand Down
6 changes: 3 additions & 3 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ func InitCmd() *cli.Command {
return &cli.Command{
Name: "init",
Usage: "create gee.toml",
Action: func(context *cli.Context) error {
return initCmd.Run()
Action: func(c *cli.Context) error {
return initCmd.Run(c)
},
}
}

func (cmd *InitCommand) Run() error {
func (cmd *InitCommand) Run(c *cli.Context) error {
cwd, err := os.Getwd()
if err != nil {
util.Warning("Warning: %s \n", err)
Expand Down
4 changes: 2 additions & 2 deletions cmd/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ func PullCmd() *cli.Command {
Name: "pull",
Usage: "Git pull and update all repos",
Action: func(c *cli.Context) error {
return pullCmd.Run()
return pullCmd.Run(c)
},
}
}

func (cmd *PullCommand) Run() error {
func (cmd *PullCommand) Run(c *cli.Context) error {
ctx, err := cmd.LoadConfiguration()
if err != nil {
util.Warning("Warning: %s \n", err)
Expand Down
119 changes: 119 additions & 0 deletions cmd/remove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package cmd

import (
"fmt"
"gee/pkg/command"
"gee/pkg/types"
"gee/pkg/util"
"github.com/urfave/cli/v2"
"os"
"path/filepath"
)

type RemoveCommand struct {
Git command.GitRepoOperation
RepoUtils *util.RepoUtils
}

func NewRemoveCommand() *RemoveCommand {
repoOp := command.GitRepoOperation{}
return &RemoveCommand{
Git: repoOp,
RepoUtils: util.NewRepoUtils(repoOp),
}
}

func RemoveCmd() *cli.Command {
removeCmd := NewRemoveCommand()
return &cli.Command{
Name: "remove",
Usage: "remove repo in gee.toml",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "repo",
Aliases: []string{"r"},
Usage: "specify the repository name to remove",
},
},
Action: func(c *cli.Context) error {
return removeCmd.Run(c)
},
}
}

func (cmd *RemoveCommand) Run(c *cli.Context) error {
var err error
repoName := c.String("repo")
if repoName == "" {
repoName, err = cmd.getRepoNameFromGitDir()
if err != nil {
return err
}
if repoName == "" {
return util.NewWarning("please specify the repository name to remove")
}
}

// Load the configuration
geeCtx, err := cmd.LoadConfiguration()
if err != nil {
return err
}

repoPath := ""
for _, repo := range geeCtx.Repos {
if repo.Name == repoName {
repoPath = repo.Path
break
}
}
if repoPath == "" {
return util.NewWarning(fmt.Sprintf("repository %s not found in the configuration", repoName))
}

// update configuration
newRepos := []types.Repo{}
for _, repo := range geeCtx.Repos {
if repo.Name != repoName {
newRepos = append(newRepos, repo)
}
}

geeCtx.Repos = newRepos
configHelper := util.NewConfigHelper()

err = configHelper.SaveConfig(geeCtx.ConfigFilePath, geeCtx)
if err != nil {
return util.NewWarning(err.Error())
}
return util.NewInfo(fmt.Sprintf("repository %s successfully remove", repoName))
}

func (cmd *RemoveCommand) GetWorkingDirectory() (string, error) {
return os.Getwd()
}

func (cmd *RemoveCommand) LoadConfiguration() (*types.GeeContext, error) {
cwd, err := cmd.GetWorkingDirectory()
if err != nil {
return nil, err
}
return util.NewConfigHelper().LoadConfig(cwd)
}

// Get repository name from .git directory
func (cmd *RemoveCommand) getRepoNameFromGitDir() (string, error) {
cwd, err := cmd.GetWorkingDirectory()
if err != nil {
return "", util.NewWarning(err.Error())
}
gitDir := filepath.Join(cwd, ".git")
exists, err := cmd.RepoUtils.FileExists(gitDir)
if err != nil {
return "", fmt.Errorf("error checking .git directory: %v", err)
}
if !exists {
return "", nil
}
return filepath.Base(cwd), nil
}
4 changes: 2 additions & 2 deletions cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ func StatusCmd() *cli.Command {
Name: "status",
Usage: "Git status of all repos",
Action: func(c *cli.Context) error {
return statusCmd.Run()
return statusCmd.Run(c)
},
}
}

func (cmd *StatusCommand) Run() error {
func (cmd *StatusCommand) Run(c *cli.Context) error {
ctx, err := cmd.LoadConfiguration()
if err != nil {
util.Warning("Warning: %s", err)
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func main() {
cmd.PullCmd(),
cmd.StatusCmd(),
cmd.CloneCmd(),
cmd.RemoveCmd(),
}

// Run the CLI app
Expand Down
7 changes: 5 additions & 2 deletions pkg/command/command.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package command

import "gee/pkg/types"
import (
"gee/pkg/types"
"github.com/urfave/cli/v2"
)

type Command interface {
Run() error
Run(c *cli.Context) error
GetWorkingDirectory(string, error)
LoadConfiguration(types.GeeContext, error)
}
11 changes: 11 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/pelletier/go-toml"
"os"
"path"
"path/filepath"
)

type ConfigHelper struct {
Expand All @@ -25,6 +26,16 @@ func (h *ConfigHelper) SetConfig(config toml.Tree) (*types.Config, error) {
return &conf, err
}

// SaveConfig writes the configuration to the gee.toml file
func (h *ConfigHelper) SaveConfig(dir string, config *types.GeeContext) error {
configFilePath := filepath.Join(dir, "gee.toml")
configTree, err := toml.Marshal(*config)
if err != nil {
return err
}
return os.WriteFile(configFilePath, configTree, 0644)
}

func (h *ConfigHelper) FindConfig(cwd string, fileName string) (string, error) {
if cwd == "" {
return "", errors.New("gee.toml not found")
Expand Down

0 comments on commit c9a11cc

Please sign in to comment.