fix(taskwarrior): parsing and convertion of times and contents
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -36,6 +37,9 @@ func (gitea *Gitea) GetComments(repo Repository) ([]Comment, error) {
|
||||
if err = decoder.Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, comment := range data {
|
||||
comment.Body = strings.ReplaceAll(comment.Body, "\r\n", "\n")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -53,6 +57,7 @@ func (gitea *Gitea) GetComment(repo Repository, id uint) (Comment, error) {
|
||||
if err = decoder.Decode(&comment); err != nil {
|
||||
return comment, err
|
||||
}
|
||||
comment.Body = strings.ReplaceAll(comment.Body, "\r\n", "\n")
|
||||
return comment, err
|
||||
}
|
||||
|
||||
|
||||
11
internal/gitw/diff.go
Normal file
11
internal/gitw/diff.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package gitw
|
||||
|
||||
import "fmt"
|
||||
|
||||
func prompt(value, theirs, mine string) string {
|
||||
// TODO: create tmp file with the corresponding contents
|
||||
// open tmp file using the $EDITOR environment variable
|
||||
// parse and return output of tmp file after $EDITOR execution has been completed
|
||||
fmt.Printf("\tPrompting for value: '%s'\n", value)
|
||||
return value
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package gitw
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/gitea"
|
||||
@@ -48,6 +49,11 @@ func (project *Project) Fetch() error {
|
||||
}
|
||||
for _, issue := range issues {
|
||||
var issue_comments []gitea.Comment
|
||||
issue_comments = append(issue_comments, gitea.Comment{
|
||||
Body: strings.ReplaceAll(issue.Body, "\r\n", "\n"),
|
||||
Created_at: issue.Created_at,
|
||||
Updated_at: issue.Updated_at,
|
||||
})
|
||||
for _, comment := range comments {
|
||||
if comment.Issue_url == issue.Html_url {
|
||||
issue_comments = append(issue_comments, comment)
|
||||
@@ -67,6 +73,7 @@ func (project *Project) merge() error {
|
||||
var tasks []taskwarrior.Task
|
||||
var task taskwarrior.Task
|
||||
var filter taskwarrior.Filter
|
||||
|
||||
// NOTE: merge tasks
|
||||
for _, issue := range project.issues {
|
||||
filter.Reset()
|
||||
@@ -104,9 +111,14 @@ func (project *Project) merge() error {
|
||||
if err := taskwarrior.UpdateTasks(tasks); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
for _, task := range tasks {
|
||||
fmt.Printf("\t%#v\n\n", task)
|
||||
}
|
||||
// TODO: reset tasks after successfully updating the issues
|
||||
tasks = nil
|
||||
}
|
||||
|
||||
tasks = nil // NOTE: reset tasks after successfully updating the issues
|
||||
|
||||
// TODO: merge milestones
|
||||
for _, milestone := range project.milestones {
|
||||
filter.Reset()
|
||||
@@ -153,6 +165,10 @@ func (project *Project) merge() error {
|
||||
}
|
||||
if !dry_run {
|
||||
return taskwarrior.UpdateTasks(tasks)
|
||||
} else {
|
||||
for _, task := range tasks {
|
||||
fmt.Printf("\t%#v\n\n", task)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -185,33 +201,65 @@ func (issue *Issue) MergeTask(task taskwarrior.Task) (taskwarrior.Task, error) {
|
||||
if issue.git_issue.Updated_at.After(last_update) {
|
||||
// there are changes we need to merge
|
||||
if taskwarrior.TaskTimeToGoTime(task.Modified).After(last_update) {
|
||||
// TODO: this means that there are local modifications which are not yet pushed
|
||||
// NOTE: this means that there are local modifications which are not yet pushed
|
||||
if task.Description != issue.git_issue.Title {
|
||||
task.Description = prompt(task.Description, issue.git_issue.Title, task.Description)
|
||||
}
|
||||
if task.Status == "completed" || issue.git_issue.State == "closed" {
|
||||
if !(task.Status == "completed" && issue.git_issue.State == "closed" || task.Status != "completed" && issue.git_issue.State != "closed") {
|
||||
task.Status = prompt(task.Status, issue.git_issue.State, task.Status)
|
||||
}
|
||||
}
|
||||
if len(task.Annotations) != len(issue.comments)+1 {
|
||||
var annotations []string
|
||||
annotations = append(annotations, issue.git_issue.Body)
|
||||
for _, annotation := range task.Annotations {
|
||||
annotations = append(annotations, annotation.Description)
|
||||
}
|
||||
var comments []string
|
||||
for _, comment := range issue.comments {
|
||||
comments = append(comments, comment.Body)
|
||||
}
|
||||
// TODO: how should the user manually enter the values?
|
||||
// TODO: provide options for theirs, mine and manual edit of the task annotations
|
||||
// annotation_joined := prompt(strings.Join(annotations, "\n\n"), strings.Join(comments, "\n\n"), strings.Join(annotations, "\n\n"))
|
||||
} else {
|
||||
for i := range issue.comments {
|
||||
// check the modification times?
|
||||
annotation := task.Annotations[i]
|
||||
comment := issue.comments[i]
|
||||
modification_time := taskwarrior.TaskTimeToGoTime(annotation.Entry)
|
||||
if comment.Updated_at.After(modification_time) {
|
||||
annotation.Description = comment.Body
|
||||
annotation.Entry = taskwarrior.GoTimeToTaskTime(comment.Updated_at)
|
||||
} else {
|
||||
annotation.Description = prompt(annotation.Description, comment.Body, annotation.Description)
|
||||
}
|
||||
task.Annotations[i] = annotation
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NOTE: there are no modifications between the last received update and the current version, hence we just accept theirs fully
|
||||
task.Description = issue.git_issue.Title
|
||||
task.Tags = issue.git_issue.Labels
|
||||
// NOTE: otherwise do not update the value
|
||||
if issue.git_issue.State == "closed" {
|
||||
// otherwise do not update the value
|
||||
task.Status = "completed"
|
||||
task.End = taskwarrior.GoTimeToTaskTime(issue.git_issue.Closed_at)
|
||||
}
|
||||
}
|
||||
task.Last_gitw_update = taskwarrior.GoTimeToTaskTime(time.Now())
|
||||
} else {
|
||||
// there are changes after the previous update here may be merge conflicts
|
||||
// TODO: implement merge conflict resolution
|
||||
}
|
||||
annotations := len(task.Annotations)
|
||||
for i, comment := range issue.comments {
|
||||
if comment.Updated_at.After(last_update) {
|
||||
if i < annotations {
|
||||
task.Annotations[i].Description = comment.Body
|
||||
task.Annotations[i].Entry = taskwarrior.GoTimeToTaskTime(comment.Updated_at)
|
||||
task.Last_gitw_update = taskwarrior.GoTimeToTaskTime(time.Now())
|
||||
} else {
|
||||
task.AppendComment(comment.Body, comment.Updated_at)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
task.Last_gitw_update = taskwarrior.GoTimeToTaskTime(time.Now().In(time.Local))
|
||||
}
|
||||
// TODO: issue values into task:
|
||||
// - is the issue more recent than the task?
|
||||
// - apply changes into task
|
||||
|
||||
@@ -59,7 +59,6 @@ func NewTask(description string, project string, git_id uint, git_type Type, tag
|
||||
}
|
||||
|
||||
func TaskTimeToGoTime(t string) time.Time {
|
||||
// TODO: apply required changes to the string for correct parsing
|
||||
splits := strings.Split(t, "T")
|
||||
if len(t) == 0 {
|
||||
return time.UnixMicro(0)
|
||||
@@ -78,6 +77,7 @@ func TaskTimeToGoTime(t string) time.Time {
|
||||
second = timestamp[2:4]
|
||||
third = timestamp[4 : len(timestamp)-1]
|
||||
timestamp = strings.Join([]string{first, second, third}, ":")
|
||||
// TODO: identify current timezone and use correct format string (works for Europe/Berlin)
|
||||
value := fmt.Sprintf("%sT%s+02:00", date, timestamp)
|
||||
result, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
@@ -88,13 +88,9 @@ func TaskTimeToGoTime(t string) time.Time {
|
||||
}
|
||||
|
||||
func GoTimeToTaskTime(t time.Time) string {
|
||||
result := t.Format(time.RFC3339)
|
||||
// TODO: apply changes to the result
|
||||
// go: 2023-10-10T19:57:22+02:00
|
||||
// task: 20231010T195722Z
|
||||
result := t.In(time.UTC).Format(time.RFC3339)
|
||||
result = strings.Replace(result, "-", "", 2)
|
||||
result = strings.Replace(result, ":", "", 2)
|
||||
result = strings.ReplaceAll(result, "+02:00", "Z")
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,18 @@
|
||||
package taskwarrior
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTimeCoversions(t *testing.T) {
|
||||
current_time := time.Now()
|
||||
task_current_time := GoTimeToTaskTime(current_time)
|
||||
go_current_time := TaskTimeToGoTime(task_current_time)
|
||||
task_current_time = GoTimeToTaskTime(go_current_time)
|
||||
current_time = TaskTimeToGoTime(task_current_time)
|
||||
|
||||
if current_time.Compare(go_current_time) != 0 {
|
||||
t.Fatalf("conversion failed: Expected: `%s` but got: `%s`", current_time.String(), go_current_time.String())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user