add(taskwarrior): pull implementation for new tasks
This implements the pull functionality for new tasks, which are not yet in the local taskwarrior instance created. WIP for #3.
This commit is contained in:
@@ -23,11 +23,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
project := gitw.NewProject(server, repository)
|
project := gitw.NewProject(server, repository)
|
||||||
|
|
||||||
if err = project.Fetch(); err != nil {
|
fmt.Printf("Pulling changes from %s\n", repository.Full_name)
|
||||||
|
if err = project.Pull(); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
fmt.Printf("%#v\n", project)
|
|
||||||
|
|
||||||
// NOTE: this can be used to add / modify tasks
|
// NOTE: this can be used to add / modify tasks
|
||||||
// var update_tasks []taskwarrior.Task
|
// var update_tasks []taskwarrior.Task
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ type PullRequest struct {
|
|||||||
Merged_at time.Time `json:"merged_at"`
|
Merged_at time.Time `json:"merged_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IssueState string
|
||||||
|
|
||||||
|
const CLOSED IssueState = "closed"
|
||||||
|
const OPEN IssueState = "open"
|
||||||
|
|
||||||
type Issue struct {
|
type Issue struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
@@ -104,7 +109,7 @@ func (gitea *Gitea) NewIssue(repo Repository, issue Issue) (Issue, error) {
|
|||||||
payload["assignee"] = issue.Assignee
|
payload["assignee"] = issue.Assignee
|
||||||
payload["assignees"] = issue.Assignees
|
payload["assignees"] = issue.Assignees
|
||||||
payload["body"] = issue.Body
|
payload["body"] = issue.Body
|
||||||
payload["closed"] = issue.State == "closed"
|
payload["closed"] = issue.State == string(CLOSED)
|
||||||
payload["due_date"] = issue.Due_date
|
payload["due_date"] = issue.Due_date
|
||||||
payload["lables"] = issue.Labels
|
payload["lables"] = issue.Labels
|
||||||
payload["milestone"] = issue.Milestone.Title != ""
|
payload["milestone"] = issue.Milestone.Title != ""
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/taskwarrior"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Milestone struct {
|
type Milestone struct {
|
||||||
@@ -21,6 +23,11 @@ type Milestone struct {
|
|||||||
Closed_at time.Time `json:"closed_at"`
|
Closed_at time.Time `json:"closed_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: implement merge for milestone tasks
|
||||||
|
func (milestone *Milestone) Merge(task taskwarrior.Task) taskwarrior.Task {
|
||||||
|
return task
|
||||||
|
}
|
||||||
|
|
||||||
func (gitea *Gitea) GetMilestones(repo Repository) ([]Milestone, error) {
|
func (gitea *Gitea) GetMilestones(repo Repository) ([]Milestone, error) {
|
||||||
url := fmt.Sprintf("%s/repos/%s/milestones?state=all", gitea.Url(), repo.Full_name)
|
url := fmt.Sprintf("%s/repos/%s/milestones?state=all", gitea.Url(), repo.Full_name)
|
||||||
response, err := http.Get(url)
|
response, err := http.Get(url)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package gitw
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/gitea"
|
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/gitea"
|
||||||
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/taskwarrior"
|
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/taskwarrior"
|
||||||
@@ -52,38 +53,115 @@ func (project *Project) Fetch() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
project.issues = append(project.issues, Issue{
|
project.issues = append(project.issues, Issue{
|
||||||
issue: issue,
|
git_issue: issue,
|
||||||
comments: issue_comments,
|
comments: issue_comments,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: tasks should include the corresponding time's of the git related issues and milestones
|
||||||
func (project *Project) merge() error {
|
func (project *Project) merge() error {
|
||||||
// TODO: run merge to update the local taskwarrior tasks into the state of the
|
var tasks []taskwarrior.Task
|
||||||
// issues and milestones
|
var filter taskwarrior.Filter
|
||||||
|
// TODO: merge milestones
|
||||||
|
for _, milestone := range project.milestones {
|
||||||
|
filter.Reset()
|
||||||
|
filter.IncludeGitId(milestone.Id)
|
||||||
|
filter.IncludeGitType(taskwarrior.MILESTONE)
|
||||||
|
git_tasks, err := taskwarrior.GetTasks(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var task taskwarrior.Task
|
||||||
|
if len(git_tasks) > 1 {
|
||||||
|
return errors.New("Git milestone id was at least used twice in taskwarrior tasks.")
|
||||||
|
} else if len(git_tasks) == 0 {
|
||||||
|
// NOTE: ignore closed milestones which do not have a taskwarrior task
|
||||||
|
if milestone.State == string(gitea.CLOSED) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// NOTE: this milestone does not yet exist
|
||||||
|
task = taskwarrior.NewTask(
|
||||||
|
milestone.Title,
|
||||||
|
project.repository.Name,
|
||||||
|
milestone.Id,
|
||||||
|
taskwarrior.MILESTONE,
|
||||||
|
)
|
||||||
|
task.AppendComment(milestone.Description, milestone.Updated_at)
|
||||||
|
fmt.Printf("\tCreated milestone: '%s'\n", task.Description)
|
||||||
|
tasks = append(tasks, task)
|
||||||
|
} else {
|
||||||
|
// NOTE: there is exactly one git_task
|
||||||
|
task = milestone.Merge(git_tasks[0])
|
||||||
|
fmt.Printf("\tUpdated milestone: '%s'\n", task.Description)
|
||||||
|
tasks = append(tasks, task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// NOTE: merge tasks
|
||||||
|
// TODO: link milestones into tasks
|
||||||
|
for _, issue := range project.issues {
|
||||||
|
filter.Reset()
|
||||||
|
filter.IncludeGitId(issue.git_issue.Id)
|
||||||
|
filter.IncludeGitType(taskwarrior.ISSUE)
|
||||||
|
git_tasks, err := taskwarrior.GetTasks(filter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var task taskwarrior.Task
|
||||||
|
if len(git_tasks) > 1 {
|
||||||
|
return errors.New("Git issue id was at least used twice in taskwarrior tasks.")
|
||||||
|
} else if len(git_tasks) == 0 {
|
||||||
|
// NOTE: ignore closed issues which do not have a taskwarrior task
|
||||||
|
if issue.git_issue.State == string(gitea.CLOSED) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// NOTE: this task does not yet exist
|
||||||
|
task = taskwarrior.NewTask(
|
||||||
|
issue.git_issue.Title,
|
||||||
|
project.repository.Name,
|
||||||
|
issue.git_issue.Id,
|
||||||
|
taskwarrior.ISSUE,
|
||||||
|
issue.git_issue.Labels...,
|
||||||
|
)
|
||||||
|
for _, comment := range issue.comments {
|
||||||
|
task.AppendComment(comment.Body, comment.Updated_at)
|
||||||
|
}
|
||||||
|
fmt.Printf("\tCreated task: '%s'\n", task.Description)
|
||||||
|
tasks = append(tasks, task)
|
||||||
|
} else {
|
||||||
|
// NOTE: there is excactly one git_task
|
||||||
|
task = issue.merge(git_tasks[0])
|
||||||
|
fmt.Printf("\tUpdated task: '%s'\n", task.Description)
|
||||||
|
tasks = append(tasks, task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: dry-run switch
|
||||||
|
if false {
|
||||||
|
return taskwarrior.UpdateTasks(tasks)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Issue struct {
|
type Issue struct {
|
||||||
issue gitea.Issue
|
git_issue gitea.Issue
|
||||||
comments []gitea.Comment
|
comments []gitea.Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Issue) into() (taskwarrior.Task, error) {
|
func (i *Issue) into() (taskwarrior.Task, error) {
|
||||||
// TODO: identify if issue is already an existing task
|
// TODO: identify if issue is already an existing task
|
||||||
var filter taskwarrior.Filter
|
var filter taskwarrior.Filter
|
||||||
filter.IncludeGitId(i.issue.Id)
|
filter.IncludeGitId(i.git_issue.Id)
|
||||||
filter.IncludeGitType(taskwarrior.ISSUE)
|
filter.IncludeGitType(taskwarrior.ISSUE)
|
||||||
tasks, err := taskwarrior.GetTasks(filter)
|
tasks, err := taskwarrior.GetTasks(filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// this means that a task for this issue does not exist yet
|
// this means that a task for this issue does not exist yet
|
||||||
return taskwarrior.NewTask(
|
return taskwarrior.NewTask(
|
||||||
i.issue.Title,
|
i.git_issue.Title,
|
||||||
i.issue.Repository.Name,
|
i.git_issue.Repository.Name,
|
||||||
i.issue.Id,
|
i.git_issue.Id,
|
||||||
taskwarrior.ISSUE,
|
taskwarrior.ISSUE,
|
||||||
i.issue.Labels...,
|
i.git_issue.Labels...,
|
||||||
), nil
|
), nil
|
||||||
} else {
|
} else {
|
||||||
// this means that a task exists and it needs to be merged
|
// this means that a task exists and it needs to be merged
|
||||||
@@ -94,6 +172,7 @@ func (i *Issue) into() (taskwarrior.Task, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: implement merging of git issue or milestone into a taskwarrior task
|
||||||
func (i *Issue) merge(task taskwarrior.Task) taskwarrior.Task {
|
func (i *Issue) merge(task taskwarrior.Task) taskwarrior.Task {
|
||||||
// TODO: issue values into task:
|
// TODO: issue values into task:
|
||||||
// - is the issue more recent than the task?
|
// - is the issue more recent than the task?
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ type Annotation struct {
|
|||||||
Entry string `json:"entry,omitempty"`
|
Entry string `json:"entry,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (task *Task) AppendComment(description string, time time.Time) {
|
||||||
|
annotation := Annotation{
|
||||||
|
Description: description,
|
||||||
|
Entry: GoTimeToTaskTime(time),
|
||||||
|
}
|
||||||
|
task.Annotations = append(task.Annotations, annotation)
|
||||||
|
}
|
||||||
|
|
||||||
func NewTask(description string, project string, git_id uint, git_type Type, tags ...string) Task {
|
func NewTask(description string, project string, git_id uint, git_type Type, tags ...string) Task {
|
||||||
// TODO: update task struct to include the new user defined value, which shall
|
// TODO: update task struct to include the new user defined value, which shall
|
||||||
// also be provided as an argument
|
// also be provided as an argument
|
||||||
|
|||||||
Reference in New Issue
Block a user