1//
2// Copyright 2017, Arkbriar
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17package gitlab
18
19import (
20	"fmt"
21)
22
23// IssueLinksService handles communication with the issue relations related methods
24// of the GitLab API.
25//
26// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html
27type IssueLinksService struct {
28	client *Client
29}
30
31// IssueLink represents a two-way relation between two issues.
32//
33// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html
34type IssueLink struct {
35	SourceIssue *Issue `json:"source_issue"`
36	TargetIssue *Issue `json:"target_issue"`
37}
38
39// ListIssueRelations gets a list of related issues of a given issue,
40// sorted by the relationship creation datetime (ascending).
41//
42// Issues will be filtered according to the user authorizations.
43//
44// GitLab API docs:
45// https://docs.gitlab.com/ee/api/issue_links.html#list-issue-relations
46func (s *IssueLinksService) ListIssueRelations(pid interface{}, issueIID int, options ...OptionFunc) ([]*Issue, *Response, error) {
47	project, err := parseID(pid)
48	if err != nil {
49		return nil, nil, err
50	}
51	u := fmt.Sprintf("projects/%s/issues/%d/links", pathEscape(project), issueIID)
52
53	req, err := s.client.NewRequest("GET", u, nil, options)
54	if err != nil {
55		return nil, nil, err
56	}
57
58	var is []*Issue
59	resp, err := s.client.Do(req, &is)
60	if err != nil {
61		return nil, resp, err
62	}
63
64	return is, resp, err
65}
66
67// CreateIssueLinkOptions represents the available CreateIssueLink() options.
68//
69// GitLab API docs: https://docs.gitlab.com/ee/api/issue_links.html
70type CreateIssueLinkOptions struct {
71	TargetProjectID *string `json:"target_project_id"`
72	TargetIssueIID  *string `json:"target_issue_iid"`
73}
74
75// CreateIssueLink creates a two-way relation between two issues.
76// User must be allowed to update both issues in order to succeed.
77//
78// GitLab API docs:
79// https://docs.gitlab.com/ee/api/issue_links.html#create-an-issue-link
80func (s *IssueLinksService) CreateIssueLink(pid interface{}, issueIID int, opt *CreateIssueLinkOptions, options ...OptionFunc) (*IssueLink, *Response, error) {
81	project, err := parseID(pid)
82	if err != nil {
83		return nil, nil, err
84	}
85	u := fmt.Sprintf("projects/%s/issues/%d/links", pathEscape(project), issueIID)
86
87	req, err := s.client.NewRequest("POST", u, opt, options)
88	if err != nil {
89		return nil, nil, err
90	}
91
92	i := new(IssueLink)
93	resp, err := s.client.Do(req, &i)
94	if err != nil {
95		return nil, resp, err
96	}
97
98	return i, resp, err
99}
100
101// DeleteIssueLink deletes an issue link, thus removes the two-way relationship.
102//
103// GitLab API docs:
104// https://docs.gitlab.com/ee/api/issue_links.html#delete-an-issue-link
105func (s *IssueLinksService) DeleteIssueLink(pid interface{}, issueIID, issueLinkID int, options ...OptionFunc) (*IssueLink, *Response, error) {
106	project, err := parseID(pid)
107	if err != nil {
108		return nil, nil, err
109	}
110	u := fmt.Sprintf("projects/%s/issues/%d/links/%d",
111		pathEscape(project),
112		issueIID,
113		issueLinkID)
114
115	req, err := s.client.NewRequest("DELETE", u, nil, options)
116	if err != nil {
117		return nil, nil, err
118	}
119
120	i := new(IssueLink)
121	resp, err := s.client.Do(req, &i)
122	if err != nil {
123		return nil, resp, err
124	}
125
126	return i, resp, err
127}
128