1ba991379Sopenharmony_ci/*
2ba991379Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3ba991379Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4ba991379Sopenharmony_ci * you may not use this file except in compliance with the License.
5ba991379Sopenharmony_ci * You may obtain a copy of the License at
6ba991379Sopenharmony_ci *
7ba991379Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8ba991379Sopenharmony_ci *
9ba991379Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10ba991379Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11ba991379Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12ba991379Sopenharmony_ci * See the License for the specific language governing permissions and
13ba991379Sopenharmony_ci * limitations under the License.
14ba991379Sopenharmony_ci */
15ba991379Sopenharmony_ci
16ba991379Sopenharmony_cipackage gitee_common
17ba991379Sopenharmony_ci
18ba991379Sopenharmony_ciimport (
19ba991379Sopenharmony_ci	"bufio"
20ba991379Sopenharmony_ci	"bytes"
21ba991379Sopenharmony_ci	"encoding/xml"
22ba991379Sopenharmony_ci	"fmt"
23ba991379Sopenharmony_ci	"fotff/vcs"
24ba991379Sopenharmony_ci	"fotff/vcs/gitee"
25ba991379Sopenharmony_ci	"github.com/huandu/go-clone"
26ba991379Sopenharmony_ci	"github.com/sirupsen/logrus"
27ba991379Sopenharmony_ci	"os"
28ba991379Sopenharmony_ci	"path/filepath"
29ba991379Sopenharmony_ci	"regexp"
30ba991379Sopenharmony_ci	"sort"
31ba991379Sopenharmony_ci	"strconv"
32ba991379Sopenharmony_ci	"strings"
33ba991379Sopenharmony_ci	"sync"
34ba991379Sopenharmony_ci	"time"
35ba991379Sopenharmony_ci)
36ba991379Sopenharmony_ci
37ba991379Sopenharmony_citype IssueInfo struct {
38ba991379Sopenharmony_ci	visited          bool
39ba991379Sopenharmony_ci	RelatedIssues    []string
40ba991379Sopenharmony_ci	MRs              []*gitee.Commit
41ba991379Sopenharmony_ci	StructCTime      string
42ba991379Sopenharmony_ci	StructureUpdates []*vcs.ProjectUpdate
43ba991379Sopenharmony_ci}
44ba991379Sopenharmony_ci
45ba991379Sopenharmony_citype Step struct {
46ba991379Sopenharmony_ci	IssueURLs        []string
47ba991379Sopenharmony_ci	MRs              []*gitee.Commit
48ba991379Sopenharmony_ci	StructCTime      string
49ba991379Sopenharmony_ci	StructureUpdates []*vcs.ProjectUpdate
50ba991379Sopenharmony_ci}
51ba991379Sopenharmony_ci
52ba991379Sopenharmony_cifunc (m *Manager) stepsFromGitee(from, to string) (pkgs []string, err error) {
53ba991379Sopenharmony_ci	updates, err := m.getRepoUpdates(from, to)
54ba991379Sopenharmony_ci	if err != nil {
55ba991379Sopenharmony_ci		return nil, err
56ba991379Sopenharmony_ci	}
57ba991379Sopenharmony_ci	startTime, err := parseTime(from)
58ba991379Sopenharmony_ci	if err != nil {
59ba991379Sopenharmony_ci		return nil, err
60ba991379Sopenharmony_ci	}
61ba991379Sopenharmony_ci	endTime, err := parseTime(to)
62ba991379Sopenharmony_ci	if err != nil {
63ba991379Sopenharmony_ci		return nil, err
64ba991379Sopenharmony_ci	}
65ba991379Sopenharmony_ci	logrus.Infof("find %d repo updates from %s to %s", len(updates), from, to)
66ba991379Sopenharmony_ci	steps, err := getAllStepsFromGitee(startTime, endTime, m.Branch, m.ManifestBranch, updates)
67ba991379Sopenharmony_ci	if err != nil {
68ba991379Sopenharmony_ci		return nil, err
69ba991379Sopenharmony_ci	}
70ba991379Sopenharmony_ci	logrus.Infof("find total %d steps from %s to %s", len(steps), from, to)
71ba991379Sopenharmony_ci	baseManifest, err := vcs.ParseManifestFile(filepath.Join(m.Workspace, from, "manifest_tag.xml"))
72ba991379Sopenharmony_ci	if err != nil {
73ba991379Sopenharmony_ci		return nil, err
74ba991379Sopenharmony_ci	}
75ba991379Sopenharmony_ci	for _, step := range steps {
76ba991379Sopenharmony_ci		var newPkg string
77ba991379Sopenharmony_ci		if newPkg, baseManifest, err = m.genStepPackage(baseManifest, step); err != nil {
78ba991379Sopenharmony_ci			return nil, err
79ba991379Sopenharmony_ci		}
80ba991379Sopenharmony_ci		pkgs = append(pkgs, newPkg)
81ba991379Sopenharmony_ci	}
82ba991379Sopenharmony_ci	return pkgs, nil
83ba991379Sopenharmony_ci}
84ba991379Sopenharmony_ci
85ba991379Sopenharmony_cifunc (m *Manager) getRepoUpdates(from, to string) (updates []vcs.ProjectUpdate, err error) {
86ba991379Sopenharmony_ci	m1, err := vcs.ParseManifestFile(filepath.Join(m.Workspace, from, "manifest_tag.xml"))
87ba991379Sopenharmony_ci	if err != nil {
88ba991379Sopenharmony_ci		return nil, err
89ba991379Sopenharmony_ci	}
90ba991379Sopenharmony_ci	m2, err := vcs.ParseManifestFile(filepath.Join(m.Workspace, to, "manifest_tag.xml"))
91ba991379Sopenharmony_ci	if err != nil {
92ba991379Sopenharmony_ci		return nil, err
93ba991379Sopenharmony_ci	}
94ba991379Sopenharmony_ci	return vcs.GetRepoUpdates(m1, m2)
95ba991379Sopenharmony_ci}
96ba991379Sopenharmony_ci
97ba991379Sopenharmony_cifunc getAllStepsFromGitee(startTime, endTime time.Time, branch string, manifestBranch string, updates []vcs.ProjectUpdate) (ret []Step, err error) {
98ba991379Sopenharmony_ci	allMRs, err := getAllMRs(startTime, endTime, branch, manifestBranch, updates)
99ba991379Sopenharmony_ci	if err != nil {
100ba991379Sopenharmony_ci		return nil, err
101ba991379Sopenharmony_ci	}
102ba991379Sopenharmony_ci	issueInfos, err := combineMRsToIssue(allMRs, branch)
103ba991379Sopenharmony_ci	if err != nil {
104ba991379Sopenharmony_ci		return nil, err
105ba991379Sopenharmony_ci	}
106ba991379Sopenharmony_ci	return combineIssuesToStep(issueInfos)
107ba991379Sopenharmony_ci}
108ba991379Sopenharmony_ci
109ba991379Sopenharmony_cifunc getAllMRs(startTime, endTime time.Time, branch string, manifestBranch string, updates []vcs.ProjectUpdate) (allMRs []*gitee.Commit, err error) {
110ba991379Sopenharmony_ci	var once sync.Once
111ba991379Sopenharmony_ci	for _, update := range updates {
112ba991379Sopenharmony_ci		var prs []*gitee.Commit
113ba991379Sopenharmony_ci		if update.P1.StructureDiff(update.P2) {
114ba991379Sopenharmony_ci			once.Do(func() {
115ba991379Sopenharmony_ci				prs, err = gitee.GetBetweenTimeMRs("openharmony", "manifest", manifestBranch, startTime, endTime)
116ba991379Sopenharmony_ci			})
117ba991379Sopenharmony_ci			if update.P1 != nil {
118ba991379Sopenharmony_ci				var p1 []*gitee.Commit
119ba991379Sopenharmony_ci				p1, err = gitee.GetBetweenTimeMRs("openharmony", update.P1.Name, branch, startTime, endTime)
120ba991379Sopenharmony_ci				prs = append(prs, p1...)
121ba991379Sopenharmony_ci			}
122ba991379Sopenharmony_ci			if update.P2 != nil {
123ba991379Sopenharmony_ci				var p2 []*gitee.Commit
124ba991379Sopenharmony_ci				p2, err = gitee.GetBetweenTimeMRs("openharmony", update.P2.Name, branch, startTime, endTime)
125ba991379Sopenharmony_ci				prs = append(prs, p2...)
126ba991379Sopenharmony_ci			}
127ba991379Sopenharmony_ci		} else {
128ba991379Sopenharmony_ci			prs, err = gitee.GetBetweenMRs(gitee.CompareParam{
129ba991379Sopenharmony_ci				Head:  update.P2.Revision,
130ba991379Sopenharmony_ci				Base:  update.P1.Revision,
131ba991379Sopenharmony_ci				Owner: "openharmony",
132ba991379Sopenharmony_ci				Repo:  update.P2.Name,
133ba991379Sopenharmony_ci			})
134ba991379Sopenharmony_ci		}
135ba991379Sopenharmony_ci		if err != nil {
136ba991379Sopenharmony_ci			return nil, err
137ba991379Sopenharmony_ci		}
138ba991379Sopenharmony_ci		allMRs = append(allMRs, prs...)
139ba991379Sopenharmony_ci	}
140ba991379Sopenharmony_ci	logrus.Infof("find total %d merge request commits of all repo updates", len(allMRs))
141ba991379Sopenharmony_ci	return
142ba991379Sopenharmony_ci}
143ba991379Sopenharmony_ci
144ba991379Sopenharmony_cifunc combineMRsToIssue(allMRs []*gitee.Commit, branch string) (map[string]*IssueInfo, error) {
145ba991379Sopenharmony_ci	ret := make(map[string]*IssueInfo)
146ba991379Sopenharmony_ci	for _, mr := range allMRs {
147ba991379Sopenharmony_ci		num, err := strconv.Atoi(strings.Trim(regexp.MustCompile(`!\d+ `).FindString(mr.Commit.Message), "! "))
148ba991379Sopenharmony_ci		if err != nil {
149ba991379Sopenharmony_ci			return nil, fmt.Errorf("parse MR message for %s fail: %s", mr.URL, err)
150ba991379Sopenharmony_ci		}
151ba991379Sopenharmony_ci		issues, err := gitee.GetMRIssueURL(mr.Owner, mr.Repo, num)
152ba991379Sopenharmony_ci		if err != nil {
153ba991379Sopenharmony_ci			return nil, err
154ba991379Sopenharmony_ci		}
155ba991379Sopenharmony_ci		if len(issues) == 0 {
156ba991379Sopenharmony_ci			issues = []string{mr.URL}
157ba991379Sopenharmony_ci		}
158ba991379Sopenharmony_ci		var scs []*vcs.ProjectUpdate
159ba991379Sopenharmony_ci		var scTime string
160ba991379Sopenharmony_ci		if mr.Owner == "openharmony" && mr.Repo == "manifest" {
161ba991379Sopenharmony_ci			if scTime, scs, err = parseStructureUpdates(mr, branch); err != nil {
162ba991379Sopenharmony_ci				return nil, err
163ba991379Sopenharmony_ci			}
164ba991379Sopenharmony_ci		}
165ba991379Sopenharmony_ci		for i, issue := range issues {
166ba991379Sopenharmony_ci			if _, ok := ret[issue]; !ok {
167ba991379Sopenharmony_ci				ret[issue] = &IssueInfo{
168ba991379Sopenharmony_ci					MRs:              []*gitee.Commit{mr},
169ba991379Sopenharmony_ci					RelatedIssues:    append(issues[:i], issues[i+1:]...),
170ba991379Sopenharmony_ci					StructCTime:      scTime,
171ba991379Sopenharmony_ci					StructureUpdates: scs,
172ba991379Sopenharmony_ci				}
173ba991379Sopenharmony_ci			} else {
174ba991379Sopenharmony_ci				ret[issue] = &IssueInfo{
175ba991379Sopenharmony_ci					MRs:              append(ret[issue].MRs, mr),
176ba991379Sopenharmony_ci					RelatedIssues:    append(ret[issue].RelatedIssues, append(issues[:i], issues[i+1:]...)...),
177ba991379Sopenharmony_ci					StructCTime:      scTime,
178ba991379Sopenharmony_ci					StructureUpdates: append(ret[issue].StructureUpdates, scs...),
179ba991379Sopenharmony_ci				}
180ba991379Sopenharmony_ci			}
181ba991379Sopenharmony_ci		}
182ba991379Sopenharmony_ci	}
183ba991379Sopenharmony_ci	logrus.Infof("find total %d issues of all repo updates", len(ret))
184ba991379Sopenharmony_ci	return ret, nil
185ba991379Sopenharmony_ci}
186ba991379Sopenharmony_ci
187ba991379Sopenharmony_cifunc combineOtherRelatedIssue(parent, self *IssueInfo, all map[string]*IssueInfo) {
188ba991379Sopenharmony_ci	if self.visited {
189ba991379Sopenharmony_ci		return
190ba991379Sopenharmony_ci	}
191ba991379Sopenharmony_ci	self.visited = true
192ba991379Sopenharmony_ci	for _, other := range self.RelatedIssues {
193ba991379Sopenharmony_ci		if son, ok := all[other]; ok {
194ba991379Sopenharmony_ci			combineOtherRelatedIssue(self, son, all)
195ba991379Sopenharmony_ci			delete(all, other)
196ba991379Sopenharmony_ci		}
197ba991379Sopenharmony_ci	}
198ba991379Sopenharmony_ci	parent.RelatedIssues = deDupIssues(append(parent.RelatedIssues, self.RelatedIssues...))
199ba991379Sopenharmony_ci	parent.MRs = deDupMRs(append(parent.MRs, self.MRs...))
200ba991379Sopenharmony_ci	parent.StructureUpdates = deDupProjectUpdates(append(parent.StructureUpdates, self.StructureUpdates...))
201ba991379Sopenharmony_ci	if len(parent.StructCTime) != 0 && parent.StructCTime < self.StructCTime {
202ba991379Sopenharmony_ci		parent.StructCTime = self.StructCTime
203ba991379Sopenharmony_ci	}
204ba991379Sopenharmony_ci}
205ba991379Sopenharmony_ci
206ba991379Sopenharmony_cifunc deDupProjectUpdates(us []*vcs.ProjectUpdate) (retMRs []*vcs.ProjectUpdate) {
207ba991379Sopenharmony_ci	dupIndexes := make([]bool, len(us))
208ba991379Sopenharmony_ci	for i := range us {
209ba991379Sopenharmony_ci		for j := i + 1; j < len(us); j++ {
210ba991379Sopenharmony_ci			if us[j].P1 == us[i].P1 && us[j].P2 == us[i].P2 {
211ba991379Sopenharmony_ci				dupIndexes[j] = true
212ba991379Sopenharmony_ci			}
213ba991379Sopenharmony_ci		}
214ba991379Sopenharmony_ci	}
215ba991379Sopenharmony_ci	for i, dup := range dupIndexes {
216ba991379Sopenharmony_ci		if dup {
217ba991379Sopenharmony_ci			continue
218ba991379Sopenharmony_ci		}
219ba991379Sopenharmony_ci		retMRs = append(retMRs, us[i])
220ba991379Sopenharmony_ci	}
221ba991379Sopenharmony_ci	return
222ba991379Sopenharmony_ci}
223ba991379Sopenharmony_ci
224ba991379Sopenharmony_cifunc deDupMRs(mrs []*gitee.Commit) (retMRs []*gitee.Commit) {
225ba991379Sopenharmony_ci	tmp := make(map[string]*gitee.Commit)
226ba991379Sopenharmony_ci	for _, m := range mrs {
227ba991379Sopenharmony_ci		tmp[m.SHA] = m
228ba991379Sopenharmony_ci	}
229ba991379Sopenharmony_ci	for _, m := range tmp {
230ba991379Sopenharmony_ci		retMRs = append(retMRs, m)
231ba991379Sopenharmony_ci	}
232ba991379Sopenharmony_ci	return
233ba991379Sopenharmony_ci}
234ba991379Sopenharmony_ci
235ba991379Sopenharmony_cifunc deDupIssues(issues []string) (retIssues []string) {
236ba991379Sopenharmony_ci	tmp := make(map[string]string)
237ba991379Sopenharmony_ci	for _, i := range issues {
238ba991379Sopenharmony_ci		tmp[i] = i
239ba991379Sopenharmony_ci	}
240ba991379Sopenharmony_ci	for _, i := range tmp {
241ba991379Sopenharmony_ci		retIssues = append(retIssues, i)
242ba991379Sopenharmony_ci	}
243ba991379Sopenharmony_ci	return
244ba991379Sopenharmony_ci}
245ba991379Sopenharmony_ci
246ba991379Sopenharmony_ci// parseStructureUpdates get changed XMLs and parse it to recognize repo structure changes.
247ba991379Sopenharmony_ci// Since we do not care which revision a repo was, P1 is not welly handled, just assign it not nil for performance.
248ba991379Sopenharmony_cifunc parseStructureUpdates(commit *gitee.Commit, branch string) (string, []*vcs.ProjectUpdate, error) {
249ba991379Sopenharmony_ci	tmp := make(map[string]vcs.ProjectUpdate)
250ba991379Sopenharmony_ci	if len(commit.Files) == 0 {
251ba991379Sopenharmony_ci		// commit that queried from MR req does not contain file details, should fetch again
252ba991379Sopenharmony_ci		var err error
253ba991379Sopenharmony_ci		if commit, err = gitee.GetCommit(commit.Owner, commit.Repo, commit.SHA); err != nil {
254ba991379Sopenharmony_ci			return "", nil, err
255ba991379Sopenharmony_ci		}
256ba991379Sopenharmony_ci	}
257ba991379Sopenharmony_ci	for _, f := range commit.Files {
258ba991379Sopenharmony_ci		if filepath.Ext(f.Filename) != ".xml" {
259ba991379Sopenharmony_ci			continue
260ba991379Sopenharmony_ci		}
261ba991379Sopenharmony_ci		if err := parseFilePatch(f.Patch, tmp); err != nil {
262ba991379Sopenharmony_ci			return "", nil, err
263ba991379Sopenharmony_ci		}
264ba991379Sopenharmony_ci	}
265ba991379Sopenharmony_ci	var ret []*vcs.ProjectUpdate
266ba991379Sopenharmony_ci	for _, pu := range tmp {
267ba991379Sopenharmony_ci		projectUpdateCopy := pu
268ba991379Sopenharmony_ci		ret = append(ret, &projectUpdateCopy)
269ba991379Sopenharmony_ci	}
270ba991379Sopenharmony_ci	for _, pu := range ret {
271ba991379Sopenharmony_ci		if pu.P1 == nil && pu.P2 != nil {
272ba991379Sopenharmony_ci			lastCommit, err := gitee.GetLatestMRBefore("openharmony", pu.P2.Name, branch, commit.Commit.Committer.Date)
273ba991379Sopenharmony_ci			if err != nil {
274ba991379Sopenharmony_ci				return "", nil, err
275ba991379Sopenharmony_ci			}
276ba991379Sopenharmony_ci			pu.P2.Revision = lastCommit.SHA
277ba991379Sopenharmony_ci		}
278ba991379Sopenharmony_ci	}
279ba991379Sopenharmony_ci	return commit.Commit.Committer.Date, ret, nil
280ba991379Sopenharmony_ci}
281ba991379Sopenharmony_ci
282ba991379Sopenharmony_cifunc parseFilePatch(str string, m map[string]vcs.ProjectUpdate) error {
283ba991379Sopenharmony_ci	sc := bufio.NewScanner(bytes.NewBuffer([]byte(str)))
284ba991379Sopenharmony_ci	for sc.Scan() {
285ba991379Sopenharmony_ci		line := sc.Text()
286ba991379Sopenharmony_ci		var p vcs.Project
287ba991379Sopenharmony_ci		if strings.HasPrefix(line, "-") {
288ba991379Sopenharmony_ci			if err := xml.Unmarshal([]byte(line[1:]), &p); err == nil {
289ba991379Sopenharmony_ci				m[p.Name] = vcs.ProjectUpdate{P1: &p, P2: m[p.Name].P2}
290ba991379Sopenharmony_ci			}
291ba991379Sopenharmony_ci		} else if strings.HasPrefix(line, "+") {
292ba991379Sopenharmony_ci			if err := xml.Unmarshal([]byte(line[1:]), &p); err == nil {
293ba991379Sopenharmony_ci				m[p.Name] = vcs.ProjectUpdate{P1: m[p.Name].P1, P2: &p}
294ba991379Sopenharmony_ci			}
295ba991379Sopenharmony_ci		}
296ba991379Sopenharmony_ci	}
297ba991379Sopenharmony_ci	return nil
298ba991379Sopenharmony_ci}
299ba991379Sopenharmony_ci
300ba991379Sopenharmony_cifunc combineIssuesToStep(issueInfos map[string]*IssueInfo) (ret []Step, err error) {
301ba991379Sopenharmony_ci	for _, info := range issueInfos {
302ba991379Sopenharmony_ci		combineOtherRelatedIssue(info, info, issueInfos)
303ba991379Sopenharmony_ci	}
304ba991379Sopenharmony_ci	for issue, infos := range issueInfos {
305ba991379Sopenharmony_ci		sort.Slice(infos.MRs, func(i, j int) bool {
306ba991379Sopenharmony_ci			// move the latest MR to the first place, use its merged_time to represent the update time of the issue
307ba991379Sopenharmony_ci			return infos.MRs[i].Commit.Committer.Date > infos.MRs[j].Commit.Committer.Date
308ba991379Sopenharmony_ci		})
309ba991379Sopenharmony_ci		ret = append(ret, Step{
310ba991379Sopenharmony_ci			IssueURLs:        append(infos.RelatedIssues, issue),
311ba991379Sopenharmony_ci			MRs:              infos.MRs,
312ba991379Sopenharmony_ci			StructCTime:      infos.StructCTime,
313ba991379Sopenharmony_ci			StructureUpdates: infos.StructureUpdates})
314ba991379Sopenharmony_ci	}
315ba991379Sopenharmony_ci	sort.Slice(ret, func(i, j int) bool {
316ba991379Sopenharmony_ci		ti, tj := ret[i].MRs[0].Commit.Committer.Date, ret[j].MRs[0].Commit.Committer.Date
317ba991379Sopenharmony_ci		if len(ret[i].StructCTime) != 0 {
318ba991379Sopenharmony_ci			ti = ret[i].StructCTime
319ba991379Sopenharmony_ci		}
320ba991379Sopenharmony_ci		if len(ret[j].StructCTime) != 0 {
321ba991379Sopenharmony_ci			ti = ret[j].StructCTime
322ba991379Sopenharmony_ci		}
323ba991379Sopenharmony_ci		return ti < tj
324ba991379Sopenharmony_ci	})
325ba991379Sopenharmony_ci	logrus.Infof("find total %d steps of all issues", len(ret))
326ba991379Sopenharmony_ci	return
327ba991379Sopenharmony_ci}
328ba991379Sopenharmony_ci
329ba991379Sopenharmony_cifunc parseTime(pkg string) (time.Time, error) {
330ba991379Sopenharmony_ci	t, err := time.ParseInLocation(`20060102_150405`, regexp.MustCompile(`\d{8}_\d{6}`).FindString(pkg), time.Local)
331ba991379Sopenharmony_ci	if err != nil {
332ba991379Sopenharmony_ci		return time.ParseInLocation(`20060102150405`, regexp.MustCompile(`\d{14}`).FindString(pkg), time.Local)
333ba991379Sopenharmony_ci	}
334ba991379Sopenharmony_ci	return t, nil
335ba991379Sopenharmony_ci}
336ba991379Sopenharmony_ci
337ba991379Sopenharmony_cifunc (m *Manager) genStepPackage(base *vcs.Manifest, step Step) (newPkg string, newManifest *vcs.Manifest, err error) {
338ba991379Sopenharmony_ci	defer func() {
339ba991379Sopenharmony_ci		logrus.Infof("package dir %s for step %v generated", newPkg, step.IssueURLs)
340ba991379Sopenharmony_ci	}()
341ba991379Sopenharmony_ci	newManifest = clone.Clone(base).(*vcs.Manifest)
342ba991379Sopenharmony_ci	for _, u := range step.StructureUpdates {
343ba991379Sopenharmony_ci		if u.P2 != nil {
344ba991379Sopenharmony_ci			newManifest.UpdateManifestProject(u.P2.Name, u.P2.Path, u.P2.Remote, u.P2.Revision, true)
345ba991379Sopenharmony_ci		} else if u.P1 != nil {
346ba991379Sopenharmony_ci			newManifest.RemoveManifestProject(u.P1.Name)
347ba991379Sopenharmony_ci		}
348ba991379Sopenharmony_ci	}
349ba991379Sopenharmony_ci	for _, mr := range step.MRs {
350ba991379Sopenharmony_ci		newManifest.UpdateManifestProject(mr.Repo, "", "", mr.SHA, false)
351ba991379Sopenharmony_ci	}
352ba991379Sopenharmony_ci	md5sum, err := newManifest.Standardize()
353ba991379Sopenharmony_ci	if err != nil {
354ba991379Sopenharmony_ci		return "", nil, err
355ba991379Sopenharmony_ci	}
356ba991379Sopenharmony_ci	if err := os.MkdirAll(filepath.Join(m.Workspace, md5sum), 0750); err != nil {
357ba991379Sopenharmony_ci		return "", nil, err
358ba991379Sopenharmony_ci	}
359ba991379Sopenharmony_ci	if err := os.WriteFile(filepath.Join(m.Workspace, md5sum, "__last_issue__"), []byte(fmt.Sprintf("%v", step.IssueURLs)), 0640); err != nil {
360ba991379Sopenharmony_ci		return "", nil, err
361ba991379Sopenharmony_ci	}
362ba991379Sopenharmony_ci	err = newManifest.WriteFile(filepath.Join(m.Workspace, md5sum, "manifest_tag.xml"))
363ba991379Sopenharmony_ci	if err != nil {
364ba991379Sopenharmony_ci		return "", nil, err
365ba991379Sopenharmony_ci	}
366ba991379Sopenharmony_ci	return md5sum, newManifest, nil
367ba991379Sopenharmony_ci}
368