-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
145 lines (121 loc) · 2.73 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package main
import (
"context"
"errors"
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"syscall"
"github.com/BurntSushi/toml"
"github.com/charmbracelet/log"
"github.com/joho/godotenv"
gap "github.com/muesli/go-app-paths"
"github.com/rlcurrall/muxi/pkg/multiplexer"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
)
var (
// Version as provided by goreleaser.
Version = ""
// CommitSHA as provided by goreleaser.
CommitSHA = ""
rootCmd = &cobra.Command{
Use: "muxi",
Short: "A simple multiplexer",
SilenceErrors: false,
RunE: execute,
}
)
func main() {
closer, err := setupLog()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if err := rootCmd.Execute(); err != nil {
_ = closer()
os.Exit(1)
}
_ = closer()
}
func getLogFilePath() (string, error) {
dir, err := gap.NewScope(gap.User, "muxi").CacheDir()
if err != nil {
return "", err
}
return filepath.Join(dir, "muxi.log"), nil
}
func setupLog() (func() error, error) {
log.SetOutput(io.Discard)
// Log to file, if set
logFile, err := getLogFilePath()
if err != nil {
return nil, err
}
if err := os.MkdirAll(filepath.Dir(logFile), 0o755); err != nil {
// log disabled
return func() error { return nil }, nil
}
f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
if err != nil {
// log disabled
return func() error { return nil }, nil
}
log.SetOutput(f)
log.SetLevel(log.DebugLevel)
return f.Close, nil
}
func execute(cmd *cobra.Command, args []string) error {
env := os.Environ()
godotenv.Load()
var conf MuxiConfig
if _, err := os.Stat("muxi.toml"); !os.IsNotExist(err) {
if _, err := toml.DecodeFile("muxi.toml", &conf); err != nil {
log.Errorf("Error loading conif file: %s", err)
return err
}
}
if len(conf.Commands) == 0 {
log.Warn("No commands configured")
return errors.New("No commands configured")
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, syscall.SIGINT)
go func() {
<-interruptChannel
cancel()
}()
mux := multiplexer.New(ctx)
for _, c := range conf.Commands {
mux.AddProcess(c.Name, c.Args, c.Icon, c.Name, c.Cwd, true, c.Autostart, env...)
}
var wg errgroup.Group
wg.Go(func() error {
defer cancel()
mux.Start()
return nil
})
if err := wg.Wait(); err != nil {
log.Errorf("An error occurred in wait group: %s", err)
return err
}
return nil
}
type PackageJSON struct {
Scripts map[string]string `json:"scripts"`
}
type MuxiConfig struct {
AddNpmScripts bool `toml:"add_npm_scripts"`
Commands []Command
}
type Command struct {
Name string
Args []string
Autostart bool
Icon string
Cwd string
}