Tear down everything
Fix config
This commit is contained in:
670
internal/taskwarrior/taskwarrior.go
Normal file
670
internal/taskwarrior/taskwarrior.go
Normal file
@@ -0,0 +1,670 @@
|
||||
// TODO: error handling
|
||||
// TODO: split combinedOutput and handle stderr differently
|
||||
// TODO: reorder functions
|
||||
package taskwarrior
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
twBinary = "task"
|
||||
)
|
||||
|
||||
var (
|
||||
nonStandardReports = map[string]struct{}{
|
||||
"burndown.daily": {},
|
||||
"burndown.monthly": {},
|
||||
"burndown.weekly": {},
|
||||
"calendar": {},
|
||||
"colors": {},
|
||||
"export": {},
|
||||
"ghistory.annual": {},
|
||||
"ghistory.monthly": {},
|
||||
"history.annual": {},
|
||||
"history.monthly": {},
|
||||
"information": {},
|
||||
"summary": {},
|
||||
"timesheet": {},
|
||||
}
|
||||
|
||||
virtualTags = map[string]struct{}{
|
||||
"ACTIVE": {},
|
||||
"ANNOTATED": {},
|
||||
"BLOCKED": {},
|
||||
"BLOCKING": {},
|
||||
"CHILD": {},
|
||||
"COMPLETED": {},
|
||||
"DELETED": {},
|
||||
"DUE": {},
|
||||
"DUETODAY": {},
|
||||
"INSTANCE": {},
|
||||
"LATEST": {},
|
||||
"MONTH": {},
|
||||
"ORPHAN": {},
|
||||
"OVERDUE": {},
|
||||
"PARENT": {},
|
||||
"PENDING": {},
|
||||
"PRIORITY": {},
|
||||
"PROJECT": {},
|
||||
"QUARTER": {},
|
||||
"READY": {},
|
||||
"SCHEDULED": {},
|
||||
"TAGGED": {},
|
||||
"TEMPLATE": {},
|
||||
"TODAY": {},
|
||||
"TOMORROW": {},
|
||||
"UDA": {},
|
||||
"UNBLOCKED": {},
|
||||
"UNTIL": {},
|
||||
"WAITING": {},
|
||||
"WEEK": {},
|
||||
"YEAR": {},
|
||||
"YESTERDAY": {},
|
||||
}
|
||||
)
|
||||
|
||||
type TaskWarrior interface {
|
||||
GetConfig() *TWConfig
|
||||
|
||||
GetActiveContext() *Context
|
||||
GetContext(context string) *Context
|
||||
GetContexts() Contexts
|
||||
SetContext(context *Context) error
|
||||
|
||||
GetProjects() []string
|
||||
|
||||
GetPriorities() []string
|
||||
|
||||
GetTags() []string
|
||||
|
||||
GetReport(report string) *Report
|
||||
GetReports() Reports
|
||||
|
||||
GetUdas() []Uda
|
||||
|
||||
GetTasks(report *Report, filter ...string) Tasks
|
||||
// AddTask(task *Task) error
|
||||
ImportTask(task *Task)
|
||||
SetTaskDone(task *Task)
|
||||
DeleteTask(task *Task)
|
||||
StartTask(task *Task)
|
||||
StopTask(task *Task)
|
||||
StopActiveTasks()
|
||||
GetInformation(task *Task) string
|
||||
AddTaskAnnotation(uuid string, annotation string)
|
||||
|
||||
Undo()
|
||||
}
|
||||
|
||||
type TaskwarriorInterop struct {
|
||||
configLocation string
|
||||
defaultArgs []string
|
||||
config *TWConfig
|
||||
reports Reports
|
||||
contexts Contexts
|
||||
ctx context.Context
|
||||
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewTaskwarriorInterop(ctx context.Context, configLocation string) *TaskwarriorInterop {
|
||||
if _, err := exec.LookPath(twBinary); err != nil {
|
||||
slog.Error("Taskwarrior not found")
|
||||
return nil
|
||||
}
|
||||
defaultArgs := []string{fmt.Sprintf("rc=%s", configLocation), "rc.verbose=nothing", "rc.dependency.confirmation=no", "rc.recurrence.confirmation=no", "rc.confirmation=no", "rc.json.array=1"}
|
||||
|
||||
ts := &TaskwarriorInterop{
|
||||
configLocation: configLocation,
|
||||
defaultArgs: defaultArgs,
|
||||
ctx: ctx,
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
ts.config = ts.extractConfig()
|
||||
if ts.config == nil {
|
||||
slog.Error("Failed to extract config - taskwarrior commands are failing. Check your taskrc file for syntax errors.")
|
||||
return nil
|
||||
}
|
||||
ts.reports = ts.extractReports()
|
||||
ts.contexts = ts.extractContexts()
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetConfig() *TWConfig {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
return ts.config
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetTasks(report *Report, filter ...string) Tasks {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
args := ts.defaultArgs
|
||||
|
||||
if report != nil && report.Context {
|
||||
for _, context := range ts.contexts {
|
||||
if context.Active && context.Name != "none" {
|
||||
args = append(args, context.ReadFilter)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if filter != nil {
|
||||
args = append(args, filter...)
|
||||
}
|
||||
|
||||
exportArgs := []string{"export"}
|
||||
if report != nil && report.Name != "" {
|
||||
exportArgs = append(exportArgs, report.Name)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(args, exportArgs...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return nil
|
||||
}
|
||||
slog.Error("Failed getting report", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
tasks := make(Tasks, 0)
|
||||
err = json.Unmarshal(output, &tasks)
|
||||
if err != nil {
|
||||
slog.Error("Failed unmarshalling tasks", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, task := range tasks {
|
||||
if len(task.Depends) > 0 {
|
||||
ids := make([]string, len(task.Depends))
|
||||
for i, dependUuid := range task.Depends {
|
||||
ids[i] = ts.getIds([]string{fmt.Sprintf("uuid:%s", dependUuid)})
|
||||
}
|
||||
|
||||
task.DependsIds = strings.Join(ids, " ")
|
||||
}
|
||||
}
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) getIds(filter []string) string {
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(append(ts.defaultArgs, filter...), "_ids")...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
slog.Error("Failed getting field", "error", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetContext(context string) *Context {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
if context == "" {
|
||||
context = "none"
|
||||
}
|
||||
|
||||
if context, ok := ts.contexts[context]; ok {
|
||||
return context
|
||||
} else {
|
||||
slog.Error("Context not found", "name", context)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetActiveContext() *Context {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
for _, context := range ts.contexts {
|
||||
if context.Active {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
return ts.contexts["none"]
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetContexts() Contexts {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
return ts.contexts
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetProjects() []string {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_projects"}...)...)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
slog.Error("Failed getting projects", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
projects := make([]string, 0)
|
||||
for _, project := range strings.Split(string(output), "\n") {
|
||||
if project != "" {
|
||||
projects = append(projects, project)
|
||||
}
|
||||
}
|
||||
|
||||
slices.Sort(projects)
|
||||
|
||||
return projects
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetPriorities() []string {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
priorities := make([]string, 0)
|
||||
for _, priority := range strings.Split(ts.config.Get("uda.priority.values"), ",") {
|
||||
if priority != "" {
|
||||
priorities = append(priorities, priority)
|
||||
}
|
||||
}
|
||||
|
||||
return priorities
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetTags() []string {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_tags"}...)...)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
slog.Error("Failed getting tags", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
tags := make([]string, 0)
|
||||
tagSet := make(map[string]struct{})
|
||||
|
||||
for _, tag := range strings.Split(string(output), "\n") {
|
||||
if _, ok := virtualTags[tag]; !ok && tag != "" {
|
||||
tags = append(tags, tag)
|
||||
tagSet[tag] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for _, tag := range strings.Split(ts.config.Get("uda.TaskwarriorInterop.tags.default"), ",") {
|
||||
if _, ok := tagSet[tag]; !ok {
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
}
|
||||
|
||||
slices.Sort(tags)
|
||||
|
||||
return tags
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetReport(report string) *Report {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
return ts.reports[report]
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetReports() Reports {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
return ts.reports
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetUdas() []Uda {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, "_udas")...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return nil
|
||||
}
|
||||
slog.Error("Failed getting UDAs", "error", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
udas := make([]Uda, 0)
|
||||
for _, uda := range strings.Split(string(output), "\n") {
|
||||
if uda != "" {
|
||||
udatype := UdaType(ts.config.Get(fmt.Sprintf("uda.%s.type", uda)))
|
||||
if udatype == "" {
|
||||
slog.Error("UDA type not found", "uda", uda)
|
||||
continue
|
||||
}
|
||||
|
||||
label := ts.config.Get(fmt.Sprintf("uda.%s.label", uda))
|
||||
values := strings.Split(ts.config.Get(fmt.Sprintf("uda.%s.values", uda)), ",")
|
||||
def := ts.config.Get(fmt.Sprintf("uda.%s.default", uda))
|
||||
|
||||
uda := Uda{
|
||||
Name: uda,
|
||||
Label: label,
|
||||
Type: udatype,
|
||||
Values: values,
|
||||
Default: def,
|
||||
}
|
||||
|
||||
udas = append(udas, uda)
|
||||
}
|
||||
}
|
||||
|
||||
return udas
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) SetContext(context *Context) error {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
if context.Name == "none" && ts.contexts["none"].Active {
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, []string{"context", context.Name}...)
|
||||
if err := cmd.Run(); err != nil {
|
||||
slog.Error("Failed setting context", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: optimize this; there should be no need to re-extract everything
|
||||
ts.config = ts.extractConfig()
|
||||
ts.contexts = ts.extractContexts()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// func (ts *TaskwarriorInterop) AddTask(task *Task) error {
|
||||
// ts.mutex.Lock()
|
||||
// defer ts.mutex.Unlock()
|
||||
|
||||
// addArgs := []string{"add"}
|
||||
|
||||
// if task.Description == "" {
|
||||
// slog.Error("Task description is required")
|
||||
// return nil
|
||||
// } else {
|
||||
// addArgs = append(addArgs, task.Description)
|
||||
// }
|
||||
// if task.Priority != "" && task.Priority != "(none)" {
|
||||
// addArgs = append(addArgs, fmt.Sprintf("priority:%s", task.Priority))
|
||||
// }
|
||||
// if task.Project != "" && task.Project != "(none)" {
|
||||
// addArgs = append(addArgs, fmt.Sprintf("project:%s", task.Project))
|
||||
// }
|
||||
// if task.Tags != nil {
|
||||
// for _, tag := range task.Tags {
|
||||
// addArgs = append(addArgs, fmt.Sprintf("+%s", tag))
|
||||
// }
|
||||
// }
|
||||
// if task.Due != "" {
|
||||
// addArgs = append(addArgs, fmt.Sprintf("due:%s", task.Due))
|
||||
// }
|
||||
|
||||
// cmd := exec.Command(twBinary, append(ts.defaultArgs, addArgs...)...)
|
||||
// err := cmd.Run()
|
||||
// if err != nil {
|
||||
// slog.Error("Failed adding task:", err)
|
||||
// }
|
||||
|
||||
// // TODO remove error?
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// TODO error handling
|
||||
func (ts *TaskwarriorInterop) ImportTask(task *Task) {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
tasks, err := json.Marshal(Tasks{task})
|
||||
if err != nil {
|
||||
slog.Error("Failed marshalling task", "error", err)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"import", "-"}...)...)
|
||||
cmd.Stdin = bytes.NewBuffer(tasks)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return
|
||||
}
|
||||
slog.Error("Failed modifying task", "error", err, "output", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) SetTaskDone(task *Task) {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"done", task.Uuid}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed setting task done", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) DeleteTask(task *Task) {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{task.Uuid, "delete"}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed deleting task", "error", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) Undo() {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"undo"}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed undoing task", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) StartTask(task *Task) {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"start", task.Uuid}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed starting task", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) StopTask(task *Task) {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"stop", task.Uuid}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed stopping task", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) StopActiveTasks() {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"+ACTIVE", "export"}...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return
|
||||
}
|
||||
slog.Error("Failed getting active tasks", "error", err, "output", string(output))
|
||||
return
|
||||
}
|
||||
|
||||
tasks := make(Tasks, 0)
|
||||
err = json.Unmarshal(output, &tasks)
|
||||
if err != nil {
|
||||
slog.Error("Failed unmarshalling active tasks", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, task := range tasks {
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"stop", task.Uuid}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed stopping task", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) GetInformation(task *Task) string {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{fmt.Sprintf("uuid:%s", task.Uuid), "information"}...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return ""
|
||||
}
|
||||
slog.Error("Failed getting task information", "error", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return string(output)
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) AddTaskAnnotation(uuid string, annotation string) {
|
||||
ts.mutex.Lock()
|
||||
defer ts.mutex.Unlock()
|
||||
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{uuid, "annotate", annotation}...)...)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
slog.Error("Failed adding annotation", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) extractConfig() *TWConfig {
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_show"}...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return nil
|
||||
}
|
||||
slog.Error("Failed getting config", "error", err, "output", string(output))
|
||||
return nil
|
||||
}
|
||||
|
||||
return NewConfig(strings.Split(string(output), "\n"))
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) extractReports() Reports {
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_config"}...)...)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
availableReports := extractReports(string(output))
|
||||
|
||||
reports := make(Reports)
|
||||
|
||||
for _, report := range availableReports {
|
||||
if _, ok := nonStandardReports[report]; ok {
|
||||
continue
|
||||
}
|
||||
reports[report] = &Report{
|
||||
Name: report,
|
||||
Description: ts.config.Get(fmt.Sprintf("report.%s.description", report)),
|
||||
Labels: strings.Split(ts.config.Get(fmt.Sprintf("report.%s.labels", report)), ","),
|
||||
Filter: ts.config.Get(fmt.Sprintf("report.%s.filter", report)),
|
||||
Sort: ts.config.Get(fmt.Sprintf("report.%s.sort", report)),
|
||||
Columns: strings.Split(ts.config.Get(fmt.Sprintf("report.%s.columns", report)), ","),
|
||||
Context: ts.config.Get(fmt.Sprintf("report.%s.context", report)) == "1",
|
||||
}
|
||||
}
|
||||
|
||||
return reports
|
||||
}
|
||||
|
||||
func extractReports(config string) []string {
|
||||
re := regexp.MustCompile(`report\.([^.]+)\.[^.]+`)
|
||||
matches := re.FindAllStringSubmatch(config, -1)
|
||||
uniques := make(map[string]struct{})
|
||||
for _, match := range matches {
|
||||
uniques[match[1]] = struct{}{}
|
||||
}
|
||||
|
||||
var reports []string
|
||||
for part := range uniques {
|
||||
reports = append(reports, part)
|
||||
}
|
||||
|
||||
slices.Sort(reports)
|
||||
return reports
|
||||
}
|
||||
|
||||
func (ts *TaskwarriorInterop) extractContexts() Contexts {
|
||||
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_context"}...)...)
|
||||
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if ts.ctx.Err() == context.Canceled {
|
||||
return nil
|
||||
}
|
||||
slog.Error("Failed getting contexts", "error", err, "output", string(output))
|
||||
return nil
|
||||
}
|
||||
|
||||
activeContext := ts.config.Get("context")
|
||||
if activeContext == "" {
|
||||
activeContext = "none"
|
||||
}
|
||||
|
||||
contexts := make(Contexts)
|
||||
contexts["none"] = &Context{
|
||||
Name: "none",
|
||||
Active: activeContext == "none",
|
||||
ReadFilter: "",
|
||||
WriteFilter: "",
|
||||
}
|
||||
for _, context := range strings.Split(string(output), "\n") {
|
||||
if context == "" {
|
||||
continue
|
||||
}
|
||||
contexts[context] = &Context{
|
||||
Name: context,
|
||||
Active: activeContext == context,
|
||||
ReadFilter: ts.config.Get(fmt.Sprintf("context.%s.read", context)),
|
||||
WriteFilter: ts.config.Get(fmt.Sprintf("context.%s.write", context)),
|
||||
}
|
||||
}
|
||||
|
||||
return contexts
|
||||
}
|
||||
Reference in New Issue
Block a user