This repository has been archived on 2025-10-30. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
gitwarrior/internal/gitw/project.go

191 lines
5.3 KiB
Go

package gitw
import (
"errors"
"fmt"
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/gitea"
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/taskwarrior"
)
type Project struct {
server gitea.Gitea
repository gitea.Repository
issues []Issue
milestones []gitea.Milestone
}
func NewProject(server gitea.Gitea, repository gitea.Repository) Project {
return Project{
server: server,
repository: repository,
}
}
func (project *Project) Pull() error {
if err := project.Fetch(); err != nil {
return err
}
if err := project.merge(); err != nil {
return err
}
return nil
}
func (project *Project) Fetch() error {
comments, err := project.server.GetComments(project.repository)
if err != nil {
return err
}
issues, err := project.server.GetIssues(project.repository)
if err != nil {
return err
}
project.milestones, err = project.server.GetMilestones(project.repository)
if err != nil {
return err
}
for _, issue := range issues {
var issue_comments []gitea.Comment
for _, comment := range comments {
if comment.Issue_url == issue.Html_url {
issue_comments = append(issue_comments, comment)
}
}
project.issues = append(project.issues, Issue{
git_issue: issue,
comments: issue_comments,
})
}
return nil
}
// TODO: tasks should include the corresponding time's of the git related issues and milestones
func (project *Project) merge() error {
var tasks []taskwarrior.Task
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.Due = taskwarrior.GoTimeToTaskTime(milestone.Due_on)
task.Entry = taskwarrior.GoTimeToTaskTime(milestone.Created_at)
task.Modified = taskwarrior.GoTimeToTaskTime(milestone.Updated_at)
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...,
)
task.Entry = taskwarrior.GoTimeToTaskTime(issue.git_issue.Created_at)
task.Modified = taskwarrior.GoTimeToTaskTime(issue.git_issue.Updated_at)
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
}
type Issue struct {
git_issue gitea.Issue
comments []gitea.Comment
}
func (i *Issue) into() (taskwarrior.Task, error) {
// TODO: identify if issue is already an existing task
var filter taskwarrior.Filter
filter.IncludeGitId(i.git_issue.Id)
filter.IncludeGitType(taskwarrior.ISSUE)
tasks, err := taskwarrior.GetTasks(filter)
if err != nil {
// this means that a task for this issue does not exist yet
return taskwarrior.NewTask(
i.git_issue.Title,
i.git_issue.Repository.Name,
i.git_issue.Id,
taskwarrior.ISSUE,
i.git_issue.Labels...,
), nil
} else {
// this means that a task exists and it needs to be merged
if len(tasks) != 1 {
return taskwarrior.Task{}, errors.New("Did not find exactly one task for a given issue.Id")
}
return i.merge(tasks[0]), nil
}
}
// TODO: implement merging of git issue or milestone into a taskwarrior task
func (i *Issue) merge(task taskwarrior.Task) taskwarrior.Task {
// TODO: issue values into task:
// - is the issue more recent than the task?
// - apply changes into task
// - in case of merge conflicts ask user for corresponding action:
// 1. use theirs
// 2. use mine
// 3. use provided value
return task
}