feat: initial commit
This commit is contained in:
commit
8a467d9004
5 changed files with 828 additions and 0 deletions
196
install.go
Normal file
196
install.go
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
// "github.com/adrg/xdg"
|
||||
)
|
||||
|
||||
// Installer verwaltet die Installation von LSP-Servern
|
||||
type Installer struct {
|
||||
installDir string
|
||||
binDir string
|
||||
}
|
||||
|
||||
// NewInstaller erstellt einen XDG-konformen Installer
|
||||
func NewInstaller(baseDir string) *Installer {
|
||||
installDir := filepath.Join(baseDir, "servers")
|
||||
binDir := filepath.Join(baseDir, "bin")
|
||||
|
||||
// Verzeichnisse erstellen
|
||||
os.MkdirAll(installDir, 0755)
|
||||
os.MkdirAll(binDir, 0755)
|
||||
|
||||
return &Installer{
|
||||
installDir: installDir,
|
||||
binDir: binDir,
|
||||
}
|
||||
}
|
||||
|
||||
// PrintPathInstructions zeigt dem Benutzer, wie der PATH gesetzt wird
|
||||
func (i *Installer) PrintPathInstructions() {
|
||||
fmt.Println("\n📁 LSP-Server werden installiert in:")
|
||||
fmt.Printf(" Binaries: %s\n", i.binDir)
|
||||
fmt.Printf(" Data: %s\n\n", i.installDir)
|
||||
|
||||
// Prüfen ob bereits im PATH
|
||||
pathEnv := os.Getenv("PATH")
|
||||
pathList := filepath.SplitList(pathEnv)
|
||||
inPath := false
|
||||
for _, p := range pathList {
|
||||
if p == i.binDir {
|
||||
inPath = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !inPath {
|
||||
fmt.Println("⚠️ Das Binary-Verzeichnis ist noch nicht im PATH!")
|
||||
fmt.Println("\nFüge folgende Zeile zu deiner Shell-Konfiguration hinzu:")
|
||||
fmt.Printf("\n # Für Bash (~/.bashrc):\n")
|
||||
fmt.Printf(" export PATH=\"%s:$PATH\"\n\n", i.binDir)
|
||||
fmt.Printf(" # Für Zsh (~/.zshrc):\n")
|
||||
fmt.Printf(" export PATH=\"%s:$PATH\"\n\n", i.binDir)
|
||||
fmt.Printf(" # Für Fish (~/.config/fish/config.fish):\n")
|
||||
fmt.Printf(" set -x PATH %s $PATH\n\n", i.binDir)
|
||||
} else {
|
||||
fmt.Println("✅ Binary-Verzeichnis ist bereits im PATH!")
|
||||
}
|
||||
}
|
||||
|
||||
// Install installiert einen LSP-Server basierend auf dem Typ
|
||||
func (i *Installer) Install(server LSPServer) error {
|
||||
switch server.InstallType {
|
||||
case "go", "golang":
|
||||
return i.installGo(server)
|
||||
case "npm":
|
||||
return i.installNpm(server)
|
||||
case "github":
|
||||
return i.installGithub(server)
|
||||
case "cargo":
|
||||
return i.installCargo(server)
|
||||
default:
|
||||
return fmt.Errorf("unsupported install type: %s (für %s)", server.InstallType, server.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// installGo installiert einen LSP-Server via go install
|
||||
func (i *Installer) installGo(server LSPServer) error {
|
||||
// Mason Source format: "golang.org/x/tools/gopls" oder ähnlich
|
||||
source := server.Source
|
||||
if !strings.Contains(source, "@") {
|
||||
source = source + "@" + server.Version
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "install", source)
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GOBIN="+i.binDir,
|
||||
)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go install failed: %v\nOutput: %s", err, output)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// installNpm installiert einen LSP-Server via npm
|
||||
func (i *Installer) installNpm(server LSPServer) error {
|
||||
serverDir := filepath.Join(i.installDir, server.Name)
|
||||
os.MkdirAll(serverDir, 0755)
|
||||
|
||||
// Mason Source format: "package-name" (einfacher npm Package-Name)
|
||||
cmd := exec.Command("npm", "install", "-g", "--prefix", serverDir, server.Source)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("npm install failed: %v\nOutput: %s", err, output)
|
||||
}
|
||||
|
||||
// Symlink zum bin-Verzeichnis erstellen
|
||||
// npm installiert in serverDir/lib/node_modules/.bin/
|
||||
binPath := filepath.Join(serverDir, "lib", "node_modules", ".bin", server.Executable)
|
||||
linkPath := filepath.Join(i.binDir, server.Executable)
|
||||
|
||||
os.Remove(linkPath) // Alten Link entfernen
|
||||
return os.Symlink(binPath, linkPath)
|
||||
}
|
||||
|
||||
// installGithub lädt ein Binary von GitHub Releases herunter
|
||||
func (i *Installer) installGithub(server LSPServer) error {
|
||||
// Mason Source format: "owner/repo"
|
||||
// Wir müssen die Download-URL konstruieren (vereinfacht)
|
||||
downloadURL := fmt.Sprintf("https://github.com/%s/releases/latest/download/%s",
|
||||
server.Source, server.Executable)
|
||||
|
||||
resp, err := http.Get(downloadURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("download failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("download failed with status: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
targetPath := filepath.Join(i.binDir, server.Executable)
|
||||
file, err := os.Create(targetPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(file, resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Executable-Rechte setzen
|
||||
return os.Chmod(targetPath, 0755)
|
||||
}
|
||||
|
||||
// installCargo installiert einen LSP-Server via cargo
|
||||
func (i *Installer) installCargo(server LSPServer) error {
|
||||
serverDir := filepath.Join(i.installDir, server.Name)
|
||||
|
||||
// Mason Source format: "crate-name"
|
||||
cmd := exec.Command("cargo", "install",
|
||||
server.Source,
|
||||
"--root", serverDir)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cargo install failed: %v\nOutput: %s", err, output)
|
||||
}
|
||||
|
||||
// Symlink erstellen
|
||||
binPath := filepath.Join(serverDir, "bin", server.Executable)
|
||||
linkPath := filepath.Join(i.binDir, server.Executable)
|
||||
|
||||
os.Remove(linkPath)
|
||||
return os.Symlink(binPath, linkPath)
|
||||
}
|
||||
|
||||
// IsInstalled prüft, ob ein Server installiert ist
|
||||
func (i *Installer) IsInstalled(server LSPServer) bool {
|
||||
binPath := filepath.Join(i.binDir, server.Executable)
|
||||
_, err := os.Stat(binPath)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Uninstall entfernt einen installierten LSP-Server
|
||||
func (i *Installer) Uninstall(server LSPServer) error {
|
||||
binPath := filepath.Join(i.binDir, server.Executable)
|
||||
serverDir := filepath.Join(i.installDir, server.Name)
|
||||
|
||||
os.Remove(binPath)
|
||||
os.RemoveAll(serverDir)
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue