gitea

Зеркало из https://github.com/go-gitea/gitea
Форк
0
/
codecommit.go 
269 строк · 7.4 Кб
1
// Copyright 2024 The Gitea Authors. All rights reserved.
2
// SPDX-License-Identifier: MIT
3

4
package migrations
5

6
import (
7
	"context"
8
	"fmt"
9
	"net/url"
10
	"strconv"
11
	"strings"
12

13
	git_module "code.gitea.io/gitea/modules/git"
14
	"code.gitea.io/gitea/modules/log"
15
	base "code.gitea.io/gitea/modules/migration"
16
	"code.gitea.io/gitea/modules/structs"
17

18
	"github.com/aws/aws-sdk-go-v2/credentials"
19
	"github.com/aws/aws-sdk-go-v2/service/codecommit"
20
	"github.com/aws/aws-sdk-go-v2/service/codecommit/types"
21
	"github.com/aws/aws-sdk-go/aws"
22
)
23

24
var (
25
	_ base.Downloader        = &CodeCommitDownloader{}
26
	_ base.DownloaderFactory = &CodeCommitDownloaderFactory{}
27
)
28

29
func init() {
30
	RegisterDownloaderFactory(&CodeCommitDownloaderFactory{})
31
}
32

33
// CodeCommitDownloaderFactory defines a codecommit downloader factory
34
type CodeCommitDownloaderFactory struct{}
35

36
// New returns a Downloader related to this factory according MigrateOptions
37
func (c *CodeCommitDownloaderFactory) New(ctx context.Context, opts base.MigrateOptions) (base.Downloader, error) {
38
	u, err := url.Parse(opts.CloneAddr)
39
	if err != nil {
40
		return nil, err
41
	}
42

43
	hostElems := strings.Split(u.Host, ".")
44
	if len(hostElems) != 4 {
45
		return nil, fmt.Errorf("cannot get the region from clone URL")
46
	}
47
	region := hostElems[1]
48

49
	pathElems := strings.Split(u.Path, "/")
50
	if len(pathElems) == 0 {
51
		return nil, fmt.Errorf("cannot get the repo name from clone URL")
52
	}
53
	repoName := pathElems[len(pathElems)-1]
54

55
	baseURL := u.Scheme + "://" + u.Host
56

57
	return NewCodeCommitDownloader(ctx, repoName, baseURL, opts.AWSAccessKeyID, opts.AWSSecretAccessKey, region), nil
58
}
59

60
// GitServiceType returns the type of git service
61
func (c *CodeCommitDownloaderFactory) GitServiceType() structs.GitServiceType {
62
	return structs.CodeCommitService
63
}
64

65
func NewCodeCommitDownloader(ctx context.Context, repoName, baseURL, accessKeyID, secretAccessKey, region string) *CodeCommitDownloader {
66
	downloader := CodeCommitDownloader{
67
		ctx:      ctx,
68
		repoName: repoName,
69
		baseURL:  baseURL,
70
		codeCommitClient: codecommit.New(codecommit.Options{
71
			Credentials: credentials.NewStaticCredentialsProvider(accessKeyID, secretAccessKey, ""),
72
			Region:      region,
73
		}),
74
	}
75

76
	return &downloader
77
}
78

79
// CodeCommitDownloader implements a downloader for AWS CodeCommit
80
type CodeCommitDownloader struct {
81
	base.NullDownloader
82
	ctx               context.Context
83
	codeCommitClient  *codecommit.Client
84
	repoName          string
85
	baseURL           string
86
	allPullRequestIDs []string
87
}
88

89
// SetContext set context
90
func (c *CodeCommitDownloader) SetContext(ctx context.Context) {
91
	c.ctx = ctx
92
}
93

94
// GetRepoInfo returns a repository information
95
func (c *CodeCommitDownloader) GetRepoInfo() (*base.Repository, error) {
96
	output, err := c.codeCommitClient.GetRepository(c.ctx, &codecommit.GetRepositoryInput{
97
		RepositoryName: aws.String(c.repoName),
98
	})
99
	if err != nil {
100
		return nil, err
101
	}
102
	repoMeta := output.RepositoryMetadata
103

104
	repo := &base.Repository{
105
		Name:      *repoMeta.RepositoryName,
106
		Owner:     *repoMeta.AccountId,
107
		IsPrivate: true, // CodeCommit repos are always private
108
		CloneURL:  *repoMeta.CloneUrlHttp,
109
	}
110
	if repoMeta.DefaultBranch != nil {
111
		repo.DefaultBranch = *repoMeta.DefaultBranch
112
	}
113
	if repoMeta.RepositoryDescription != nil {
114
		repo.DefaultBranch = *repoMeta.RepositoryDescription
115
	}
116
	return repo, nil
117
}
118

119
// GetComments returns comments of an issue or PR
120
func (c *CodeCommitDownloader) GetComments(commentable base.Commentable) ([]*base.Comment, bool, error) {
121
	var (
122
		nextToken *string
123
		comments  []*base.Comment
124
	)
125

126
	for {
127
		resp, err := c.codeCommitClient.GetCommentsForPullRequest(c.ctx, &codecommit.GetCommentsForPullRequestInput{
128
			NextToken:     nextToken,
129
			PullRequestId: aws.String(strconv.FormatInt(commentable.GetForeignIndex(), 10)),
130
		})
131
		if err != nil {
132
			return nil, false, err
133
		}
134

135
		for _, prComment := range resp.CommentsForPullRequestData {
136
			for _, ccComment := range prComment.Comments {
137
				comment := &base.Comment{
138
					IssueIndex: commentable.GetForeignIndex(),
139
					PosterName: c.getUsernameFromARN(*ccComment.AuthorArn),
140
					Content:    *ccComment.Content,
141
					Created:    *ccComment.CreationDate,
142
					Updated:    *ccComment.LastModifiedDate,
143
				}
144
				comments = append(comments, comment)
145
			}
146
		}
147

148
		nextToken = resp.NextToken
149
		if nextToken == nil {
150
			break
151
		}
152
	}
153

154
	return comments, true, nil
155
}
156

157
// GetPullRequests returns pull requests according page and perPage
158
func (c *CodeCommitDownloader) GetPullRequests(page, perPage int) ([]*base.PullRequest, bool, error) {
159
	allPullRequestIDs, err := c.getAllPullRequestIDs()
160
	if err != nil {
161
		return nil, false, err
162
	}
163

164
	startIndex := (page - 1) * perPage
165
	endIndex := page * perPage
166
	if endIndex > len(allPullRequestIDs) {
167
		endIndex = len(allPullRequestIDs)
168
	}
169
	batch := allPullRequestIDs[startIndex:endIndex]
170

171
	prs := make([]*base.PullRequest, 0, len(batch))
172
	for _, id := range batch {
173
		output, err := c.codeCommitClient.GetPullRequest(c.ctx, &codecommit.GetPullRequestInput{
174
			PullRequestId: aws.String(id),
175
		})
176
		if err != nil {
177
			return nil, false, err
178
		}
179
		orig := output.PullRequest
180
		number, err := strconv.ParseInt(*orig.PullRequestId, 10, 64)
181
		if err != nil {
182
			log.Error("CodeCommit pull request id is not a number: %s", *orig.PullRequestId)
183
			continue
184
		}
185
		if len(orig.PullRequestTargets) == 0 {
186
			log.Error("CodeCommit pull request does not contain targets", *orig.PullRequestId)
187
			continue
188
		}
189
		target := orig.PullRequestTargets[0]
190
		pr := &base.PullRequest{
191
			Number:     number,
192
			Title:      *orig.Title,
193
			PosterName: c.getUsernameFromARN(*orig.AuthorArn),
194
			Content:    *orig.Description,
195
			State:      "open",
196
			Created:    *orig.CreationDate,
197
			Updated:    *orig.LastActivityDate,
198
			Merged:     target.MergeMetadata.IsMerged,
199
			Head: base.PullRequestBranch{
200
				Ref:      strings.TrimPrefix(*target.SourceReference, git_module.BranchPrefix),
201
				SHA:      *target.SourceCommit,
202
				RepoName: c.repoName,
203
			},
204
			Base: base.PullRequestBranch{
205
				Ref:      strings.TrimPrefix(*target.DestinationReference, git_module.BranchPrefix),
206
				SHA:      *target.DestinationCommit,
207
				RepoName: c.repoName,
208
			},
209
			ForeignIndex: number,
210
		}
211

212
		if orig.PullRequestStatus == types.PullRequestStatusEnumClosed {
213
			pr.State = "closed"
214
			pr.Closed = orig.LastActivityDate
215
		}
216

217
		_ = CheckAndEnsureSafePR(pr, c.baseURL, c)
218
		prs = append(prs, pr)
219
	}
220

221
	return prs, len(prs) < perPage, nil
222
}
223

224
// FormatCloneURL add authentication into remote URLs
225
func (c *CodeCommitDownloader) FormatCloneURL(opts MigrateOptions, remoteAddr string) (string, error) {
226
	u, err := url.Parse(remoteAddr)
227
	if err != nil {
228
		return "", err
229
	}
230
	u.User = url.UserPassword(opts.AuthUsername, opts.AuthPassword)
231
	return u.String(), nil
232
}
233

234
func (c *CodeCommitDownloader) getAllPullRequestIDs() ([]string, error) {
235
	if len(c.allPullRequestIDs) > 0 {
236
		return c.allPullRequestIDs, nil
237
	}
238

239
	var (
240
		nextToken *string
241
		prIDs     []string
242
	)
243

244
	for {
245
		output, err := c.codeCommitClient.ListPullRequests(c.ctx, &codecommit.ListPullRequestsInput{
246
			RepositoryName: aws.String(c.repoName),
247
			NextToken:      nextToken,
248
		})
249
		if err != nil {
250
			return nil, err
251
		}
252
		prIDs = append(prIDs, output.PullRequestIds...)
253
		nextToken = output.NextToken
254
		if nextToken == nil {
255
			break
256
		}
257
	}
258

259
	c.allPullRequestIDs = prIDs
260
	return c.allPullRequestIDs, nil
261
}
262

263
func (c *CodeCommitDownloader) getUsernameFromARN(arn string) string {
264
	parts := strings.Split(arn, "/")
265
	if len(parts) > 0 {
266
		return parts[len(parts)-1]
267
	}
268
	return ""
269
}
270

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.