mirror of
https://github.com/Slug-Boi/cocommit.git
synced 2026-05-13 12:45:47 +00:00
Merge pull request #84 from Slug-Boi/feat_default-editor
Feat: default editor + config
This commit is contained in:
@@ -24,7 +24,7 @@ func main() {
|
|||||||
// mount the source code directory on the host
|
// mount the source code directory on the host
|
||||||
// at /src in the container
|
// at /src in the container
|
||||||
source := client.Container().
|
source := client.Container().
|
||||||
From("golang:1.23").
|
From("golang:1.24").
|
||||||
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
||||||
Exclude: []string{},
|
Exclude: []string{},
|
||||||
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
|
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module ci
|
module ci
|
||||||
|
|
||||||
go 1.23.2
|
go 1.24.6
|
||||||
|
|
||||||
require dagger.io/dagger v0.13.6
|
require dagger.io/dagger v0.13.6
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ func main() {
|
|||||||
// mount the source code directory on the host
|
// mount the source code directory on the host
|
||||||
// at /src in the container
|
// at /src in the container
|
||||||
source := client.Container().
|
source := client.Container().
|
||||||
From("golang:1.23").
|
From("golang:1.24").
|
||||||
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{
|
||||||
Exclude: []string{"build/"},
|
Exclude: []string{"build/"},
|
||||||
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
|
})).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache)
|
||||||
|
|||||||
+3
-7
@@ -24,7 +24,7 @@ var amendCmd = &cobra.Command{
|
|||||||
pflag, _ := cmd.Flags().GetBool("print-output")
|
pflag, _ := cmd.Flags().GetBool("print-output")
|
||||||
tflag, _ := cmd.Flags().GetBool("test_print")
|
tflag, _ := cmd.Flags().GetBool("test_print")
|
||||||
git_flags, _ := cmd.Flags().GetString("git-flags")
|
git_flags, _ := cmd.Flags().GetString("git-flags")
|
||||||
edit, _ := cmd.Flags().GetBool("edit")
|
no_edit, _ := cmd.Flags().GetBool("no-edit")
|
||||||
hash, _ := cmd.Flags().GetString("hash")
|
hash, _ := cmd.Flags().GetString("hash")
|
||||||
|
|
||||||
|
|
||||||
@@ -34,10 +34,6 @@ var amendCmd = &cobra.Command{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if edit {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var authors string
|
var authors string
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
// open the TUI to select co-authors
|
// open the TUI to select co-authors
|
||||||
@@ -56,7 +52,7 @@ var amendCmd = &cobra.Command{
|
|||||||
git_flags_split = strings.Split(git_flags, " ")
|
git_flags_split = strings.Split(git_flags, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
err, _ := utils.GitCommitAppender(authors, hash, git_flags_split, tflag, pflag)
|
err, _ := utils.GitCommitAppender(authors, hash, git_flags_split, tflag, pflag, no_edit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Error amending commit:", err.Error())
|
println("Error amending commit:", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -70,6 +66,6 @@ func init() {
|
|||||||
amendCmd.Flags().StringP("git-flags", "g", "", "Git flags to add to the commit command")
|
amendCmd.Flags().StringP("git-flags", "g", "", "Git flags to add to the commit command")
|
||||||
amendCmd.Flags().BoolP("print-output", "p", false, "Print the commit message to stdout")
|
amendCmd.Flags().BoolP("print-output", "p", false, "Print the commit message to stdout")
|
||||||
amendCmd.Flags().BoolP("test_print", "t", false, "Print the commit message to stdout without amending")
|
amendCmd.Flags().BoolP("test_print", "t", false, "Print the commit message to stdout without amending")
|
||||||
amendCmd.Flags().BoolP("edit", "e", false, "Edit the commit message in the editor")
|
amendCmd.Flags().BoolP("no-edit", "n", false, "Do not edit the commit message in the editor")
|
||||||
amendCmd.Flags().StringP("hash", "s", "", "Hash of the commit to amend")
|
amendCmd.Flags().StringP("hash", "s", "", "Hash of the commit to amend")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// configCmd represents the config command
|
||||||
|
var configCmd = &cobra.Command{
|
||||||
|
Use: "config",
|
||||||
|
Short: "This command will create or edit the configuration file for cocommit",
|
||||||
|
Long: `This command will create or edit the configuration file for cocommit.
|
||||||
|
You can set various settings like the author file, starting scope, and which editor to use.
|
||||||
|
A flag can be used to print the current configuration, as well as its location.
|
||||||
|
To see what options are available to use in the config file, please refer to the wiki page on the GitHub repository:
|
||||||
|
COMING SOON`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
printConfig, _ := cmd.Flags().GetBool("print")
|
||||||
|
editConfig, _ := cmd.Flags().GetBool("edit")
|
||||||
|
configLocation, _ := cmd.Flags().GetBool("location")
|
||||||
|
removeConfig, _ := cmd.Flags().GetBool("remove")
|
||||||
|
|
||||||
|
if printConfig {
|
||||||
|
if !utils.CheckConfig() {
|
||||||
|
fmt.Println("No configuration file found. Default is being used.")
|
||||||
|
fmt.Println("Default configuration:")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fmt.Println("Current configuration:")
|
||||||
|
}
|
||||||
|
fmt.Println(utils.ConfigVar.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the config file exists
|
||||||
|
if !utils.CheckConfig() {
|
||||||
|
err := utils.HandleMissingConfig()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Error handling missing configuration file: %v", err))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if printConfig {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if editConfig {
|
||||||
|
utils.LaunchEditor("default",utils.GetConfigFilePath())
|
||||||
|
return
|
||||||
|
} else if configLocation {
|
||||||
|
fmt.Println("Configuration file location:", utils.GetConfigFilePath())
|
||||||
|
return
|
||||||
|
} else if removeConfig {
|
||||||
|
utils.RemoveConfig()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("No action specified. Use flags to specify an action, use -h for help.")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(configCmd)
|
||||||
|
configCmd.Flags().BoolP("print", "p", false, "Print the current configuration")
|
||||||
|
configCmd.Flags().BoolP("edit", "e", false, "Edit the configuration file in your default editor")
|
||||||
|
configCmd.Flags().BoolP("location", "l", false, "Print the location of the configuration file")
|
||||||
|
configCmd.Flags().BoolP("remove", "r", false, "Remove the configuration file")
|
||||||
|
}
|
||||||
+11
-2
@@ -9,8 +9,8 @@ import (
|
|||||||
|
|
||||||
"github.com/Slug-Boi/cocommit/src/cmd/tui"
|
"github.com/Slug-Boi/cocommit/src/cmd/tui"
|
||||||
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
"github.com/inancgumus/screen"
|
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/inancgumus/screen"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -155,7 +155,16 @@ func Execute() {
|
|||||||
|
|
||||||
func call_tui(args []string) []string {
|
func call_tui(args []string) []string {
|
||||||
// append commit message to args
|
// append commit message to args
|
||||||
args = append(args, tui.Entry_CM())
|
//args = append(args, tui.Entry_CM())
|
||||||
|
message, err := utils.LaunchEditor(utils.ConfigVar.Settings.Editor,"")
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Error launching editor: %v", err))
|
||||||
|
}
|
||||||
|
if message == "" {
|
||||||
|
message = tui.Entry_CM()
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, message)
|
||||||
|
|
||||||
// clear the screen
|
// clear the screen
|
||||||
screen.Clear()
|
screen.Clear()
|
||||||
|
|||||||
@@ -14,37 +14,33 @@ import (
|
|||||||
// An example of the author file can be found in the examples folder of the repo
|
// An example of the author file can be found in the examples folder of the repo
|
||||||
func Find_authorfile() string {
|
func Find_authorfile() string {
|
||||||
var file string
|
var file string
|
||||||
|
if ConfigVar == nil {
|
||||||
if os.Getenv("author_file") == "" {
|
cfg, _ := LoadConfig()
|
||||||
if ConfigVar == nil {
|
if cfg == nil {
|
||||||
cfg, _ := LoadConfig()
|
// mimic the default config structure
|
||||||
if cfg == nil {
|
cfg = &Config{
|
||||||
// mimic the default config structure
|
Settings: struct {
|
||||||
cfg = &Config{
|
AuthorFile string `mapstructure:"author_file"`
|
||||||
Settings: struct {
|
StartingScope string `mapstructure:"starting_scope"`
|
||||||
AuthorFile string `mapstructure:"author_file"`
|
Editor string `mapstructure:"editor"`
|
||||||
StartingScope string `mapstructure:"starting_scope"`
|
}{
|
||||||
Editor string `mapstructure:"editor"`
|
AuthorFile: "",
|
||||||
}{
|
StartingScope: "git",
|
||||||
AuthorFile: "",
|
Editor: "built-in",
|
||||||
StartingScope: "git",
|
},
|
||||||
Editor: "built-in",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
cfg.SetGlobalConfig()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cfg.SetGlobalConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("author_file") == "" {
|
||||||
if ConfigVar.Settings.AuthorFile != "" {
|
if ConfigVar.Settings.AuthorFile != "" {
|
||||||
file = ConfigVar.Settings.AuthorFile
|
file = ConfigVar.Settings.AuthorFile
|
||||||
} else if os.Getenv("author_file") != "" {
|
|
||||||
file = os.Getenv("author_file")
|
|
||||||
} else {
|
} else {
|
||||||
userconf, err :=os.UserConfigDir()
|
userconf, err :=os.UserConfigDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Error getting user config dir: %v", err))
|
panic(fmt.Sprintf("Error getting user config dir: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(userconf+"/cocommit/authors.json"); os.IsNotExist(err) {
|
if _, err := os.Stat(userconf+"/cocommit/authors.json"); os.IsNotExist(err) {
|
||||||
panic(fmt.Sprintf("No author file set, please set the author_file environment variable or create a config file using the command: cocommit config -c"))
|
panic(fmt.Sprintf("No author file set, please set the author_file environment variable or create a config file using the command: cocommit config -c"))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+30
-2
@@ -2,6 +2,7 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -129,7 +130,7 @@ func group_selection(group []User, excludeMode []string) []string {
|
|||||||
return excludeMode
|
return excludeMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func GitCommitAppender(authors string, hash string, flags []string, t,p bool) (error, string) {
|
func GitCommitAppender(authors string, hash string, flags []string, t,p,n bool) (error, string) {
|
||||||
// Get old commit message
|
// Get old commit message
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
|
|
||||||
@@ -153,9 +154,36 @@ func GitCommitAppender(authors string, hash string, flags []string, t,p bool) (e
|
|||||||
// commit shell command
|
// commit shell command
|
||||||
// specify git command1
|
// specify git command1
|
||||||
input := []string{"commit"}
|
input := []string{"commit"}
|
||||||
|
|
||||||
|
// Edit the old message
|
||||||
input = append(input, flags...)
|
input = append(input, flags...)
|
||||||
old_commit = strings.TrimSpace(old_commit)
|
old_commit = strings.TrimSpace(old_commit)
|
||||||
input = append(input, "--amend", "-m", old_commit+"\n"+authors)
|
|
||||||
|
// Edit old commit message
|
||||||
|
var edited_commit string
|
||||||
|
if !n {
|
||||||
|
// Create tempfile for the commit message
|
||||||
|
file, err := os.CreateTemp("", "cocommit_editor_*.txt")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not create tempfile: %s", err.Error()), ""
|
||||||
|
}
|
||||||
|
defer os.Remove(file.Name())
|
||||||
|
|
||||||
|
// Write the old commit message to the file
|
||||||
|
_, err = file.WriteString(old_commit + "\n" + authors)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not write to tempfile: %s", err.Error()), ""
|
||||||
|
}
|
||||||
|
file.Close()
|
||||||
|
edited_commit, err = LaunchEditor(ConfigVar.Settings.Editor, file.Name())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not launch editor: %s", err.Error()), ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
edited_commit = old_commit + "\n" + authors
|
||||||
|
}
|
||||||
|
|
||||||
|
input = append(input, "--amend", "-m", edited_commit)
|
||||||
|
|
||||||
if p {
|
if p {
|
||||||
println(old_commit + "\n" + authors)
|
println(old_commit + "\n" + authors)
|
||||||
|
|||||||
+79
-33
@@ -33,6 +33,13 @@ type Config struct {
|
|||||||
} `mapstructure:"settings"`
|
} `mapstructure:"settings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) String() string {
|
||||||
|
return fmt.Sprintf("Author File: %s\nStarting Scope: %s\nEditor: %s",
|
||||||
|
c.Settings.AuthorFile,
|
||||||
|
c.Settings.StartingScope,
|
||||||
|
c.Settings.Editor)
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
configDir, err := os.UserConfigDir()
|
configDir, err := os.UserConfigDir()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -40,10 +47,11 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var v *viper.Viper
|
||||||
|
|
||||||
func LoadConfig() (*Config, error) {
|
func LoadConfig() (*Config, error) {
|
||||||
// TODO: create if and give param as default config location
|
// TODO: create if and give param as default config location
|
||||||
|
v = viper.New()
|
||||||
v := viper.New()
|
|
||||||
v.SetConfigName(configName)
|
v.SetConfigName(configName)
|
||||||
v.SetConfigType(configType)
|
v.SetConfigType(configType)
|
||||||
|
|
||||||
@@ -92,7 +100,7 @@ func (c *Config) SetGlobalConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMissingConfig(v *viper.Viper) error {
|
func HandleMissingConfig() error {
|
||||||
fmt.Println("Config file not found. Would you like to create one? (y/n)")
|
fmt.Println("Config file not found. Would you like to create one? (y/n)")
|
||||||
var response string
|
var response string
|
||||||
if _, err := fmt.Scanln(&response); err != nil {
|
if _, err := fmt.Scanln(&response); err != nil {
|
||||||
@@ -104,10 +112,48 @@ func handleMissingConfig(v *viper.Viper) error {
|
|||||||
return fmt.Errorf("config file not found")
|
return fmt.Errorf("config file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return createConfig(v)
|
if v == nil {
|
||||||
|
v = viper.New()
|
||||||
|
|
||||||
|
v.SetConfigName(configName)
|
||||||
|
v.SetConfigType(configType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
func createConfig(v *viper.Viper) error {
|
func CheckConfig() bool {
|
||||||
|
if v == nil {
|
||||||
|
return false
|
||||||
|
} else if v.ConfigFileUsed() == "" {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfigFilePath() string {
|
||||||
|
if v == nil || v.ConfigFileUsed() == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return v.ConfigFileUsed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveConfig() error {
|
||||||
|
if v == nil || v.ConfigFileUsed() == "" {
|
||||||
|
return fmt.Errorf("no config file to remove")
|
||||||
|
}
|
||||||
|
|
||||||
|
configPath := v.ConfigFileUsed()
|
||||||
|
if err := os.Remove(configPath); err != nil {
|
||||||
|
return fmt.Errorf("failed to remove config file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Config file removed: %s\n", configPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateConfig() error {
|
||||||
fmt.Println("Where would you like to create the config file?")
|
fmt.Println("Where would you like to create the config file?")
|
||||||
for i, path := range defaultConfigLocations {
|
for i, path := range defaultConfigLocations {
|
||||||
fmt.Printf("%d. %s\n", i, path)
|
fmt.Printf("%d. %s\n", i, path)
|
||||||
@@ -145,38 +191,38 @@ func createConfig(v *viper.Viper) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Save() error {
|
func (c *Config) Save() error {
|
||||||
v := viper.New()
|
v := viper.New()
|
||||||
|
|
||||||
// Set all configuration values from the struct
|
// Set all configuration values from the struct
|
||||||
v.Set("settings.author_file", c.Settings.AuthorFile)
|
v.Set("settings.author_file", c.Settings.AuthorFile)
|
||||||
v.Set("settings.starting_scope", c.Settings.StartingScope)
|
v.Set("settings.starting_scope", c.Settings.StartingScope)
|
||||||
v.Set("settings.editor", c.Settings.Editor)
|
v.Set("settings.editor", c.Settings.Editor)
|
||||||
|
|
||||||
v.SetConfigName(configName)
|
v.SetConfigName(configName)
|
||||||
v.SetConfigType(configType)
|
v.SetConfigType(configType)
|
||||||
|
|
||||||
// Try to determine the original config file location
|
// Try to determine the original config file location
|
||||||
if viper.ConfigFileUsed() != "" {
|
if viper.ConfigFileUsed() != "" {
|
||||||
v.SetConfigFile(viper.ConfigFileUsed())
|
v.SetConfigFile(viper.ConfigFileUsed())
|
||||||
} else {
|
} else {
|
||||||
// Fall back to first default location if no existing config
|
// Fall back to first default location if no existing config
|
||||||
if len(defaultConfigLocations) > 0 && defaultConfigLocations[0] != "" {
|
if len(defaultConfigLocations) > 0 && defaultConfigLocations[0] != "" {
|
||||||
v.SetConfigFile(filepath.Join(defaultConfigLocations[0], fmt.Sprintf("%s.%s", configName, configType)))
|
v.SetConfigFile(filepath.Join(defaultConfigLocations[0], fmt.Sprintf("%s.%s", configName, configType)))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("no config file location available")
|
return fmt.Errorf("no config file location available")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the directory exists
|
// Ensure the directory exists
|
||||||
configDir := filepath.Dir(v.ConfigFileUsed())
|
configDir := filepath.Dir(v.ConfigFileUsed())
|
||||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||||
return fmt.Errorf("failed to create config directory: %w", err)
|
return fmt.Errorf("failed to create config directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the config file
|
// Write the config file
|
||||||
if err := v.WriteConfig(); err != nil {
|
if err := v.WriteConfig(); err != nil {
|
||||||
return fmt.Errorf("failed to save config: %w", err)
|
return fmt.Errorf("failed to save config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HandleEditor() (string, error) {
|
||||||
|
editor := ConfigVar.Settings.Editor
|
||||||
|
if editor == "built-in" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if editor == "" || editor == "default" {
|
||||||
|
editor = os.Getenv("EDITOR")
|
||||||
|
if editor == "" {
|
||||||
|
editor = "vim" // default to vim if no editor is set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := exec.LookPath(editor); err != nil {
|
||||||
|
return "", fmt.Errorf("editor %s not found in PATH", editor)
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := LaunchEditor(editor, "")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to launch editor %s: %v", editor, err)
|
||||||
|
}
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LaunchEditor(editor string, filepath string, ) (string, error) {
|
||||||
|
// Create a temp file or use an existing file
|
||||||
|
var tempFile *os.File
|
||||||
|
var err error
|
||||||
|
|
||||||
|
switch strings.ToLower(editor) {
|
||||||
|
case "default", "":
|
||||||
|
editor = os.Getenv("EDITOR")
|
||||||
|
if editor == "" {
|
||||||
|
editor = "vim" // default to vim if no editor is set
|
||||||
|
}
|
||||||
|
case "built-in":
|
||||||
|
// fallback to built-in editor
|
||||||
|
return "", nil
|
||||||
|
default:
|
||||||
|
if _, err := exec.LookPath(editor); err != nil {
|
||||||
|
return "", fmt.Errorf("editor %s not found in PATH", editor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if filepath == "" {
|
||||||
|
tempFile, err = os.CreateTemp("", "cocommit_editor_*.txt")
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
} else {
|
||||||
|
tempFile, err = os.OpenFile(filepath, os.O_RDWR, 0666)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Could not create or open tempfile: %s", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(editor, tempFile.Name())
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return "", fmt.Errorf("error running editor command: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(tempFile.Name())
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error reading temp file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
message := string(data)
|
||||||
|
if message == "" {
|
||||||
|
fmt.Printf("Error: Commit message is empty. Please provide a commit message.\n")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the temp file
|
||||||
|
if strings.HasSuffix(message, "\n") {
|
||||||
|
message = strings.TrimSuffix(message, "\n")
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(message, "\r") {
|
||||||
|
message = strings.TrimSuffix(message, "\r")
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(message) == "" {
|
||||||
|
fmt.Printf("Error: Commit message is empty. Please provide a commit message.\n")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
// If the message is too long, truncate it
|
||||||
|
// if len(message) > 72 {
|
||||||
|
// fmt.Printf("Warning: Commit message is too long (%d characters). It will be truncated to 72 characters.\n", len(message))
|
||||||
|
// //TODO: Maybe add the rest to the description of the message?
|
||||||
|
// //description := message[72:]
|
||||||
|
// message = message[:72]
|
||||||
|
// }
|
||||||
|
|
||||||
|
return message, nil
|
||||||
|
}
|
||||||
+71
-14
@@ -7,11 +7,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const author_data = `
|
const author_data = `
|
||||||
@@ -166,6 +167,7 @@ func Test_FindAuthorFilePanic(t *testing.T) {
|
|||||||
os.Setenv("author_file", "")
|
os.Setenv("author_file", "")
|
||||||
os.Setenv("HOME", "")
|
os.Setenv("HOME", "")
|
||||||
os.Setenv("XDG_CONFIG_HOME", "")
|
os.Setenv("XDG_CONFIG_HOME", "")
|
||||||
|
utils.ConfigVar.Settings.AuthorFile = ""
|
||||||
utils.Find_authorfile()
|
utils.Find_authorfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,14 +180,10 @@ func Test_FindAuthorFileEnv(t *testing.T) {
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
os.Setenv("author_file", originalAuthorFile)
|
os.Setenv("author_file", originalAuthorFile)
|
||||||
|
|
||||||
if r := recover(); r == nil {
|
|
||||||
t.Errorf("Find_authorfile() did not panic")
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Set an invalid environment variable to trigger panic
|
os.Setenv("author_file", "author_file_test")
|
||||||
os.Setenv("author_file", "")
|
utils.ConfigVar.Settings.AuthorFile = ""
|
||||||
|
|
||||||
utils.Find_authorfile()
|
utils.Find_authorfile()
|
||||||
}
|
}
|
||||||
@@ -652,7 +650,7 @@ func Test_CommitAppender(t *testing.T) {
|
|||||||
message := strings.TrimSpace(string(out))
|
message := strings.TrimSpace(string(out))
|
||||||
|
|
||||||
commit := utils.Commit("", authors)
|
commit := utils.Commit("", authors)
|
||||||
err, appendedMessage := utils.GitCommitAppender(commit, "", nil, true, true)
|
err, appendedMessage := utils.GitCommitAppender(commit, "", nil, true, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GitCommitAppender() returned error: %v", err)
|
t.Errorf("GitCommitAppender() returned error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -665,7 +663,7 @@ func Test_CommitAppender(t *testing.T) {
|
|||||||
// check inverted commit
|
// check inverted commit
|
||||||
authors = []string{"^te"}
|
authors = []string{"^te"}
|
||||||
commit = utils.Commit("", authors)
|
commit = utils.Commit("", authors)
|
||||||
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true)
|
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GitCommitAppender() returned error: %v", err)
|
t.Errorf("GitCommitAppender() returned error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -678,7 +676,7 @@ func Test_CommitAppender(t *testing.T) {
|
|||||||
// Test CommitAppender with multiple authors
|
// Test CommitAppender with multiple authors
|
||||||
authors = []string{"te", "testtest"}
|
authors = []string{"te", "testtest"}
|
||||||
commit = utils.Commit("", authors)
|
commit = utils.Commit("", authors)
|
||||||
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true)
|
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GitCommitAppender() returned error: %v", err)
|
t.Errorf("GitCommitAppender() returned error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -690,7 +688,7 @@ func Test_CommitAppender(t *testing.T) {
|
|||||||
// Test CommitAppender with all authors
|
// Test CommitAppender with all authors
|
||||||
authors = []string{"all"}
|
authors = []string{"all"}
|
||||||
commit = utils.Commit("", authors)
|
commit = utils.Commit("", authors)
|
||||||
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true)
|
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GitCommitAppender() returned error: %v", err)
|
t.Errorf("GitCommitAppender() returned error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -704,7 +702,7 @@ func Test_CommitAppender(t *testing.T) {
|
|||||||
// Test CommitAppender with group authors
|
// Test CommitAppender with group authors
|
||||||
authors = []string{"gr1"}
|
authors = []string{"gr1"}
|
||||||
commit = utils.Commit("", authors)
|
commit = utils.Commit("", authors)
|
||||||
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true)
|
err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GitCommitAppender() returned error: %v", err)
|
t.Errorf("GitCommitAppender() returned error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -842,6 +840,65 @@ func Test_FetchGHProfileHTTP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Github tests END
|
// Github tests END
|
||||||
|
|
||||||
|
// Config tests BEGIN
|
||||||
|
|
||||||
|
func Test_Save(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
filename := "test_save_config.toml"
|
||||||
|
|
||||||
|
initial_config_data := `[settings]
|
||||||
|
author_file = "test_authors.json"
|
||||||
|
starting_scope = "git"
|
||||||
|
editor = "built-in"`
|
||||||
|
|
||||||
|
os.Create(filename)
|
||||||
|
defer os.Remove(filename)
|
||||||
|
// Write some test data to the file
|
||||||
|
os.WriteFile(filename, []byte(initial_config_data), 0644)
|
||||||
|
|
||||||
|
override_cfg := &utils.Config{
|
||||||
|
Settings: struct {
|
||||||
|
AuthorFile string `mapstructure:"author_file"`
|
||||||
|
StartingScope string `mapstructure:"starting_scope"`
|
||||||
|
Editor string `mapstructure:"editor"`
|
||||||
|
}{
|
||||||
|
AuthorFile: "test_authors.json",
|
||||||
|
StartingScope: "git",
|
||||||
|
Editor: "built-in",
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Set viper config file to be cfg
|
||||||
|
viper.SetConfigFile(filename)
|
||||||
|
// Set the config type to toml
|
||||||
|
viper.SetConfigType("toml")
|
||||||
|
|
||||||
|
|
||||||
|
// Change some values in the config
|
||||||
|
override_cfg.Settings.AuthorFile = "test"
|
||||||
|
override_cfg.Settings.StartingScope = "not_git"
|
||||||
|
override_cfg.Settings.Editor = "test_editor"
|
||||||
|
|
||||||
|
// Save the config
|
||||||
|
err := override_cfg.Save()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Save() returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file exists and contains expected content
|
||||||
|
data, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Save() did not create file: %v", data)
|
||||||
|
}
|
||||||
|
if string(initial_config_data) == string(data) {
|
||||||
|
t.Errorf("Save() did not write expected content:\nNew:\n%s\n\nOld:\n%s", string(data), string(initial_config_data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user