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/gitea/milestone.go

159 lines
5.5 KiB
Go

package gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/diff"
"gitea.yves-biener.de/yves-biener/gitwarrior/internal/taskwarrior"
)
type Milestone struct {
Id uint `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
State string `json:"state"`
Open_issues uint `json:"open_issues"`
Closed_issues uint `json:"closed_issues"`
Created_at time.Time `json:"created_at"`
Updated_at time.Time `json:"updated_at"`
Due_on time.Time `json:"due_on"`
Closed_at time.Time `json:"closed_at"`
}
func (milestone *Milestone) IntoTask(repository Repository) (task taskwarrior.Task) {
task = taskwarrior.NewTask(
milestone.Title,
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)
return
}
// TODO: implement merge for milestone tasks
func (milestone *Milestone) MergeTask(task taskwarrior.Task) taskwarrior.Task {
last_update := taskwarrior.TaskTimeToGoTime(task.Last_gitw_update)
if milestone.Updated_at.After(last_update) {
// there are changes we need to merge
if taskwarrior.TaskTimeToGoTime(task.Modified).After(last_update) {
// NOTE: this means that there are lacal modifications which are not yet pushed
if task.Description != milestone.Title {
task.Description = diff.Prompt(task.Description, milestone.Title, task.Description)
}
if task.Status == "completed" || milestone.State == "closed" {
if !(task.Status == "completed" && milestone.State == "closed" || task.Status != "completed" && milestone.State != "closed") {
task.Status = diff.Prompt(task.Status, milestone.State, task.Status)
}
}
if len(task.Annotations) < 1 {
task.AppendComment(milestone.Description, milestone.Created_at)
} else {
task.Annotations[0].Description = diff.Prompt(task.Annotations[0].Description, milestone.Description, task.Annotations[0].Description)
task.Annotations[0].Entry = taskwarrior.GoTimeToTaskTime(time.Now().In(time.Local))
}
} else {
// NOTE: there are no modifications between the last received update and the current version, hence we just accept theirs fully
task.Description = milestone.Title
if milestone.State == "closed" {
// otherwise do not update the value
task.Status = "completed"
task.End = taskwarrior.GoTimeToTaskTime(milestone.Closed_at)
}
if len(task.Annotations) == 1 {
task.Annotations[0].Description = milestone.Description
task.Annotations[0].Entry = taskwarrior.GoTimeToTaskTime(milestone.Updated_at)
} else {
task.AppendComment(milestone.Description, milestone.Updated_at)
}
}
task.Last_gitw_update = taskwarrior.GoTimeToTaskTime(time.Now().In(time.Local))
}
return task
}
func (gitea *Gitea) GetMilestones(repo Repository) ([]Milestone, error) {
url := fmt.Sprintf("%s/repos/%s/milestones?state=all", gitea.Url(), repo.Full_name)
response, err := http.Get(url)
if err != nil {
return nil, err
}
defer response.Body.Close()
var data []Milestone
decoder := json.NewDecoder(response.Body)
// NOTE: remove this if I do not want to store everything from the json result in the struct
decoder.DisallowUnknownFields() // remain if every field shall be extracted
if err = decoder.Decode(&data); err != nil {
return nil, err
}
return data, nil
}
func (gitea *Gitea) GetMilestone(repo Repository, id uint) (Milestone, error) {
url := fmt.Sprintf("%s/repos/%s/milestones/%d", gitea.Url(), repo.Full_name, id)
response, err := http.Get(url)
var milestone Milestone
if err != nil {
return milestone, err
}
defer response.Body.Close()
decoder := json.NewDecoder(response.Body)
// NOTE: remove this if I do not want to store everything from the json result in the struct
decoder.DisallowUnknownFields() // remain if every field shall be extracted
if err = decoder.Decode(&milestone); err != nil {
return milestone, err
}
return milestone, nil
}
func (gitea *Gitea) UpdateMilestone(repo Repository, milestone Milestone) error {
url := fmt.Sprintf("%s/repos/%s/milestones/%d", gitea.Url(), repo.Full_name, milestone.Id)
var payload map[string]interface{}
payload["description"] = milestone.Description
payload["due_on"] = milestone.Due_on
payload["state"] = milestone.State
payload["title"] = milestone.Title
json, err := json.Marshal(&payload)
if err != nil {
return err
}
_, err = http.NewRequest(http.MethodPatch, url, bytes.NewBuffer(json))
if err != nil {
return err
}
return nil
}
func (gitea *Gitea) NewMilestone(repo Repository, milestone Milestone) (Milestone, error) {
url := fmt.Sprintf("%s/repos/%s/milestones", gitea.Url(), repo.Full_name)
payload, err := json.Marshal(&map[string]interface{}{
"description": milestone.Description,
"due_on": milestone.Due_on,
"state": milestone.State,
"title": milestone.Title,
})
var res Milestone
if err != nil {
return res, err
}
response, err := http.Post(url, "application/json", bytes.NewBuffer(payload))
if err != nil {
return res, err
}
defer response.Body.Close()
decoder := json.NewDecoder(response.Body)
// NOTE: remove this if I do not want to stare everything from the json result in the struct
decoder.DisallowUnknownFields() // remain if every field shall be extracted
if err = decoder.Decode(&res); err != nil {
return res, err
}
return res, nil
}