Files
phs_v1.0.1.0/developtools/integration_verification/tools/fotff/vcs/manifest.go
2024-09-27 19:16:49 +08:00

187 lines
4.4 KiB
Go

/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package vcs
import (
"crypto/md5"
"encoding/xml"
"fmt"
"github.com/sirupsen/logrus"
"os"
"sort"
)
type Manifest struct {
XMLName xml.Name `xml:"manifest"`
Remote Remote `xml:"remote"`
Default Default `xml:"default"`
Projects []Project `xml:"project"`
}
type Remote struct {
Name string `xml:"name,attr"`
Fetch string `xml:"fetch,attr"`
Review string `xml:"review,attr"`
}
type Default struct {
Remote string `xml:"remote,attr"`
Revision string `xml:"revision,attr"`
SyncJ string `xml:"sync-j,attr"`
}
type Project struct {
XMLName xml.Name `xml:"project"`
Name string `xml:"name,attr"`
Path string `xml:"path,attr,omitempty"`
Revision string `xml:"revision,attr"`
Remote string `xml:"remote,attr,omitempty"`
CloneDepth string `xml:"clone-depth,attr,omitempty"`
LinkFile []LinkFile `xml:"linkfile,omitempty"`
}
type LinkFile struct {
Src string `xml:"src,attr"`
Dest string `xml:"dest,attr"`
}
type ProjectUpdate struct {
P1, P2 *Project
}
func (p *Project) String() string {
if p == nil {
return "<nil>"
}
return fmt.Sprintf("<%s>", p.Name)
}
func (p *Project) StructureDiff(p2 *Project) bool {
if p == nil && p2 != nil || p != nil && p2 == nil {
return true
}
if p == nil && p2 == nil {
return false
}
return p.Name != p2.Name || p.Path != p2.Path || p.Remote != p2.Remote
}
func (p *Project) Equals(p2 *Project) bool {
return p.Name == p2.Name && p.Path == p2.Path && p.Remote == p2.Remote && p.Revision == p2.Revision
}
func ParseManifestFile(file string) (*Manifest, error) {
data, err := os.ReadFile(file)
if err != nil {
return nil, err
}
var m Manifest
err = xml.Unmarshal(data, &m)
return &m, err
}
func (m *Manifest) WriteFile(filePath string) error {
data, err := xml.MarshalIndent(m, "", " ")
if err != nil {
return err
}
data = append([]byte(xml.Header), data...)
return os.WriteFile(filePath, data, 0640)
}
func GetRepoUpdates(m1, m2 *Manifest) (updates []ProjectUpdate, err error) {
if _, err := m1.Standardize(); err != nil {
return nil, err
}
if _, err := m2.Standardize(); err != nil {
return nil, err
}
var j int
for i := 0; i < len(m1.Projects); {
if m2.Projects[j].Name == m1.Projects[i].Name {
if !m1.Projects[i].Equals(&m2.Projects[j]) {
logrus.Infof("%v changes", &m1.Projects[i])
updates = append(updates, ProjectUpdate{
P1: &m1.Projects[i],
P2: &m2.Projects[j],
})
}
i++
j++
} else if m2.Projects[j].Name > m1.Projects[i].Name {
logrus.Infof("%v removed", &m1.Projects[i])
updates = append(updates, ProjectUpdate{
P1: &m1.Projects[i],
P2: nil,
})
i++
} else { // m2.Projects[j].Name < m1.Projects[i].Name
logrus.Infof("%v added", &m2.Projects[j])
updates = append(updates, ProjectUpdate{
P1: nil,
P2: &m2.Projects[j],
})
j++
}
}
return
}
func (m *Manifest) UpdateManifestProject(name, path, remote, revision string, add bool) {
if name == "manifest" {
return
}
for i, p := range m.Projects {
if p.Name == name {
if path != "" {
m.Projects[i].Path = path
}
if remote != "" {
m.Projects[i].Remote = remote
}
if revision != "" {
m.Projects[i].Revision = revision
}
return
}
}
if add {
m.Projects = append(m.Projects, Project{Name: name, Path: path, Revision: revision, Remote: remote})
}
}
func (m *Manifest) RemoveManifestProject(name string) {
for i, p := range m.Projects {
if p.Name == name {
m.Projects = append(m.Projects[:i], m.Projects[i:]...)
return
}
}
}
func (m *Manifest) Standardize() (string, error) {
sort.Slice(m.Projects, func(i, j int) bool {
return m.Projects[i].Name < m.Projects[j].Name
})
data, err := xml.MarshalIndent(m, "", " ")
if err != nil {
return "", err
}
data = append([]byte(xml.Header), data...)
sumByte := md5.Sum(data)
return fmt.Sprintf("%X", sumByte), nil
}