Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 48a43dbc98 | |||
| 078c6d8bd5 | |||
| 12de0f1b6c | |||
| 10aabc8c0a | |||
| 5325c18c4e | |||
| be1dd05d9b |
85
README.md
85
README.md
@@ -1,91 +1,86 @@
|
|||||||
# GOTASK
|
# GOTASK
|
||||||
|
|
||||||
Tiny project aiming at creating a CLI task tracker in Golang
|
Tiny project aiming to create a CLI task tracker in Golang
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
1. Practice Golang
|
1. Practice Golang
|
||||||
1. Keep track of tasks
|
1. Keep track of tasks
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
1. ~~Add~~
|
|
||||||
2. ~~List all~~
|
|
||||||
3. Progress
|
|
||||||
4. Regress
|
|
||||||
5. List by
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
### Add tasks
|
### Add tasks
|
||||||
```console
|
```console
|
||||||
[user@host]$ gotask add "Publish code"
|
[user@host]$ gotask-cli add "Publish code"
|
||||||
New task "Publish code" added to do @ id=4
|
New task "Publish code" added to do @ id=4
|
||||||
```
|
```
|
||||||
|
|
||||||
### List all tasks
|
### List all tasks
|
||||||
```console
|
```console
|
||||||
[user@host]$ gotask list
|
[user@host]$ gotask-cli list
|
||||||
+---------------------------------------------------------------------+
|
+----+--------------+--------+---------------------+---------+
|
||||||
|id| Description | Status | Created | Updated |
|
| ID | DESCRIPTION | STATUS | CREATED | UPDATED |
|
||||||
|--|--------------|-------------|------------------|------------------|
|
+----+--------------+--------+---------------------+---------+
|
||||||
| 1| Update doc | todo | 01-03-2026 09:23 | | # Never updated
|
| 1 | Update doc | todo | 2026-04-03 22:34:40 | |
|
||||||
| 2| Write code | doing | 04-03-2026 10:13 | 05-03-2026 17:45 | # Set in progress at UpdateAt
|
| 2 | Write code | todo | 2026-04-03 22:38:26 | |
|
||||||
| 3| Write tests | done | 05-03-2026 11:34 | 01-04-2026 19:43 | # Done at UpdateAt
|
| 3 | Write tests | todo | 2026-04-03 22:38:45 | |
|
||||||
| 4| Publish code | todo | 01-04-2026 09:13 | |
|
| 4 | Publish code | todo | 2026-04-03 22:38:56 | |
|
||||||
+---------------------------------------------------------------------+
|
+----+--------------+--------+---------------------+---------+
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mark progress
|
### Mark progress
|
||||||
```console
|
```console
|
||||||
[user@host]$ gotask progress 4
|
[user@host]$ gotask-cli progress 4
|
||||||
[todo] task "Publish code" progress to [doing]
|
[todo] task "Publish code" progress to [doing]
|
||||||
```
|
```
|
||||||
|
|
||||||
### List tasks by status
|
### List tasks by status
|
||||||
```console
|
```console
|
||||||
[user@host]$ gotask list doing
|
[user@host]$ gotask-cli list doing
|
||||||
+---------------------------------------------------------------------+
|
+----+--------------+--------+---------------------+---------------------+
|
||||||
|id| Description | Status | Created | Updated |
|
| ID | DESCRIPTION | STATUS | CREATED | UPDATED |
|
||||||
|--|--------------|-------------|------------------|------------------|
|
+----+--------------+--------+---------------------+---------------------+
|
||||||
| 2| Write code | doing | 04-03-2026 10:13 | 05-03-2026 17:45 |
|
| 4 | Publish code | doing | 2026-04-03 22:38:56 | 2026-04-03 22:44:36 |
|
||||||
| 4| Publish code | doing | 01-04-2026 09:13 | 01-04-2026 10:30 |
|
+----+--------------+--------+---------------------+---------------------+
|
||||||
+---------------------------------------------------------------------+
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mark regress
|
### Mark regress
|
||||||
```console
|
```console
|
||||||
[user@host]$ gotask regress 4
|
[user@host]$ gotask-cli regress 4
|
||||||
[doing] task "Publish code" regress to [todo]
|
[doing] task "Publish code" regress to [todo]
|
||||||
```
|
```
|
||||||
|
|
||||||
### List task by id
|
|
||||||
```console
|
|
||||||
[user@host]$ gotask list 4
|
|
||||||
+---------------------------------------------------------------------+
|
|
||||||
|id| Description | Status | Created | Updated |
|
|
||||||
|--|--------------|-------------|------------------|------------------|
|
|
||||||
| 4| Publish code | todo | 01-04-2026 09:13 | 01-04-2026 10:33 |
|
|
||||||
+---------------------------------------------------------------------+
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Storing data
|
## Storing data
|
||||||
For convenience reasons, the data will be stored in a JSON file with the following structure.
|
For convenience reasons, the data will be stored in a JSON file with the following structure.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id": 1,
|
"Id": 1,
|
||||||
"Description": "Update doc",
|
"Description": "Update doc",
|
||||||
"Status": 0,
|
"Status": 0,
|
||||||
"Created": 1772353380,
|
"Created": 1775248480,
|
||||||
"UpdatedAt": -1
|
"Updated": -1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"Id": 2,
|
||||||
"Description": "Write code",
|
"Description": "Write code",
|
||||||
"Status": 1,
|
"Status": 0,
|
||||||
"Created": 1772615580,
|
"Created": 1775248706,
|
||||||
"UpdatedAt": 1772729100
|
"Updated": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3,
|
||||||
|
"Description": "Write tests",
|
||||||
|
"Status": 0,
|
||||||
|
"Created": 1775248725,
|
||||||
|
"Updated": -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4,
|
||||||
|
"Description": "Publish code",
|
||||||
|
"Status": 0,
|
||||||
|
"Created": 1775248736,
|
||||||
|
"Updated": 1775249113
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|||||||
20
commands/add_task.go
Normal file
20
commands/add_task.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gotask-cli/models"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddTask(desc string, backlog []models.Task) []models.Task {
|
||||||
|
newtask := models.Task{
|
||||||
|
Id: uint(len(backlog)) + 1,
|
||||||
|
Description: desc,
|
||||||
|
Status: 0,
|
||||||
|
Created: time.Now().Unix(),
|
||||||
|
Updated: -1}
|
||||||
|
|
||||||
|
fmt.Printf("New task \"%s\" added to do @ id=%d", newtask.Description, newtask.Id)
|
||||||
|
backlog = append(backlog, newtask)
|
||||||
|
return backlog
|
||||||
|
}
|
||||||
9
commands/help.go
Normal file
9
commands/help.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Help() {
|
||||||
|
fmt.Println("Hang in there, will do the help stuff some day !")
|
||||||
|
}
|
||||||
10
commands/list_tasks.go
Normal file
10
commands/list_tasks.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gotask-cli/models"
|
||||||
|
"gotask-cli/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListTasks(backlog []models.Task) {
|
||||||
|
utils.PrintTasksAsATable(backlog)
|
||||||
|
}
|
||||||
28
commands/list_tasks_by.go
Normal file
28
commands/list_tasks_by.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gotask-cli/models"
|
||||||
|
"gotask-cli/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListTasksBy(status string, backlog []models.Task) {
|
||||||
|
var backlogToDisplay []models.Task
|
||||||
|
var statusID models.Status
|
||||||
|
for i, v := range models.StatusName {
|
||||||
|
if v == status {
|
||||||
|
statusID = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range backlog {
|
||||||
|
if v.Status == models.Status(statusID) {
|
||||||
|
backlogToDisplay = append(backlogToDisplay, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(backlogToDisplay) > 0 {
|
||||||
|
utils.PrintTasksAsATable(backlogToDisplay)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No tasks with the status [%s]", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
commands/progress_task.go
Normal file
18
commands/progress_task.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gotask-cli/models"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ProgressTask(id uint, backlog []models.Task) []models.Task {
|
||||||
|
if backlog[id].Status >= 0 && backlog[id].Status < 2 {
|
||||||
|
backlog[id].Status++
|
||||||
|
backlog[id].Updated = time.Now().Unix()
|
||||||
|
fmt.Printf("[%s] task \"%s\" progress to [%s]", models.StatusName[backlog[id].Status-1], backlog[id].Description, models.StatusName[backlog[id].Status])
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Can't progress task %s", backlog[id].Description)
|
||||||
|
}
|
||||||
|
return backlog
|
||||||
|
}
|
||||||
18
commands/regress_task.go
Normal file
18
commands/regress_task.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gotask-cli/models"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegressTask(id uint, backlog []models.Task) []models.Task {
|
||||||
|
if backlog[id].Status >= 1 && backlog[id].Status <= 2 {
|
||||||
|
backlog[id].Status--
|
||||||
|
backlog[id].Updated = time.Now().Unix()
|
||||||
|
fmt.Printf("[%s] task \"%s\" regress to [%s]", models.StatusName[backlog[id].Status+1], backlog[id].Description, models.StatusName[backlog[id].Status])
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Can't regress task %s", backlog[id].Description)
|
||||||
|
}
|
||||||
|
return backlog
|
||||||
|
}
|
||||||
168
gotask-cli.go
168
gotask-cli.go
@@ -1,143 +1,77 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"strconv"
|
||||||
|
|
||||||
"github.com/jedib0t/go-pretty/v6/table"
|
"gotask-cli/commands"
|
||||||
)
|
"gotask-cli/utils"
|
||||||
|
|
||||||
type Status int
|
|
||||||
|
|
||||||
const (
|
|
||||||
todo Status = iota
|
|
||||||
doing
|
|
||||||
done
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const path string = "./tasks.json"
|
const path string = "./tasks.json"
|
||||||
const tempPath string = "./tasks.save"
|
|
||||||
|
|
||||||
var statusName = map[Status]string{
|
|
||||||
todo: "todo",
|
|
||||||
doing: "doing",
|
|
||||||
done: "done",
|
|
||||||
}
|
|
||||||
|
|
||||||
type task struct {
|
|
||||||
Id uint
|
|
||||||
Description string
|
|
||||||
Status Status
|
|
||||||
Created int64
|
|
||||||
Updated int64
|
|
||||||
}
|
|
||||||
|
|
||||||
var backlog []task
|
|
||||||
|
|
||||||
func initBacklog() {
|
|
||||||
if _, err := os.Stat(path); err == nil {
|
|
||||||
loadBacklog()
|
|
||||||
|
|
||||||
} else if errors.Is(err, os.ErrNotExist) {
|
|
||||||
// path does not exist
|
|
||||||
f, err := os.Create(path)
|
|
||||||
check(err)
|
|
||||||
defer f.Close()
|
|
||||||
loadBacklog()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
check(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadBacklog() {
|
|
||||||
content, err := os.ReadFile(path)
|
|
||||||
check(err)
|
|
||||||
err = json.Unmarshal([]byte(content), &backlog)
|
|
||||||
check(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func check(e error) {
|
|
||||||
if e != nil {
|
|
||||||
panic(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printTasksAsATable(tasks []task) {
|
|
||||||
t := table.NewWriter()
|
|
||||||
t.SetOutputMirror(os.Stdout)
|
|
||||||
t.AppendHeader(table.Row{"Id", "Description", "Status", "Created", "Updated"})
|
|
||||||
for _, v := range tasks {
|
|
||||||
var updated string
|
|
||||||
if v.Updated == -1 {
|
|
||||||
updated = ""
|
|
||||||
} else {
|
|
||||||
updated = time.Unix(v.Updated, 0).Format(time.DateTime)
|
|
||||||
}
|
|
||||||
t.AppendRow([]interface{}{
|
|
||||||
v.Id,
|
|
||||||
v.Description,
|
|
||||||
statusName[v.Status],
|
|
||||||
time.Unix(v.Created, 0).Format(time.DateTime),
|
|
||||||
updated,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
t.Render()
|
|
||||||
}
|
|
||||||
|
|
||||||
func addTask(desc string) {
|
|
||||||
newtask := task{
|
|
||||||
Id: uint(len(backlog)) + 1,
|
|
||||||
Description: desc,
|
|
||||||
Status: 0,
|
|
||||||
Created: time.Now().Unix(),
|
|
||||||
Updated: -1}
|
|
||||||
|
|
||||||
fmt.Printf("New task \"%s\" added to do @ id=%d", newtask.Description, newtask.Id)
|
|
||||||
backlog = append(backlog, newtask)
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveBacklog() {
|
|
||||||
if _, err := os.Stat(tempPath); err == nil {
|
|
||||||
err = os.Remove(tempPath)
|
|
||||||
} else if errors.Is(err, os.ErrNotExist) {
|
|
||||||
} else {
|
|
||||||
check(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
f, err := os.Create(tempPath)
|
|
||||||
check(err)
|
|
||||||
defer f.Close()
|
|
||||||
backlogJSON, _ := json.MarshalIndent(backlog, "", "\t")
|
|
||||||
f.Write(backlogJSON)
|
|
||||||
|
|
||||||
err = os.Rename(tempPath, path)
|
|
||||||
check(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
initBacklog()
|
backlog := utils.InitBacklog(path)
|
||||||
if len(os.Args[1:]) >= 1 {
|
if len(os.Args[1:]) >= 1 {
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
case "help":
|
case "help":
|
||||||
fmt.Println("S.O.S!")
|
commands.Help()
|
||||||
case "add":
|
case "add":
|
||||||
if len(os.Args[1:]) >= 2 {
|
if len(os.Args[1:]) == 2 {
|
||||||
addTask(os.Args[2])
|
backlog = commands.AddTask(os.Args[2], backlog)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Missing argument")
|
fmt.Println("Missing argument")
|
||||||
|
commands.Help()
|
||||||
}
|
}
|
||||||
case "list":
|
case "list":
|
||||||
printTasksAsATable(backlog)
|
switch len(os.Args[1:]) {
|
||||||
|
case 1:
|
||||||
|
commands.ListTasks(backlog)
|
||||||
|
case 2:
|
||||||
|
switch os.Args[2] {
|
||||||
|
case "todo", "doing", "done":
|
||||||
|
commands.ListTasksBy(os.Args[2], backlog)
|
||||||
|
default:
|
||||||
|
fmt.Printf("Unknown status %s", os.Args[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Println("Too many arguments !")
|
||||||
|
}
|
||||||
|
case "progress":
|
||||||
|
if len(os.Args[1:]) == 2 {
|
||||||
|
id, err := strconv.ParseUint(os.Args[2], 10, 32)
|
||||||
|
utils.Check(err)
|
||||||
|
if id > 0 && id <= uint64(len(backlog)) {
|
||||||
|
commands.ProgressTask(uint(id)-1, backlog)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No task found with id=%d, try list to get id", id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Missing argument")
|
||||||
|
commands.Help()
|
||||||
|
}
|
||||||
|
case "regress":
|
||||||
|
if len(os.Args[1:]) == 2 {
|
||||||
|
id, err := strconv.ParseUint(os.Args[2], 10, 32)
|
||||||
|
utils.Check(err)
|
||||||
|
if id > 0 && id <= uint64(len(backlog)) {
|
||||||
|
commands.RegressTask(uint(id)-1, backlog)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("No task found with id=%d, try list to get id", id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Missing argument")
|
||||||
|
commands.Help()
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fmt.Println("NO !")
|
fmt.Println("NO !")
|
||||||
}
|
}
|
||||||
saveBacklog()
|
utils.SaveBacklog(backlog, path)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Missing argument")
|
fmt.Println("Missing argument")
|
||||||
|
commands.Help()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
models/task.go
Normal file
23
models/task.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type Status int
|
||||||
|
|
||||||
|
const (
|
||||||
|
todo Status = iota
|
||||||
|
doing
|
||||||
|
done
|
||||||
|
)
|
||||||
|
|
||||||
|
var StatusName = map[Status]string{
|
||||||
|
todo: "todo",
|
||||||
|
doing: "doing",
|
||||||
|
done: "done",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Task struct {
|
||||||
|
Id uint
|
||||||
|
Description string
|
||||||
|
Status Status
|
||||||
|
Created int64
|
||||||
|
Updated int64
|
||||||
|
}
|
||||||
7
utils/err_checker.go
Normal file
7
utils/err_checker.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
func Check(e error) {
|
||||||
|
if e != nil {
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
33
utils/read_backlog.go
Normal file
33
utils/read_backlog.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"gotask-cli/models"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitBacklog(path string) []models.Task {
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
|
||||||
|
} else if errors.Is(err, os.ErrNotExist) {
|
||||||
|
f, err := os.Create(path)
|
||||||
|
Check(err)
|
||||||
|
defer f.Close()
|
||||||
|
f.Write([]byte("[]"))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Check(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return loadBacklog(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadBacklog(path string) []models.Task {
|
||||||
|
var backlog []models.Task
|
||||||
|
content, err := os.ReadFile(path)
|
||||||
|
Check(err)
|
||||||
|
err = json.Unmarshal([]byte(content), &backlog)
|
||||||
|
Check(err)
|
||||||
|
return backlog
|
||||||
|
}
|
||||||
31
utils/table_render.go
Normal file
31
utils/table_render.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gotask-cli/models"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jedib0t/go-pretty/v6/table"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrintTasksAsATable(tasks []models.Task) {
|
||||||
|
t := table.NewWriter()
|
||||||
|
t.SetOutputMirror(os.Stdout)
|
||||||
|
t.AppendHeader(table.Row{"Id", "Description", "Status", "Created", "Updated"})
|
||||||
|
for _, v := range tasks {
|
||||||
|
var updated string
|
||||||
|
if v.Updated == -1 {
|
||||||
|
updated = ""
|
||||||
|
} else {
|
||||||
|
updated = time.Unix(v.Updated, 0).Format(time.DateTime)
|
||||||
|
}
|
||||||
|
t.AppendRow([]interface{}{
|
||||||
|
v.Id,
|
||||||
|
v.Description,
|
||||||
|
models.StatusName[v.Status],
|
||||||
|
time.Unix(v.Created, 0).Format(time.DateTime),
|
||||||
|
updated,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
t.Render()
|
||||||
|
}
|
||||||
29
utils/write_backlog.go
Normal file
29
utils/write_backlog.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gotask-cli/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
const tempPath string = "./tasks.save"
|
||||||
|
|
||||||
|
func SaveBacklog(backlog []models.Task, path string) {
|
||||||
|
if _, err := os.Stat(tempPath); err == nil {
|
||||||
|
err = os.Remove(tempPath)
|
||||||
|
} else if errors.Is(err, os.ErrNotExist) {
|
||||||
|
} else {
|
||||||
|
Check(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
f, err := os.Create(tempPath)
|
||||||
|
Check(err)
|
||||||
|
defer f.Close()
|
||||||
|
backlogJSON, _ := json.MarshalIndent(backlog, "", "\t")
|
||||||
|
f.Write(backlogJSON)
|
||||||
|
|
||||||
|
err = os.Rename(tempPath, path)
|
||||||
|
Check(err)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user