mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-21 23:01:03 +00:00
more progress
This commit is contained in:
parent
3cfa4a2bda
commit
5bf1a40d2f
9 changed files with 120 additions and 100 deletions
|
|
@ -30,15 +30,10 @@ type Container struct {
|
|||
OSCommand *OSCommand
|
||||
Log *logrus.Entry
|
||||
Stats ContainerCliStat
|
||||
StatHistory []ContainerCliStat
|
||||
Details Details
|
||||
}
|
||||
|
||||
type DetailsCollection struct {
|
||||
InspectDetails Details
|
||||
CLIStats ContainerCliStat
|
||||
ClientStats ContainerStats
|
||||
}
|
||||
|
||||
type Details struct {
|
||||
ID string `json:"Id"`
|
||||
Created time.Time `json:"Created"`
|
||||
|
|
@ -251,11 +246,13 @@ func (c *Container) GetDisplayStrings(isFocused bool) []string {
|
|||
|
||||
// GetDisplayCPUPerc colors the cpu percentage based on how extreme it is
|
||||
func (c *Container) GetDisplayCPUPerc() string {
|
||||
if c.Stats.CPUPerc == "" {
|
||||
stats := c.GetStats()
|
||||
|
||||
if stats.CPUPerc == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
percentage, err := strconv.ParseFloat(strings.TrimSuffix(c.Stats.CPUPerc, "%"), 32)
|
||||
percentage, err := strconv.ParseFloat(strings.TrimSuffix(stats.CPUPerc, "%"), 32)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return ""
|
||||
|
|
@ -270,7 +267,7 @@ func (c *Container) GetDisplayCPUPerc() string {
|
|||
clr = color.FgWhite
|
||||
}
|
||||
|
||||
return utils.ColoredString(c.Stats.CPUPerc, clr)
|
||||
return utils.ColoredString(stats.CPUPerc, clr)
|
||||
}
|
||||
|
||||
// GetColor Container color
|
||||
|
|
@ -344,3 +341,11 @@ func (c *Container) Attach() (*exec.Cmd, error) {
|
|||
func (c *Container) Top() (types.ContainerProcessList, error) {
|
||||
return c.Client.ContainerTop(context.Background(), c.ID, []string{})
|
||||
}
|
||||
|
||||
// GetStats gets the container's most recent stats
|
||||
func (c *Container) GetStats() ContainerCliStat {
|
||||
if len(c.StatHistory) == 0 {
|
||||
return ContainerCliStat{}
|
||||
}
|
||||
return c.StatHistory[len(c.StatHistory)-1]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/acarl005/stripansi"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/client"
|
||||
|
|
@ -25,6 +28,11 @@ type DockerCommand struct {
|
|||
Client *client.Client
|
||||
InDockerComposeProject bool
|
||||
ErrorChan chan error
|
||||
ContainerMutex sync.Mutex
|
||||
ServiceMutex sync.Mutex
|
||||
Services []*Service
|
||||
Containers []*Container
|
||||
Images []*Image
|
||||
}
|
||||
|
||||
// NewDockerCommand it runs git commands
|
||||
|
|
@ -45,50 +53,54 @@ func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Localize
|
|||
}, nil
|
||||
}
|
||||
|
||||
// UpdateContainerStats takes a slice of containers and returns the same slice but with new stats added
|
||||
// TODO: consider using this for everything stats-related
|
||||
func (c *DockerCommand) UpdateContainerStats(containers []*Container) {
|
||||
// TODO: consider using a stream rather than polling
|
||||
command := `docker stats --all --no-trunc --no-stream --format '{{json .}}'`
|
||||
output, err := c.OSCommand.RunCommandWithOutput(command)
|
||||
// MonitorContainerStats monitors a stream of container stats and updates the containers as each new stats object is received
|
||||
func (c *DockerCommand) MonitorContainerStats() {
|
||||
|
||||
command := `docker stats --all --no-trunc --format '{{json .}}'`
|
||||
cmd := c.OSCommand.RunCustomCommand(command)
|
||||
|
||||
r, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
c.ErrorChan <- err
|
||||
return
|
||||
}
|
||||
|
||||
jsonStats := "[" + strings.Join(
|
||||
strings.Split(
|
||||
strings.Trim(output, "\n"), "\n",
|
||||
), ",",
|
||||
) + "]"
|
||||
cmd.Start()
|
||||
|
||||
c.Log.Warn(jsonStats)
|
||||
|
||||
var stats []ContainerCliStat
|
||||
if err := json.Unmarshal([]byte(jsonStats), &stats); err != nil {
|
||||
c.ErrorChan <- err
|
||||
return
|
||||
}
|
||||
|
||||
for _, stat := range stats {
|
||||
for _, container := range containers {
|
||||
if container.ID == stat.ID {
|
||||
container.Stats = stat
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
for scanner.Scan() {
|
||||
var stats ContainerCliStat
|
||||
// need to strip ANSI codes because uses escape sequences to clear the screen with each refresh
|
||||
cleanString := stripansi.Strip(scanner.Text())
|
||||
if err := json.Unmarshal([]byte(cleanString), &stats); err != nil {
|
||||
c.ErrorChan <- err
|
||||
return
|
||||
}
|
||||
c.ContainerMutex.Lock()
|
||||
for _, container := range c.Containers {
|
||||
if container.ID == stats.ID {
|
||||
container.StatHistory = append(container.StatHistory, stats)
|
||||
}
|
||||
}
|
||||
c.ContainerMutex.Unlock()
|
||||
}
|
||||
|
||||
c.Log.Warn("updated containers")
|
||||
cmd.Wait()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetContainersAndServices returns a slice of docker containers
|
||||
func (c *DockerCommand) GetContainersAndServices(currentServices []*Service) ([]*Container, []*Service, error) {
|
||||
func (c *DockerCommand) GetContainersAndServices() error {
|
||||
c.ServiceMutex.Lock()
|
||||
defer c.ServiceMutex.Unlock()
|
||||
|
||||
currentServices := c.Services
|
||||
|
||||
containers, err := c.GetContainers()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
var services []*Service
|
||||
|
|
@ -98,7 +110,7 @@ func (c *DockerCommand) GetContainersAndServices(currentServices []*Service) ([]
|
|||
} else {
|
||||
services, err = c.GetServices()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,11 +136,19 @@ func (c *DockerCommand) GetContainersAndServices(currentServices []*Service) ([]
|
|||
return services[i].Name < services[j].Name
|
||||
})
|
||||
|
||||
return containers, services, nil
|
||||
c.Containers = containers
|
||||
c.Services = services
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetContainers gets the docker containers
|
||||
func (c *DockerCommand) GetContainers() ([]*Container, error) {
|
||||
c.ContainerMutex.Lock()
|
||||
defer c.ContainerMutex.Unlock()
|
||||
|
||||
currentContainers := c.Containers
|
||||
|
||||
containers, err := c.Client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -149,12 +169,16 @@ func (c *DockerCommand) GetContainers() ([]*Container, error) {
|
|||
OSCommand: c.OSCommand,
|
||||
Log: c.Log,
|
||||
}
|
||||
|
||||
// bring across old stats information
|
||||
for _, currentContainer := range currentContainers {
|
||||
if currentContainer.ID == container.ID {
|
||||
ownContainers[i].StatHistory = currentContainer.StatHistory // might need to use pointers here in case we're deep copying everything
|
||||
ownContainers[i].Details = currentContainer.Details
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.UpdateContainerDetails(ownContainers)
|
||||
|
||||
c.UpdateContainerStats(ownContainers)
|
||||
|
||||
return ownContainers, nil
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +215,12 @@ func (c *DockerCommand) GetServices() ([]*Service, error) {
|
|||
|
||||
// UpdateContainerDetails attaches the details returned from docker inspect to each of the containers
|
||||
// this contains a bit more info than what you get from the go-docker client
|
||||
func (c *DockerCommand) UpdateContainerDetails(containers []*Container) error {
|
||||
func (c *DockerCommand) UpdateContainerDetails() error {
|
||||
c.ContainerMutex.Lock()
|
||||
defer c.ContainerMutex.Unlock()
|
||||
|
||||
containers := c.Containers
|
||||
|
||||
ids := make([]string, len(containers))
|
||||
for i, container := range containers {
|
||||
ids[i] = container.ID
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/fatih/color"
|
||||
|
|
@ -91,8 +90,6 @@ func (i *Image) RenderHistory() (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
i.Log.Warn(spew.Sdump(history))
|
||||
|
||||
layers := make([]*Layer, len(history))
|
||||
for i, layer := range history {
|
||||
layers[i] = &Layer{layer}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
|
||||
|
|
@ -58,9 +60,11 @@ func (c *OSCommand) SetCommand(cmd func(string, ...string) *exec.Cmd) {
|
|||
|
||||
// RunCommandWithOutput wrapper around commands returning their output and error
|
||||
func (c *OSCommand) RunCommandWithOutput(command string) (string, error) {
|
||||
c.Log.WithField("command", command).Info("RunCommand")
|
||||
cmd := c.ExecutableFromString(command)
|
||||
return sanitisedCommandOutput(cmd.CombinedOutput())
|
||||
before := time.Now()
|
||||
output, err := sanitisedCommandOutput(cmd.CombinedOutput())
|
||||
c.Log.Warn(fmt.Sprintf("'%s': %s", command, time.Since(before)))
|
||||
return output, err
|
||||
}
|
||||
|
||||
// RunExecutableWithOutput runs an executable file and returns its output
|
||||
|
|
@ -77,7 +81,7 @@ func (c *OSCommand) RunExecutable(cmd *exec.Cmd) error {
|
|||
// ExecutableFromString takes a string like `git status` and returns an executable command for it
|
||||
func (c *OSCommand) ExecutableFromString(commandStr string) *exec.Cmd {
|
||||
splitCmd := str.ToArgv(commandStr)
|
||||
c.Log.Info(splitCmd)
|
||||
// c.Log.Info(splitCmd)
|
||||
return c.command(splitCmd[0], splitCmd[1:]...)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func (gui *Gui) getSelectedContainer(g *gocui.Gui) (*commands.Container, error)
|
|||
return &commands.Container{}, gui.Errors.ErrNoContainers
|
||||
}
|
||||
|
||||
return gui.State.Containers[selectedLine], nil
|
||||
return gui.DockerCommand.Containers[selectedLine], nil
|
||||
}
|
||||
|
||||
func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error {
|
||||
|
|
@ -42,7 +42,7 @@ func (gui *Gui) handleContainersFocus(g *gocui.Gui, v *gocui.View) error {
|
|||
prevSelectedLine := gui.State.Panels.Containers.SelectedLine
|
||||
newSelectedLine := cy - oy
|
||||
|
||||
if newSelectedLine > len(gui.State.Containers)-1 || len(utils.Decolorise(gui.State.Containers[newSelectedLine].Name)) < cx {
|
||||
if newSelectedLine > len(gui.DockerCommand.Containers)-1 || len(utils.Decolorise(gui.DockerCommand.Containers[newSelectedLine].Name)) < cx {
|
||||
return gui.handleContainerSelect(gui.g, v)
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ func (gui *Gui) handleContainerSelect(g *gocui.Gui, v *gocui.View) error {
|
|||
gui.State.Panels.Main.ObjectKey = key
|
||||
}
|
||||
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.State.Containers), v); err != nil {
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Containers.SelectedLine, len(gui.DockerCommand.Containers), v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ func (gui *Gui) renderContainerConfig(mainView *gocui.View, container *commands.
|
|||
mainView.Autoscroll = false
|
||||
mainView.Title = "Config"
|
||||
|
||||
data, err := json.MarshalIndent(&container.Container, "", " ")
|
||||
data, err := json.MarshalIndent(&container.Details, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -242,25 +242,25 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if len(gui.State.Containers) > 0 && gui.State.Panels.Containers.SelectedLine == -1 {
|
||||
if len(gui.DockerCommand.Containers) > 0 && gui.State.Panels.Containers.SelectedLine == -1 {
|
||||
gui.State.Panels.Containers.SelectedLine = 0
|
||||
}
|
||||
if len(gui.State.Containers)-1 < gui.State.Panels.Containers.SelectedLine {
|
||||
gui.State.Panels.Containers.SelectedLine = len(gui.State.Containers) - 1
|
||||
if len(gui.DockerCommand.Containers)-1 < gui.State.Panels.Containers.SelectedLine {
|
||||
gui.State.Panels.Containers.SelectedLine = len(gui.DockerCommand.Containers) - 1
|
||||
}
|
||||
|
||||
// doing the exact same thing for services
|
||||
if len(gui.State.Services) > 0 && gui.State.Panels.Services.SelectedLine == -1 {
|
||||
if len(gui.DockerCommand.Services) > 0 && gui.State.Panels.Services.SelectedLine == -1 {
|
||||
gui.State.Panels.Services.SelectedLine = 0
|
||||
}
|
||||
if len(gui.State.Services)-1 < gui.State.Panels.Services.SelectedLine {
|
||||
gui.State.Panels.Services.SelectedLine = len(gui.State.Services) - 1
|
||||
if len(gui.DockerCommand.Services)-1 < gui.State.Panels.Services.SelectedLine {
|
||||
gui.State.Panels.Services.SelectedLine = len(gui.DockerCommand.Services) - 1
|
||||
}
|
||||
|
||||
gui.g.Update(func(g *gocui.Gui) error {
|
||||
containersView.Clear()
|
||||
isFocused := gui.g.CurrentView().Name() == "containers"
|
||||
list, err := utils.RenderList(gui.State.Containers, utils.IsFocused(isFocused))
|
||||
list, err := utils.RenderList(gui.DockerCommand.Containers, utils.IsFocused(isFocused))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -279,7 +279,7 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
servicesView := gui.getServicesView()
|
||||
servicesView.Clear()
|
||||
isFocused = gui.g.CurrentView().Name() == "services"
|
||||
list, err = utils.RenderList(gui.State.Services, utils.IsFocused(isFocused))
|
||||
list, err = utils.RenderList(gui.DockerCommand.Services, utils.IsFocused(isFocused))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -295,15 +295,7 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
}
|
||||
|
||||
func (gui *Gui) refreshStateContainersAndServices() error {
|
||||
containers, services, err := gui.DockerCommand.GetContainersAndServices(gui.State.Services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gui.State.Containers = containers
|
||||
gui.State.Services = services
|
||||
|
||||
return nil
|
||||
return gui.DockerCommand.GetContainersAndServices()
|
||||
}
|
||||
|
||||
func (gui *Gui) handleContainersNextLine(g *gocui.Gui, v *gocui.View) error {
|
||||
|
|
@ -312,7 +304,7 @@ func (gui *Gui) handleContainersNextLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Containers
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Containers), false)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Containers), false)
|
||||
|
||||
return gui.handleContainerSelect(gui.g, v)
|
||||
}
|
||||
|
|
@ -323,7 +315,7 @@ func (gui *Gui) handleContainersPrevLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Containers
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Containers), true)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Containers), true)
|
||||
|
||||
return gui.handleContainerSelect(gui.g, v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,9 +109,6 @@ type panelStates struct {
|
|||
}
|
||||
|
||||
type guiState struct {
|
||||
Services []*commands.Service
|
||||
Containers []*commands.Container
|
||||
Images []*commands.Image
|
||||
MenuItemCount int // can't store the actual list because it's of interface{} type
|
||||
PreviousView string
|
||||
Platform commands.Platform
|
||||
|
|
@ -126,7 +123,6 @@ type guiState struct {
|
|||
func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand *commands.OSCommand, tr *i18n.Localizer, config *config.AppConfig, errorChan chan error) (*Gui, error) {
|
||||
|
||||
initialState := guiState{
|
||||
Containers: make([]*commands.Container, 0),
|
||||
PreviousView: "services",
|
||||
Platform: *oSCommand.Platform,
|
||||
Panels: &panelStates{
|
||||
|
|
@ -430,8 +426,8 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||
}
|
||||
|
||||
listViews := map[*gocui.View]listViewState{
|
||||
containersView: {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.State.Containers)},
|
||||
imagesView: {selectedLine: gui.State.Panels.Images.SelectedLine, lineCount: len(gui.State.Images)},
|
||||
containersView: {selectedLine: gui.State.Panels.Containers.SelectedLine, lineCount: len(gui.DockerCommand.Containers)},
|
||||
imagesView: {selectedLine: gui.State.Panels.Images.SelectedLine, lineCount: len(gui.DockerCommand.Images)},
|
||||
}
|
||||
|
||||
// menu view might not exist so we check to be safe
|
||||
|
|
@ -501,6 +497,7 @@ func (gui *Gui) renderGlobalOptions() error {
|
|||
}
|
||||
|
||||
func (gui *Gui) goEvery(interval time.Duration, function func() error) {
|
||||
_ = function() // time.Tick doesn't run immediately so we'll do that here // TODO: maybe change
|
||||
go func() {
|
||||
for range time.Tick(interval) {
|
||||
_ = function()
|
||||
|
|
@ -536,9 +533,12 @@ func (gui *Gui) Run() error {
|
|||
gui.waitForIntro.Wait()
|
||||
gui.goEvery(time.Millisecond*50, gui.renderAppStatus)
|
||||
gui.goEvery(time.Millisecond*30, gui.reRenderMain)
|
||||
gui.goEvery(time.Millisecond*500, gui.refreshContainersAndServices)
|
||||
gui.goEvery(time.Millisecond*100, gui.refreshContainersAndServices)
|
||||
gui.goEvery(time.Millisecond*1000, gui.DockerCommand.UpdateContainerDetails)
|
||||
}()
|
||||
|
||||
go gui.DockerCommand.MonitorContainerStats()
|
||||
|
||||
go func() {
|
||||
for err := range gui.ErrorChan {
|
||||
gui.createErrorPanel(gui.g, err.Error())
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ func (gui *Gui) getSelectedImage(g *gocui.Gui) (*commands.Image, error) {
|
|||
return &commands.Image{}, gui.Errors.ErrNoImages
|
||||
}
|
||||
|
||||
return gui.State.Images[selectedLine], nil
|
||||
return gui.DockerCommand.Images[selectedLine], nil
|
||||
}
|
||||
|
||||
func (gui *Gui) handleImagesFocus(g *gocui.Gui, v *gocui.View) error {
|
||||
|
|
@ -39,7 +39,7 @@ func (gui *Gui) handleImagesFocus(g *gocui.Gui, v *gocui.View) error {
|
|||
prevSelectedLine := gui.State.Panels.Images.SelectedLine
|
||||
newSelectedLine := cy - oy
|
||||
|
||||
if newSelectedLine > len(gui.State.Images)-1 || len(utils.Decolorise(gui.State.Images[newSelectedLine].Name)) < cx {
|
||||
if newSelectedLine > len(gui.DockerCommand.Images)-1 || len(utils.Decolorise(gui.DockerCommand.Images[newSelectedLine].Name)) < cx {
|
||||
return gui.handleImageSelect(gui.g, v)
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ func (gui *Gui) handleImageSelect(g *gocui.Gui, v *gocui.View) error {
|
|||
gui.State.Panels.Main.ObjectKey = key
|
||||
}
|
||||
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Images.SelectedLine, len(gui.State.Images), v); err != nil {
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Images.SelectedLine, len(gui.DockerCommand.Images), v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -129,18 +129,18 @@ func (gui *Gui) refreshImages() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if len(gui.State.Images) > 0 && gui.State.Panels.Images.SelectedLine == -1 {
|
||||
if len(gui.DockerCommand.Images) > 0 && gui.State.Panels.Images.SelectedLine == -1 {
|
||||
gui.State.Panels.Images.SelectedLine = 0
|
||||
}
|
||||
if len(gui.State.Images)-1 < gui.State.Panels.Images.SelectedLine {
|
||||
gui.State.Panels.Images.SelectedLine = len(gui.State.Images) - 1
|
||||
if len(gui.DockerCommand.Images)-1 < gui.State.Panels.Images.SelectedLine {
|
||||
gui.State.Panels.Images.SelectedLine = len(gui.DockerCommand.Images) - 1
|
||||
}
|
||||
|
||||
gui.g.Update(func(g *gocui.Gui) error {
|
||||
|
||||
ImagesView.Clear()
|
||||
isFocused := gui.g.CurrentView().Name() == "Images"
|
||||
list, err := utils.RenderList(gui.State.Images, utils.IsFocused(isFocused))
|
||||
list, err := utils.RenderList(gui.DockerCommand.Images, utils.IsFocused(isFocused))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -161,7 +161,7 @@ func (gui *Gui) refreshStateImages() error {
|
|||
return err
|
||||
}
|
||||
|
||||
gui.State.Images = Images
|
||||
gui.DockerCommand.Images = Images
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -172,7 +172,7 @@ func (gui *Gui) handleImagesNextLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Images
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Images), false)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Images), false)
|
||||
|
||||
return gui.handleImageSelect(gui.g, v)
|
||||
}
|
||||
|
|
@ -183,7 +183,7 @@ func (gui *Gui) handleImagesPrevLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Images
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Images), true)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Images), true)
|
||||
|
||||
return gui.handleImageSelect(gui.g, v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func (gui *Gui) getSelectedService(g *gocui.Gui) (*commands.Service, error) {
|
|||
return &commands.Service{}, errors.New("no service selected")
|
||||
}
|
||||
|
||||
return gui.State.Services[selectedLine], nil
|
||||
return gui.DockerCommand.Services[selectedLine], nil
|
||||
}
|
||||
|
||||
func (gui *Gui) handleServicesFocus(g *gocui.Gui, v *gocui.View) error {
|
||||
|
|
@ -37,7 +37,7 @@ func (gui *Gui) handleServicesFocus(g *gocui.Gui, v *gocui.View) error {
|
|||
prevSelectedLine := gui.State.Panels.Services.SelectedLine
|
||||
newSelectedLine := cy - oy
|
||||
|
||||
if newSelectedLine > len(gui.State.Services)-1 || len(utils.Decolorise(gui.State.Services[newSelectedLine].Name)) < cx {
|
||||
if newSelectedLine > len(gui.DockerCommand.Services)-1 || len(utils.Decolorise(gui.DockerCommand.Services[newSelectedLine].Name)) < cx {
|
||||
return gui.handleServiceSelect(gui.g, v)
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ func (gui *Gui) handleServiceSelect(g *gocui.Gui, v *gocui.View) error {
|
|||
gui.State.Panels.Main.ObjectKey = key
|
||||
}
|
||||
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Services.SelectedLine, len(gui.State.Services), v); err != nil {
|
||||
if err := gui.focusPoint(0, gui.State.Panels.Services.SelectedLine, len(gui.DockerCommand.Services), v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ func (gui *Gui) handleServicesNextLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Services
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Services), false)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Services), false)
|
||||
|
||||
return gui.handleServiceSelect(gui.g, v)
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ func (gui *Gui) handleServicesPrevLine(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
panelState := gui.State.Panels.Services
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.State.Services), true)
|
||||
gui.changeSelectedLine(&panelState.SelectedLine, len(gui.DockerCommand.Services), true)
|
||||
|
||||
return gui.handleServiceSelect(gui.g, v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,10 @@ func NewTaskManager(log *logrus.Entry) *TaskManager {
|
|||
}
|
||||
|
||||
func (t *TaskManager) NewTask(f func(stop chan struct{})) error {
|
||||
t.Log.Warn("new task")
|
||||
|
||||
t.waitingMutex.Lock()
|
||||
defer t.waitingMutex.Unlock()
|
||||
|
||||
t.Log.Warn("locked mutex")
|
||||
|
||||
if t.currentTask != nil {
|
||||
t.Log.Warn("about to ask current task to stop")
|
||||
t.currentTask.Stop()
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +41,6 @@ func (t *TaskManager) NewTask(f func(stop chan struct{})) error {
|
|||
}
|
||||
|
||||
go func() {
|
||||
t.Log.Warn("running new task")
|
||||
f(stop)
|
||||
notifyStopped <- struct{}{}
|
||||
}()
|
||||
|
|
@ -57,6 +51,5 @@ func (t *TaskManager) NewTask(f func(stop chan struct{})) error {
|
|||
func (t *Task) Stop() {
|
||||
t.stop <- struct{}{}
|
||||
<-t.notifyStopped
|
||||
t.Log.Warn("task successfully stopped")
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue