install.go

 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}