Skip to content

Commit

Permalink
feat: add support for user.signingKey #32 (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
ayakovlenko committed Jun 13, 2024
1 parent e3d62b4 commit 82b3620
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 50 deletions.
2 changes: 1 addition & 1 deletion cmd/zit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/urfave/cli/v2"
)

const AppVersion = "v3.0.1"
const AppVersion = "v3.1.0-alpha.1"

func main() {
app := &cli.App{
Expand Down
10 changes: 8 additions & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ type HostConfig struct {

// User TODO
type User struct {
Name string `yaml:"name"`
Email string `yaml:"email"`
Name string `yaml:"name"`
Email string `yaml:"email"`
Signing *Signing `yaml:"sign"`
}

type Signing struct {
Key string `yaml:"key"`
Format string `yaml:"format"`
}

// Override TODO
Expand Down
9 changes: 0 additions & 9 deletions internal/gitutil/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,6 @@ func RemoteURL(gitClient git.GitClient, name string) (string, error) {
return out, nil
}

// SetConfig TODO
func SetConfig(gitClient git.GitClient, scope, key, value string) error {
_, err := gitClient.Exec("config", scope, key, value)
if err != nil {
return err
}
return nil
}

// GetConfig TODO
func GetConfig(gitClient git.GitClient, scope, key string) (string, error) {
out, err := gitClient.Exec("config", scope, key)
Expand Down
63 changes: 51 additions & 12 deletions internal/identity/identity.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package identity

import (
"fmt"
"zit/internal/config"
"zit/internal/gitutil"
"zit/pkg/git"
)

func findBestMatch(conf config.HostConfig, repo gitutil.RepoInfo) *config.User {
var user *config.User

if conf.Default != nil {
user = &config.User{
Name: conf.Default.Name,
Email: conf.Default.Email,
}
user = conf.Default
}

if conf.Overrides == nil {
Expand All @@ -22,20 +21,60 @@ func findBestMatch(conf config.HostConfig, repo gitutil.RepoInfo) *config.User {
for _, override := range conf.Overrides {
if override.Repo != "" {
if override.Owner == repo.Owner && override.Repo == repo.Name {
return &config.User{
Name: override.User.Name,
Email: override.User.Email,
}
return &override.User
}
}

if override.Owner == repo.Owner {
return &config.User{
Name: override.User.Name,
Email: override.User.Email,
}
return &override.User
}
}

return user
}

// setIdentity sets identity in a given repository based on a chosen identity.
func setIdentity(
gitClient git.GitClient,
cred config.User,
dryRun bool,
) error {
if !dryRun {
if err := git.SetLocalConfig(gitClient, "user.name", cred.Name); err != nil {
return err
}

if err := git.SetLocalConfig(gitClient, "user.email", cred.Email); err != nil {
return err
}
}

fmt.Printf("set user: %s <%s>\n", cred.Name, cred.Email)

sign := cred.Signing
if sign == nil {
return nil
}

if !dryRun {
if err := git.SetLocalConfig(gitClient, "commit.gpgsign", "true"); err != nil {
return err
}

if err := git.SetLocalConfig(gitClient, "tag.gpgsign", "true"); err != nil {
return err
}

if err := git.SetLocalConfig(gitClient, "user.signingKey", sign.Key); err != nil {
return err
}

if err := git.SetLocalConfig(gitClient, "gpg.format", sign.Format); err != nil {
return err
}
}

fmt.Printf("set signing key: %s key at %s\n", sign.Format, sign.Key)

return nil
}
104 changes: 104 additions & 0 deletions internal/identity/identity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"
"zit/internal/config"
"zit/internal/gitutil"
"zit/pkg/git"

"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -182,3 +183,106 @@ func TestFindBestMatch(t *testing.T) {
assert.Equal(t, want, have)
})
}

func TestSetIdentity(t *testing.T) {

t.Run("set credentials", func(t *testing.T) {
// given
dryRun := false

gitClient := git.NewMockGitClient()

cred := config.User{
Name: "John Doe",
Email: "john.doe@gmail.com",
}

gitClient.AddCommand(
[]string{"config", "--local", "user.name", "John Doe"}, "", nil,
)

gitClient.AddCommand(
[]string{"config", "--local", "user.email", "john.doe@gmail.com"}, "", nil,
)

// when

err := setIdentity(gitClient, cred, dryRun)

// then

assert.NoError(t, err)
})

t.Run("set credentials and signing key", func(t *testing.T) {
// given
dryRun := false

gitClient := git.NewMockGitClient()

cred := config.User{
Name: "John Doe",
Email: "john.doe@gmail.com",
Signing: &config.Signing{
Key: "~/.ssh/key",
Format: "ssh",
},
}

gitClient.AddCommand(
[]string{"config", "--local", "user.name", "John Doe"}, "", nil,
)

gitClient.AddCommand(
[]string{"config", "--local", "user.email", "john.doe@gmail.com"}, "", nil,
)

gitClient.AddCommand(
[]string{"config", "--local", "commit.gpgsign", "true"}, "", nil,
)

gitClient.AddCommand(
[]string{"config", "--local", "tag.gpgsign", "true"}, "", nil,
)

gitClient.AddCommand(
[]string{"config", "--local", "user.signingKey", "~/.ssh/key"}, "", nil,
)

gitClient.AddCommand(
[]string{"config", "--local", "gpg.format", "ssh"}, "", nil,
)

// when

err := setIdentity(gitClient, cred, dryRun)

// then

assert.NoError(t, err)
})

t.Run("set credentials and signing key -- dry run", func(t *testing.T) {
// given
dryRun := true

gitClient := git.NewMockGitClient()

cred := config.User{
Name: "John Doe",
Email: "john.doe@gmail.com",
Signing: &config.Signing{
Key: "~/.ssh/key",
Format: "ssh",
},
}

// when

err := setIdentity(gitClient, cred, dryRun)

// then

assert.NoError(t, err)
})
}
41 changes: 15 additions & 26 deletions internal/identity/set_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,25 @@ var SetCmd = &cli.Command{
},
},
Action: func(cCtx *cli.Context) error {
gitClient := git.NewGitClient()

fs := afero.NewOsFs()

if err := gitutil.EnsureGitDir(gitClient); err != nil {
return err
}
gitClient := git.NewGitClient()

userHomeDir, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("cannot user home dir: %v", err)
}

configPathFromEnv := os.Getenv(config.EnvVarName)

if err := gitutil.EnsureGitDir(gitClient); err != nil {
return err
}

confPath, err := config.LocateConfFile(
fs,
userHomeDir,
os.Getenv(config.EnvVarName),
configPathFromEnv,
)
if err != nil {
return err
Expand All @@ -60,9 +62,9 @@ var SetCmd = &cli.Command{
Add remote URL so that zit could use it for choosing the correct git identity as
defined in the configuration file:
git remote add origin <url>
git remote add origin <url>
`, err)
os.Exit(1)
os.Exit(1) // TODO: return "FriendlyError" instead of os.Exit
} else {
return err
}
Expand All @@ -83,23 +85,10 @@ defined in the configuration file:
return fmt.Errorf("cannot find a match for host %q", repo.Host)
}

dryRun := cCtx.Bool(dryRunFlag)

if !dryRun {
if err := gitutil.SetConfig(gitClient, "--local", "user.name", cred.Name); err != nil {
return err
}
if err := gitutil.SetConfig(gitClient, "--local", "user.email", cred.Email); err != nil {
return err
}
}

if dryRun {
fmt.Printf("[dry-run] ")
}

fmt.Printf("set user: %s <%s>\n", cred.Name, cred.Email)

return nil
return setIdentity(
gitClient,
*cred,
cCtx.Bool(dryRunFlag),
)
},
}
9 changes: 9 additions & 0 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package git

import "fmt"

func IsGitDir(client GitClient) (bool, error) {
out, err := client.Exec("rev-parse", "--is-inside-work-tree")
if err != nil {
return false, err
}
return out == "true", nil
}

func SetLocalConfig(gitClient GitClient, key, value string) error {
if _, err := gitClient.Exec("config", "--local", key, value); err != nil {
return fmt.Errorf("set local config %s=%s: %v", key, value, err)
}
return nil
}

0 comments on commit 82b3620

Please sign in to comment.