mirror of
https://github.com/Valkyrie00/bold-brew.git
synced 2026-03-14 14:25:53 +01:00
refactor(brew): merge operations.go into brew.go
Consolidate all BrewService methods into a single file. Add section comments to organize code into logical groups: - Core info (GetBrewVersion) - Package operations (Update/Install/Remove) - Tap support (InstallTap/IsTapInstalled) - Internal helpers (executeCommand)
This commit is contained in:
parent
3e047e4461
commit
b1e2c581e5
2 changed files with 147 additions and 156 deletions
|
|
@ -2,8 +2,11 @@ package services
|
|||
|
||||
import (
|
||||
"bbrew/internal/models"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
|
@ -59,3 +62,147 @@ func (s *BrewService) UpdateHomebrew() error {
|
|||
cmd := exec.Command("brew", "update")
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
// UpdateAllPackages upgrades all outdated packages.
|
||||
func (s *BrewService) UpdateAllPackages(app *tview.Application, outputView *tview.TextView) error {
|
||||
cmd := exec.Command("brew", "upgrade") // #nosec G204
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// UpdatePackage upgrades a specific package.
|
||||
func (s *BrewService) UpdatePackage(info models.Package, app *tview.Application, outputView *tview.TextView) error {
|
||||
var cmd *exec.Cmd
|
||||
if info.Type == models.PackageTypeCask {
|
||||
cmd = exec.Command("brew", "upgrade", "--cask", info.Name) // #nosec G204
|
||||
} else {
|
||||
cmd = exec.Command("brew", "upgrade", info.Name) // #nosec G204
|
||||
}
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// RemovePackage uninstalls a package.
|
||||
func (s *BrewService) RemovePackage(info models.Package, app *tview.Application, outputView *tview.TextView) error {
|
||||
var cmd *exec.Cmd
|
||||
if info.Type == models.PackageTypeCask {
|
||||
cmd = exec.Command("brew", "uninstall", "--cask", info.Name) // #nosec G204
|
||||
} else {
|
||||
cmd = exec.Command("brew", "uninstall", info.Name) // #nosec G204
|
||||
}
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// InstallPackage installs a package.
|
||||
func (s *BrewService) InstallPackage(info models.Package, app *tview.Application, outputView *tview.TextView) error {
|
||||
var cmd *exec.Cmd
|
||||
if info.Type == models.PackageTypeCask {
|
||||
cmd = exec.Command("brew", "install", "--cask", info.Name) // #nosec G204
|
||||
} else {
|
||||
cmd = exec.Command("brew", "install", info.Name) // #nosec G204
|
||||
}
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// InstallTap installs a Homebrew tap.
|
||||
func (s *BrewService) InstallTap(tapName string, app *tview.Application, outputView *tview.TextView) error {
|
||||
cmd := exec.Command("brew", "tap", tapName) // #nosec G204
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// IsTapInstalled checks if a tap is already installed.
|
||||
func (s *BrewService) IsTapInstalled(tapName string) bool {
|
||||
cmd := exec.Command("brew", "tap")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
taps := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
for _, tap := range taps {
|
||||
if strings.TrimSpace(tap) == tapName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// executeCommand runs a command and captures its output, updating the provided TextView.
|
||||
func (s *BrewService) executeCommand(
|
||||
app *tview.Application,
|
||||
cmd *exec.Cmd,
|
||||
outputView *tview.TextView,
|
||||
) error {
|
||||
stdoutPipe, stdoutWriter := io.Pipe()
|
||||
stderrPipe, stderrWriter := io.Pipe()
|
||||
cmd.Stdout = stdoutWriter
|
||||
cmd.Stderr = stderrWriter
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
|
||||
cmdErrCh := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer stdoutWriter.Close()
|
||||
defer stderrWriter.Close()
|
||||
cmdErrCh <- cmd.Wait()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer stdoutPipe.Close()
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := stdoutPipe.Read(buf)
|
||||
if n > 0 {
|
||||
output := make([]byte, n)
|
||||
copy(output, buf[:n])
|
||||
app.QueueUpdateDraw(func() {
|
||||
_, _ = outputView.Write(output) // #nosec G104
|
||||
outputView.ScrollToEnd()
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
app.QueueUpdateDraw(func() {
|
||||
fmt.Fprintf(outputView, "\nError: %v\n", err)
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer stderrPipe.Close()
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := stderrPipe.Read(buf)
|
||||
if n > 0 {
|
||||
output := make([]byte, n)
|
||||
copy(output, buf[:n])
|
||||
app.QueueUpdateDraw(func() {
|
||||
_, _ = outputView.Write(output) // #nosec G104
|
||||
outputView.ScrollToEnd()
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
app.QueueUpdateDraw(func() {
|
||||
fmt.Fprintf(outputView, "\nError: %v\n", err)
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return <-cmdErrCh
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,156 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"bbrew/internal/models"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
// UpdateAllPackages upgrades all outdated packages.
|
||||
func (s *BrewService) UpdateAllPackages(app *tview.Application, outputView *tview.TextView) error {
|
||||
cmd := exec.Command("brew", "upgrade") // #nosec G204
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// UpdatePackage upgrades a specific package.
|
||||
func (s *BrewService) UpdatePackage(info models.Package, app *tview.Application, outputView *tview.TextView) error {
|
||||
var cmd *exec.Cmd
|
||||
if info.Type == models.PackageTypeCask {
|
||||
cmd = exec.Command("brew", "upgrade", "--cask", info.Name) // #nosec G204
|
||||
} else {
|
||||
cmd = exec.Command("brew", "upgrade", info.Name) // #nosec G204
|
||||
}
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// RemovePackage uninstalls a package.
|
||||
func (s *BrewService) RemovePackage(info models.Package, app *tview.Application, outputView *tview.TextView) error {
|
||||
var cmd *exec.Cmd
|
||||
if info.Type == models.PackageTypeCask {
|
||||
cmd = exec.Command("brew", "uninstall", "--cask", info.Name) // #nosec G204
|
||||
} else {
|
||||
cmd = exec.Command("brew", "uninstall", info.Name) // #nosec G204
|
||||
}
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// InstallPackage installs a package.
|
||||
func (s *BrewService) InstallPackage(info models.Package, app *tview.Application, outputView *tview.TextView) error {
|
||||
var cmd *exec.Cmd
|
||||
if info.Type == models.PackageTypeCask {
|
||||
cmd = exec.Command("brew", "install", "--cask", info.Name) // #nosec G204
|
||||
} else {
|
||||
cmd = exec.Command("brew", "install", info.Name) // #nosec G204
|
||||
}
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// InstallTap installs a Homebrew tap.
|
||||
func (s *BrewService) InstallTap(tapName string, app *tview.Application, outputView *tview.TextView) error {
|
||||
cmd := exec.Command("brew", "tap", tapName) // #nosec G204
|
||||
return s.executeCommand(app, cmd, outputView)
|
||||
}
|
||||
|
||||
// IsTapInstalled checks if a tap is already installed.
|
||||
func (s *BrewService) IsTapInstalled(tapName string) bool {
|
||||
cmd := exec.Command("brew", "tap")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
taps := strings.Split(strings.TrimSpace(string(output)), "\n")
|
||||
for _, tap := range taps {
|
||||
if strings.TrimSpace(tap) == tapName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// executeCommand runs a command and captures its output, updating the provided TextView.
|
||||
func (s *BrewService) executeCommand(
|
||||
app *tview.Application,
|
||||
cmd *exec.Cmd,
|
||||
outputView *tview.TextView,
|
||||
) error {
|
||||
stdoutPipe, stdoutWriter := io.Pipe()
|
||||
stderrPipe, stderrWriter := io.Pipe()
|
||||
cmd.Stdout = stdoutWriter
|
||||
cmd.Stderr = stderrWriter
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
|
||||
cmdErrCh := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer stdoutWriter.Close()
|
||||
defer stderrWriter.Close()
|
||||
cmdErrCh <- cmd.Wait()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer stdoutPipe.Close()
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := stdoutPipe.Read(buf)
|
||||
if n > 0 {
|
||||
output := make([]byte, n)
|
||||
copy(output, buf[:n])
|
||||
app.QueueUpdateDraw(func() {
|
||||
_, _ = outputView.Write(output) // #nosec G104
|
||||
outputView.ScrollToEnd()
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
app.QueueUpdateDraw(func() {
|
||||
fmt.Fprintf(outputView, "\nError: %v\n", err)
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer stderrPipe.Close()
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
n, err := stderrPipe.Read(buf)
|
||||
if n > 0 {
|
||||
output := make([]byte, n)
|
||||
copy(output, buf[:n])
|
||||
app.QueueUpdateDraw(func() {
|
||||
_, _ = outputView.Write(output) // #nosec G104
|
||||
outputView.ScrollToEnd()
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
app.QueueUpdateDraw(func() {
|
||||
fmt.Fprintf(outputView, "\nError: %v\n", err)
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return <-cmdErrCh
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue