refactor: change package management for different software sources

This commit is contained in:
Patryk Hegenberg 2025-01-12 23:38:14 +01:00
parent f14b54ea20
commit c4fbac6b8d
12 changed files with 289 additions and 170 deletions

32
cargo.go Normal file
View file

@ -0,0 +1,32 @@
package main
import (
"fmt"
"log"
"os/exec"
)
type CargoConfig struct {
Enable bool `mapstructure:"enable"`
Packages []string `mapstructure:"packages"`
}
func installCargoPackages(packages []string) error {
if len(packages) == 0 {
return nil
}
fmt.Println("\nInstalliere Cargo-Pakete...")
for _, pkg := range packages {
err := installPackageWithProgress(pkg, func() error {
cmd := exec.Command("cargo", "install", pkg)
return cmd.Run()
})
if err != nil {
log.Printf("Fehler bei der Installation von %s: %v", pkg, err)
}
}
fmt.Println("Installation abgeschlossen")
return nil
}

View file

@ -3,7 +3,10 @@ package main
type Config struct {
Headless bool `mapstructure:"headless"`
Packages Packages `mapstructure:"packages"`
SpecialPackages SpecialPackages `mapstructure:"special_packages"`
Flatpak FlatpakConfig `mapstructure:"flatpak"`
Homebrew HomebrewConfig `mapstructure:"homebrew"`
Cargo CargoConfig `mapstructure:"cargo"`
Go GoConfig `mapstructure:"go"`
Pipx PipxConfig `mapstructure:"pipx"`
Dotfiles DotfilesConfig `mapstructure:"dotfiles"`
}

View file

@ -1,37 +1,19 @@
headless = false
headless = true
[packages]
headless = [
"git",
"curl",
"wget",
"ripgrep",
"bottom",
"bat",
"biber",
"bear",
"docker",
"docker-compose",
"fd",
"bat",
"lsd",
"zsh",
"jq",
"neofetch",
"neovim",
"helix",
"npm",
"stow",
"task",
"timew",
"typst-lsp",
"tree-sitter-cli",
"tmux",
"zoxide",
"python3-pip",
"pipx",
"golang",
"rustup",
"latexmk",
"luarocks",
]
@ -40,7 +22,6 @@ non_headless = [
"discord",
"flameshot",
"fuzzel",
"google-chrome",
"hyprcursor",
"hypridle",
"hyprland",
@ -54,8 +35,6 @@ non_headless = [
"neovide",
"pidgin",
"remmina",
"spotify",
"thunderbird",
"thunderbird-i18n-de",
"virt-manager",
"vlc",
@ -64,24 +43,26 @@ non_headless = [
"zathura",
"zathura-pdf-mupdf",
"zoom",
"zotero",
"android-studio",
]
[special_packages]
go = [
"github.com/jesseduffield/lazygit",
[go]
enable = true
packages = [
"github.com/stefanlogue/meteor",
"golang.org/x/tools/gopls",
"github.com/go-delve/delve/cmd/dlv",
"github.com/air-verse/air",
"go.senan.xyz/cliphist",
"github.com/goreleaser/goreleaser/v2",
# "go.senan.xyz/cliphist",
]
cargo = ["git-cliff", "bottom", "typst-cli"]
[cargo]
enable = true
packages = ["typst-cli"]
pipx = ["harlequin", "posting", "euporie"]
[pipx]
enable = true
packages = ["euporie"]
[flatpak]
enable = true
@ -96,8 +77,52 @@ packages = [
"io.freetubeapp.FreeTube",
"com.discordapp.Discord",
"com.nextcloud.desktopclient.nextcloud",
"com.github.tchx84.Flatseal",
"io.github.flattool.Warehouse",
"org.onlyoffice.desktopeditors",
# "com.google.Chrome",
# "org.mozilla.Thunderbird",
]
[homebrew]
enable = true
packages = [
"fd",
"fzf",
"ripgrep",
"neovim",
"helix",
"golang",
"rust",
"node",
"yazi",
"zk",
"bat",
"bottom",
"btop",
"git-cliff",
"glow",
"lazygit",
"goreleaser",
"harlequin",
"mage",
"posting",
"typst",
"wails",
"zoxide",
"lsd",
"jq",
"yq",
"timewarrior",
"tmux",
"pipx",
"fastfetch",
"stow",
"distrobox",
"asciidoc",
"asciidoctor",
]
[dotfiles]
enable = true
enable = false
git_repo = "https://codeberg.org/Pata1704/dotfiles.git"

View file

@ -4,8 +4,6 @@ import (
"fmt"
"log"
"os/exec"
"github.com/charmbracelet/bubbles/progress"
)
type FlatpakConfig struct {
@ -54,19 +52,15 @@ func installFlatpakPackages(packages []string) error {
}
fmt.Println("\nInstalliere Flatpak-Pakete...")
p := progress.New(
progress.WithDefaultGradient(),
progress.WithWidth(40),
)
for i, pkg := range packages {
p.SetPercent(float64(i) / float64(len(packages)))
fmt.Printf("Installiere Flatpak: %s\n", pkg)
for _, pkg := range packages {
err := installPackageWithProgress(pkg, func() error {
cmd := exec.Command("flatpak", "install", "-y", pkg)
if err := cmd.Run(); err != nil {
return cmd.Run()
})
if err != nil {
log.Printf("Fehler bei der Installation von %s: %v", pkg, err)
continue
}
}
return nil

32
golang.go Normal file
View file

@ -0,0 +1,32 @@
package main
import (
"fmt"
"log"
"os/exec"
)
type GoConfig struct {
Enable bool `mapstructure:"enable"`
Packages []string `mapstructure:"packages"`
}
func installGoPackages(packages []string) error {
if len(packages) == 0 {
return nil
}
fmt.Println("\nInstalliere Golang-Pakete...")
for _, pkg := range packages {
err := installPackageWithProgress(pkg, func() error {
cmd := exec.Command("go", "install", pkg+"@latest")
return cmd.Run()
})
if err != nil {
log.Printf("Fehler bei der Installation von %s: %v", pkg, err)
}
}
fmt.Println("Installation abgeschlossen")
return nil
}

40
homebrew.go Normal file
View file

@ -0,0 +1,40 @@
package main
import (
"fmt"
"log"
"os/exec"
)
type HomebrewConfig struct {
Enable bool `mapstructure:"enable"`
Packages []string `mapstructure:"packages"`
}
func installHomebrew() error {
err := executeShellCommand("sh -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)", "NONINTERACTE=1")
if err != nil {
return fmt.Errorf("fehler bei der Installation von Homebrew: %v", err)
}
return nil
}
func installHomebrewPackages(packages []string) error {
if len(packages) == 0 {
return nil
}
fmt.Println("\nInstalliere Homebrew-Pakete...")
for _, pkg := range packages {
err := installPackageWithProgress(pkg, func() error {
cmd := exec.Command("brew", "install", pkg)
return cmd.Run()
})
if err != nil {
log.Printf("Fehler bei der Installation von %s: %v", pkg, err)
}
}
fmt.Println("Installation abgeschlossen")
return nil
}

View file

@ -56,15 +56,6 @@ func (m model) installSpecialSoftware() error {
}
}
// if _, err := exec.LookPath("pipx"); err == nil {
// fmt.Println("Pipx ist bereits installiert.")
// } else {
// pipXCommand := "python3 -m pip install --user pipx && python3 -m pipx ensurepath"
// if err := installPackage(pipXCommand, "", ""); err != nil {
// return err
// }
// }
return nil
}

View file

@ -11,12 +11,6 @@ type Packages struct {
NonHeadless []string `mapstructure:"non_headless"`
}
type SpecialPackages struct {
Go []string `mapstructure:"go"`
Cargo []string `mapstructure:"cargo"`
Pipx []string `mapstructure:"pipx"`
}
func installPackage(cmd, pkg, sudoPassword string) error {
fullCmd := fmt.Sprintf("%s %s", cmd, pkg)
command := exec.Command("sudo", "-S", "sh", "-c", fullCmd)
@ -32,31 +26,6 @@ func installPackage(cmd, pkg, sudoPassword string) error {
return nil
}
func installSpecialPackages(sp SpecialPackages) error {
for _, pkg := range sp.Go {
cmd := exec.Command("go", "install", pkg+"@latest")
if err := cmd.Run(); err != nil {
return fmt.Errorf("fehler bei der Installation von %s: %v", pkg, err)
}
}
for _, pkg := range sp.Cargo {
cmd := exec.Command("cargo", "install", pkg)
if err := cmd.Run(); err != nil {
return fmt.Errorf("fehler bei der Installation von %s: %v", pkg, err)
}
}
for _, pkg := range sp.Pipx {
cmd := exec.Command("pipx", "install", pkg)
if err := cmd.Run(); err != nil {
return fmt.Errorf("fehler bei der Installation von %s: %v", pkg, err)
}
}
return nil
}
func printUnavailablePackages() {
if len(unavailablePackages) > 0 {
fmt.Println("\nFolgende Pakete waren nicht verfügbar:")

32
pipx.go Normal file
View file

@ -0,0 +1,32 @@
package main
import (
"fmt"
"log"
"os/exec"
)
type PipxConfig struct {
Enable bool `mapstructure:"enable"`
Packages []string `mapstructure:"packages"`
}
func installPipxPackages(packages []string) error {
if len(packages) == 0 {
return nil
}
fmt.Println("\nInstalliere Pipx-Pakete...")
for _, pkg := range packages {
err := installPackageWithProgress(pkg, func() error {
cmd := exec.Command("pipx", "install", pkg)
return cmd.Run()
})
if err != nil {
log.Printf("Fehler bei der Installation von %s: %v", pkg, err)
}
}
fmt.Println("Installation abgeschlossen")
return nil
}

View file

@ -3,8 +3,8 @@ package main
import (
"fmt"
"log"
"os"
"os/exec"
"runtime"
"github.com/charmbracelet/bubbles/progress"
"github.com/charmbracelet/bubbles/spinner"
@ -22,7 +22,7 @@ type specialSoftwareModel struct {
}
func newSpecialSoftwareModel(sudoPassword string) specialSoftwareModel {
items := []string{"oh-my-posh", "golang", "rust"}
items := []string{"oh-my-posh", "oh-my-zsh"}
p := progress.New(
progress.WithDefaultGradient(),
@ -92,42 +92,33 @@ func (m specialSoftwareModel) installItemCmd(item string) tea.Cmd {
if _, err := exec.LookPath("oh-my-posh"); err == nil {
return installedItemMsg(item)
}
err := executeShellCommand("curl -s https://ohmyposh.dev/install.sh | bash -s")
err := executeShellCommand("curl -s https://ohmyposh.dev/install.sh | bash -s", "")
if err != nil {
log.Printf("Fehler bei der Installation von oh-my-posh: %v\n", err)
}
case "golang":
if _, err := exec.LookPath("go"); err == nil {
case "oh-my-zsh":
if _, err := os.Stat(os.Getenv("HOME") + "/.oh-my-zsh"); !os.IsNotExist(err) {
return installedItemMsg(item)
}
golangVersion := "1.23.4"
if err := downloadGolang(golangVersion); err != nil {
log.Printf("Fehler beim Herunterladen von Go: %v", err)
}
golangCommand := fmt.Sprintf("sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go%s.linux-%s.tar.gz", golangVersion, runtime.GOARCH)
if err := installPackage(golangCommand, "", m.sudoPassword); err != nil {
log.Printf("Fehler beim Installieren von Go: %v", err)
}
case "rust":
if _, err := exec.LookPath("rustc"); err == nil {
if _, err := exec.LookPath("cargo"); err == nil {
return installedItemMsg(item)
}
}
err := executeShellCommand("curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -q -y")
err := executeShellCommand(`sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"`, "")
if err != nil {
log.Printf("Fehler bei der Installation von rustup: %v\n", err)
log.Printf("Fehler bei der Installation von Oh My Zsh: %v\n", err)
}
}
return installedItemMsg(item)
}
}
func executeShellCommand(command string) error {
cmd := exec.Command("bash", "-c", command)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("befehl fehlgeschlagen: %v\nAusgabe: %s", err, output)
plugins := []string{
"git clone https://github.com/zsh-users/zsh-autosuggestions.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions",
"git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting",
"git clone https://github.com/zdharma-continuum/fast-syntax-highlighting.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fast-syntax-highlighting",
"git clone --depth 1 -- https://github.com/marlonrichert/zsh-autocomplete.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autocomplete",
}
for _, plugin := range plugins {
err := executeShellCommand(plugin, "")
if err != nil {
log.Printf("Fehler bei der Installation des Plugins: %v\n", err)
}
}
}
return installedItemMsg(item)
}
return nil
}

92
tui.go
View file

@ -3,9 +3,7 @@ package main
import (
"fmt"
"log"
"os/exec"
"github.com/charmbracelet/bubbles/progress"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/huh"
"github.com/charmbracelet/lipgloss"
@ -68,12 +66,21 @@ func run(cmd *cobra.Command, args []string) {
printUnavailablePackages()
var installSpecial bool
if cfg.Homebrew.Enable {
if err := installHomebrew(); err != nil {
log.Printf("Warnung: %v", err)
}
if err := installHomebrewPackages(cfg.Homebrew.Packages); err != nil {
log.Printf("Warnung bei Homebrew-Paketen: %v", err)
}
}
var installBuild bool
form = huh.NewForm(
huh.NewGroup(
huh.NewConfirm().
Title("Möchten Sie die speziellen Pakete (Go, Rust, Pipx) installieren?").
Value(&installSpecial),
Title("Möchten Sie die Build Essentials installieren?").
Value(&installBuild),
),
).WithTheme(huh.ThemeCatppuccin())
@ -82,10 +89,26 @@ func run(cmd *cobra.Command, args []string) {
log.Fatal(err)
}
if installSpecial {
if installBuild {
if err := installBuildEssentials(os, sudoPassword); err != nil {
log.Printf("Warnung: %v", err)
}
}
var installShellExtensions bool
form = huh.NewForm(
huh.NewGroup(
huh.NewConfirm().
Title("Möchten Sie die Shell-Extensions installieren?").
Value(&installShellExtensions),
),
).WithTheme(huh.ThemeCatppuccin())
err = form.Run()
if err != nil {
log.Fatal(err)
}
if installShellExtensions {
sm := newSpecialSoftwareModel(sudoPassword)
p = tea.NewProgram(sm)
if _, err := p.Run(); err != nil {
@ -93,54 +116,19 @@ func run(cmd *cobra.Command, args []string) {
}
}
if len(cfg.SpecialPackages.Go) > 0 || len(cfg.SpecialPackages.Cargo) > 0 || len(cfg.SpecialPackages.Pipx) > 0 {
var allSpecialPkgs []struct {
typ string
name string
command string
}
for _, pkg := range cfg.SpecialPackages.Go {
allSpecialPkgs = append(allSpecialPkgs, struct {
typ string
name string
command string
}{"go", pkg, "go install " + pkg + "@latest"})
}
for _, pkg := range cfg.SpecialPackages.Cargo {
allSpecialPkgs = append(allSpecialPkgs, struct {
typ string
name string
command string
}{"cargo", pkg, "cargo install " + pkg})
}
for _, pkg := range cfg.SpecialPackages.Pipx {
allSpecialPkgs = append(allSpecialPkgs, struct {
typ string
name string
command string
}{"pipx", pkg, "pipx install " + pkg})
}
if len(allSpecialPkgs) > 0 {
fmt.Println("\nInstalliere spezielle Pakete...")
p := progress.New(
progress.WithDefaultGradient(),
progress.WithWidth(40),
)
for i, pkg := range allSpecialPkgs {
p.SetPercent(float64(i) / float64(len(allSpecialPkgs)))
fmt.Printf("Installiere %s Paket: %s\n", pkg.typ, pkg.name)
cmd := exec.Command("sh", "-c", pkg.command)
if err := cmd.Run(); err != nil {
log.Printf("Fehler bei der Installation von %s: %v", pkg.name, err)
continue
if cfg.Go.Enable {
if err := installGoPackages(cfg.Go.Packages); err != nil {
log.Printf("Warnung bei Homebrew-Paketen: %v", err)
}
}
if cfg.Cargo.Enable {
if err := installCargoPackages(cfg.Cargo.Packages); err != nil {
log.Printf("Warnung bei Homebrew-Paketen: %v", err)
}
}
if cfg.Pipx.Enable {
if err := installPipxPackages(cfg.Pipx.Packages); err != nil {
log.Printf("Warnung bei Homebrew-Paketen: %v", err)
}
}
if cfg.Flatpak.Enable {

View file

@ -5,6 +5,7 @@ import (
"io"
"net/http"
"os"
"os/exec"
"runtime"
"github.com/charmbracelet/huh"
@ -65,3 +66,24 @@ func max(a, b int) int {
}
return b
}
func installPackageWithProgress(name string, installFunc func() error) error {
err := installFunc()
if err != nil {
fmt.Printf("\r❌ %s\n", name)
return err
}
fmt.Printf("\r✓ %s\n", name)
return nil
}
func executeShellCommand(command string, env string) error {
cmd := exec.Command("bash", "-c", command)
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, env)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("befehl fehlgeschlagen: %v\nAusgabe: %s", err, output)
}
return nil
}