Skip to content
Draft
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
1 change: 1 addition & 0 deletions cmd/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ func AddSubcommands(baseCmd *cobra.Command) {
baseCmd.AddCommand(
addRemoteCmd,
applyCmd,
newConfigCmd(),
newCloneCmd(),
editCmd,
fetchCmd,
Expand Down
39 changes: 39 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cmd

import (
"github.com/spf13/cobra"
"strings"
)

func newConfigCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "config key[=value]",
Short: "set or get a config value",
RunE: Config,
}

// Set flags
cmd.Flags().Bool("global", false, "set/get from global config")

return cmd
}

func Config(cmd *cobra.Command, args []string) error {
// Three modes:
// - config key - get key
// - config key value - set key to value
// - config key=value - set key to value

if len(args) > 1 {
return setConfig(args[0], args[1])
}
if strings.Contains(args[0], "=") {
split := strings.SplitN(args[0], "=", 0)
return setConfig(split[0], split[1])
}
return getConfig(args[0])
}

func getConfig(key string) error {}

func setConfig(key, value string) error {}
9 changes: 9 additions & 0 deletions cmd/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"github.com/barrettj12/jit/common"
"github.com/barrettj12/jit/common/config"
"github.com/barrettj12/jit/common/types"
"github.com/spf13/cobra"
"strings"
Expand All @@ -16,6 +17,14 @@ var editCmd = &cobra.Command{

// Edit opens the given branch in the default editor.
func Edit(cmd *cobra.Command, args []string) error {
editor, err := config.Editor()
if err != nil {
fmt.Printf("error getting default editor: %v\n", err)
} else {
fmt.Printf("default editor is %q\n", editor)
}
return nil

branch, err := common.ReqArg(args, 0, "Which branch would you like to edit?")
if err != nil {
return err
Expand Down
17 changes: 17 additions & 0 deletions common/config/bindings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package config

import (
"errors"
)

// Editor returns the default editor.
func Editor() (string, error) {
editor, err := readRepoConfig[string]("editor")
if err != nil {
editor, err = readGlobalConfig[string]("editor")
if err != nil {
return "", errors.New("default editor not set")
}
}
return editor, nil
}
65 changes: 65 additions & 0 deletions common/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package config

import (
"fmt"
"github.com/barrettj12/jit/common"
"gopkg.in/yaml.v3"
"os"
"path/filepath"
)

// Read a config value from the repo-specific config file at
//
// <repo-root>/.jit/config.yaml
//
// The provided type parameter defines the type that the value will be
// unmarshalled to.
func readRepoConfig[T any](key string) (t T, err error) {
repoBasePath, err := getRepoBasePath()
if err != nil {
return t, fmt.Errorf("getting repo base path: %w", err)
}
repoConfigFilePath := filepath.Join(repoBasePath.Path(), ".jit/config.yaml")
return readConfigFile[T](repoConfigFilePath, key)
}

// Read a config value from the global Jit config file at
//
// $HOME/.jit/config.yaml
//
// The provided type parameter defines the type that the value will be
// unmarshalled to.
func readGlobalConfig[T any](key string) (t T, err error) {
userHomeDir, err := getUserHomeDir()
if err != nil {
return t, fmt.Errorf("getting user home dir: %w", err)
}
globalConfigFilePath := filepath.Join(userHomeDir, ".jit/config.yaml")
return readConfigFile[T](globalConfigFilePath, key)
}

// Read a key from a Jit config file. The format of the config file is a
// uni-level mapping of keys to values. The provided type parameter defines the
// type that the value will be unmarshalled to.
func readConfigFile[T any](filePath, key string) (t T, err error) {
file, err := os.Open(filePath)
if err != nil {
return t, fmt.Errorf("reading repo config: %w", err)
}

var config map[string]T
// We will get an error for values that don't match type T, but we should
// ignore this, because we only care about the value corresponding to the
// given key.
err = yaml.NewDecoder(file).Decode(&config)
if _, ok := config[key]; !ok {
return t, fmt.Errorf("key %q not defined in config file at %s", key, filePath)
}
return config[key], nil
}

func addKeyToConfigFile(filePath, key string, value any) {}

// These methods can be replaced for testing.
var getRepoBasePath = common.RepoBasePath
var getUserHomeDir = os.UserHomeDir
32 changes: 32 additions & 0 deletions common/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package config

import (
"fmt"
"os"
"path/filepath"
"testing"
)

// TODO: maybe better to do this in each test to isolate the tests
func TestMain(m *testing.M) {
// Mock out config files
tmpDir, err := os.MkdirTemp("", "")
if err != nil {
panic(fmt.Sprintf("failed to create testing dir: %v", err))
}
defer func() {
err := os.RemoveAll(tmpDir)
if err != nil {
fmt.Printf("error removing temp dir %q: %v", tmpDir, err)
}
}()

getRepoConfigFilePath = func() (string, error) {
return filepath.Join(tmpDir, "repoconfig"), nil
}
getGlobalConfigFilePath = func() (string, error) {
return filepath.Join(tmpDir, "globalconfig"), nil
}

m.Run()
}
8 changes: 8 additions & 0 deletions common/config/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Package config contains utilities for interacting with Jit config.
// Jit can be configured in several ways:
// - environment variables
// - global Jit config in $HOME/.jit/config
// - repo-specific Jit config in $REPO/.jit/config
//
// Jit config is distinct from Git config.
package config
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ module github.com/barrettj12/jit

go 1.22

require github.com/spf13/cobra v1.8.1
require (
github.com/spf13/cobra v1.8.1
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=