Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,53 @@ git clone https://aur.archlinux.org/git-switcher.git
makepkg -is
```

## Commands

Git Switcher offers several commands to help you manage your Git profiles:

### `list`

Lists all your saved git profiles. The currently active profile will be highlighted with an asterisk (*) and marked as `(current)`.

**Usage:**

```sh
git-switcher list
```

**Example Output:**

```
Available Git profiles:
work-profile
* personal-profile (current)
freelance-project
```

### `switch`

Allows you to interactively select and switch to a different Git profile from your saved list. This is also the default behavior when running `git-switcher` without any subcommand.

*(The GIF below demonstrates this functionality)*

### `create`

Guides you through the process of creating and saving a new Git profile.

*(The GIF below demonstrates this functionality)*

### `delete`

Allows you to select and delete one of your saved Git profiles.

*(The GIF below demonstrates this functionality)*

### `rename`

Allows you to rename an existing saved Git profile.

*(The GIF below demonstrates this functionality)*

## Switch Profile

![Switcher](https://user-images.githubusercontent.com/53150440/135753964-94d83bf5-597c-4983-b0cf-5da6f12e6c7c.gif)
Expand Down
3 changes: 1 addition & 2 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,5 @@ A new configuration file will be created in the ~/.config/gitconfigs directory.`
func init() {
// This function is called when the package is initialized.
// We are adding the createCmd to the rootCmd here.
// This will be done for all command files.
// rootCmd.AddCommand(createCmd) // Will be added in root.go's init
// rootCmd.AddCommand(createCmd) // Commands are added in root.go's init
}
3 changes: 1 addition & 2 deletions cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,5 @@ If the deleted profile is the currently active one, ~/.gitconfig will also be re
}

func init() {
// Will be added in root.go
// rootCmd.AddCommand(deleteCmd)
// rootCmd.AddCommand(deleteCmd) // Commands are added in root.go's init
}
3 changes: 1 addition & 2 deletions cmd/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,5 @@ This allows you to directly modify the active git configuration.`,
}

func init() {
// Will be added in root.go
// rootCmd.AddCommand(editCmd)
// rootCmd.AddCommand(editCmd) // Commands are added in root.go's init
}
97 changes: 97 additions & 0 deletions cmd/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package cmd

import (
"fmt"
"log"
"os"
"path/filepath"

"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/theykk/git-switcher/utils"
)

var (
getHomeDirFnc = homedir.Dir // Function variable for easy mocking in tests
configSubPath = filepath.Join(".config", "gitconfigs")
gitConfigName = ".gitconfig"
)

var listCmd = &cobra.Command{
Use: "list",
Short: "Lists all available git profiles",
Long: `Lists all available git profiles and indicates the currently active one.`,
Run: func(cmd *cobra.Command, args []string) {
home, err := getHomeDirFnc()
if err != nil {
log.Fatalf("Error getting home directory: %v", err) // Use log.Fatalf for consistency
}

configDir := filepath.Join(home, configSubPath)
if _, err := os.Stat(configDir); os.IsNotExist(err) {
// Use cmd.OutOrStdout() for output redirection in tests
fmt.Fprintln(cmd.OutOrStdout(), "Configuration directory "+filepath.Join("~", configSubPath)+" not found. Please create it first.")
return
}

files, err := os.ReadDir(configDir)
if err != nil {
log.Fatalf("Error reading profiles directory: %v", err) // Use log.Fatalf
}

gitconfigPath := filepath.Join(home, gitConfigName)
activeHash := ""
if _, err := os.Stat(gitconfigPath); err == nil { // Check if .gitconfig exists
activeHash = utils.Hash(gitconfigPath)
} else if !os.IsNotExist(err) {
// For errors other than "not exist", log them.
log.Printf("Warning: Error checking current .gitconfig: %v", err) // Keep log.Printf for warnings
}

fmt.Fprintln(cmd.OutOrStdout(), "Available Git profiles:") // This title is part of the output.
foundProfiles := false
for _, fileEntry := range files { // Renamed 'file' to 'fileEntry' for clarity
if !fileEntry.IsDir() {
profileName := fileEntry.Name()
profilePath := filepath.Join(configDir, profileName)

// Ensure the profile file itself exists before hashing
if _, err := os.Stat(profilePath); os.IsNotExist(err) {
log.Printf("Warning: profile file %s does not exist. Skipping.", profilePath) // Keep log.Printf for warnings
continue
}

profileHash := utils.Hash(profilePath)
foundProfiles = true

if activeHash != "" && profileHash == activeHash {
// color.Green will be used by Cobra if it detects a TTY.
// For tests, stdout is usually not a TTY, so color might be disabled.
// The test should ideally check for the presence of "*" and "(current)".
// Using fmt.Sprintf for consistent output formatting in tests.
// Actual color output can be manually verified.
fmt.Fprintf(cmd.OutOrStdout(), "* %s (current)\n", profileName)
} else {
fmt.Fprintf(cmd.OutOrStdout(), " %s\n", profileName)
}
}
}

if !foundProfiles {
// Standardize this message slightly for easier testing.
fmt.Fprintln(cmd.OutOrStdout(), " No profiles found in "+filepath.Join("~", configSubPath)+".")
}
},
}

// GetListCmdForTest exposes listCmd for testing purposes if needed by other packages,
// though for same-package tests, it's directly accessible.
// func GetListCmdForTest() *cobra.Command {
// return listCmd
// }

func init() {
// This ensures listCmd is added to rootCmd when the package is initialized.
// No changes needed here normally for testing listCmd itself via rootCmd.Execute().
rootCmd.AddCommand(listCmd)
}
Loading
Loading