1package cli
2
3import (
4 "fmt"
5 "io"
6 "net/http"
7 "os"
8 "path/filepath"
9 "strings"
10
11 "github.com/floatpane/matcha/internal/httpclient"
12)
13
14// RunInstall handles `matcha install <url_or_file>`.
15func RunInstall(args []string) error {
16 if len(args) == 0 {
17 return fmt.Errorf("usage: matcha install <url_or_file>")
18 }
19
20 source := args[0]
21 var data []byte
22 var filename string
23
24 if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
25 // Download from URL
26 client := httpclient.New(httpclient.InstallTimeout)
27 resp, err := client.Get(source) //nolint:noctx
28 if err != nil {
29 return fmt.Errorf("failed to download: %w", err)
30 }
31 defer resp.Body.Close() //nolint:errcheck
32
33 if resp.StatusCode != http.StatusOK {
34 return fmt.Errorf("download returned status %d", resp.StatusCode)
35 }
36
37 data, err = io.ReadAll(resp.Body)
38 if err != nil {
39 return fmt.Errorf("failed to read response: %w", err)
40 }
41
42 // Extract filename from URL path
43 parts := strings.Split(strings.TrimRight(source, "/"), "/")
44 filename = parts[len(parts)-1]
45 } else {
46 // Read from local file
47 var err error
48 data, err = os.ReadFile(source)
49 if err != nil {
50 return fmt.Errorf("failed to read file: %w", err)
51 }
52 filename = filepath.Base(source)
53 }
54
55 if !strings.HasSuffix(filename, ".lua") {
56 return fmt.Errorf("plugin file must have a .lua extension")
57 }
58
59 pluginsDir, err := pluginsDir()
60 if err != nil {
61 return err
62 }
63
64 dest := filepath.Join(pluginsDir, filename)
65 if err := os.WriteFile(dest, data, 0644); err != nil { //nolint:gosec
66 return fmt.Errorf("failed to write plugin: %w", err)
67 }
68
69 fmt.Printf("Installed %s to %s\n", filename, dest)
70 return nil
71}
72
73func pluginsDir() (string, error) {
74 home, err := os.UserHomeDir()
75 if err != nil {
76 return "", fmt.Errorf("cannot find home directory: %w", err)
77 }
78 dir := filepath.Join(home, ".config", "matcha", "plugins")
79 if err := os.MkdirAll(dir, 0750); err != nil {
80 return "", fmt.Errorf("cannot create plugins directory: %w", err)
81 }
82 return dir, nil
83}