Bug: 296873595 Test: Manual test (use go test inside tools/metadata/testdata) Change-Id: I404b57224828149f26bcf4deadb662f513886231
170 lines
3.8 KiB
Go
170 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"sync"
|
|
|
|
"android/soong/testing/test_spec_proto"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
type keyToLocksMap struct {
|
|
locks sync.Map
|
|
}
|
|
|
|
func (kl *keyToLocksMap) GetLockForKey(key string) *sync.Mutex {
|
|
mutex, _ := kl.locks.LoadOrStore(key, &sync.Mutex{})
|
|
return mutex.(*sync.Mutex)
|
|
}
|
|
|
|
func getSortedKeys(syncMap *sync.Map) []string {
|
|
var allKeys []string
|
|
syncMap.Range(
|
|
func(key, _ interface{}) bool {
|
|
allKeys = append(allKeys, key.(string))
|
|
return true
|
|
},
|
|
)
|
|
|
|
sort.Strings(allKeys)
|
|
return allKeys
|
|
}
|
|
|
|
func writeOutput(
|
|
outputFile string,
|
|
allMetadata []*test_spec_proto.TestSpec_OwnershipMetadata,
|
|
) {
|
|
testSpec := &test_spec_proto.TestSpec{
|
|
OwnershipMetadataList: allMetadata,
|
|
}
|
|
data, err := proto.Marshal(testSpec)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
file, err := os.Create(outputFile)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
_, err = file.Write(data)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func readFileToString(filePath string) string {
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
data, err := io.ReadAll(file)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return string(data)
|
|
}
|
|
|
|
func processProtobuf(
|
|
filePath string, ownershipMetadataMap *sync.Map, keyLocks *keyToLocksMap,
|
|
errCh chan error, wg *sync.WaitGroup,
|
|
) {
|
|
defer wg.Done()
|
|
|
|
fileContent := strings.TrimRight(readFileToString(filePath), "\n")
|
|
testData := test_spec_proto.TestSpec{}
|
|
err := proto.Unmarshal([]byte(fileContent), &testData)
|
|
if err != nil {
|
|
errCh <- err
|
|
return
|
|
}
|
|
|
|
ownershipMetadata := testData.GetOwnershipMetadataList()
|
|
for _, metadata := range ownershipMetadata {
|
|
key := metadata.GetTargetName()
|
|
lock := keyLocks.GetLockForKey(key)
|
|
lock.Lock()
|
|
|
|
value, loaded := ownershipMetadataMap.LoadOrStore(
|
|
key, []*test_spec_proto.TestSpec_OwnershipMetadata{metadata},
|
|
)
|
|
if loaded {
|
|
existingMetadata := value.([]*test_spec_proto.TestSpec_OwnershipMetadata)
|
|
isDuplicate := false
|
|
for _, existing := range existingMetadata {
|
|
if metadata.GetTrendyTeamId() != existing.GetTrendyTeamId() {
|
|
errCh <- fmt.Errorf(
|
|
"Conflicting trendy team IDs found for %s at:\n%s with teamId"+
|
|
": %s,\n%s with teamId: %s",
|
|
key,
|
|
metadata.GetPath(), metadata.GetTrendyTeamId(), existing.GetPath(),
|
|
existing.GetTrendyTeamId(),
|
|
)
|
|
|
|
lock.Unlock()
|
|
return
|
|
}
|
|
if metadata.GetTrendyTeamId() == existing.GetTrendyTeamId() && metadata.GetPath() == existing.GetPath() {
|
|
isDuplicate = true
|
|
break
|
|
}
|
|
}
|
|
if !isDuplicate {
|
|
existingMetadata = append(existingMetadata, metadata)
|
|
ownershipMetadataMap.Store(key, existingMetadata)
|
|
}
|
|
}
|
|
|
|
lock.Unlock()
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
inputFile := flag.String("inputFile", "", "Input file path")
|
|
outputFile := flag.String("outputFile", "", "Output file path")
|
|
flag.Parse()
|
|
|
|
if *inputFile == "" || *outputFile == "" {
|
|
fmt.Println("Usage: metadata -inputFile <input file path> -outputFile <output file path>")
|
|
os.Exit(1)
|
|
}
|
|
|
|
inputFileData := strings.TrimRight(readFileToString(*inputFile), "\n")
|
|
filePaths := strings.Split(inputFileData, "\n")
|
|
ownershipMetadataMap := &sync.Map{}
|
|
keyLocks := &keyToLocksMap{}
|
|
errCh := make(chan error, len(filePaths))
|
|
var wg sync.WaitGroup
|
|
|
|
for _, filePath := range filePaths {
|
|
wg.Add(1)
|
|
go processProtobuf(filePath, ownershipMetadataMap, keyLocks, errCh, &wg)
|
|
}
|
|
|
|
wg.Wait()
|
|
close(errCh)
|
|
|
|
for err := range errCh {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
allKeys := getSortedKeys(ownershipMetadataMap)
|
|
var allMetadata []*test_spec_proto.TestSpec_OwnershipMetadata
|
|
|
|
for _, key := range allKeys {
|
|
value, _ := ownershipMetadataMap.Load(key)
|
|
metadataList := value.([]*test_spec_proto.TestSpec_OwnershipMetadata)
|
|
allMetadata = append(allMetadata, metadataList...)
|
|
}
|
|
|
|
writeOutput(*outputFile, allMetadata)
|
|
}
|