Skip to content

Commit 0c7b662

Browse files
author
Stewart Miles
committed
Support for manifest name aliases.
This adds support for the manifestname manifest file attribute. Manifest can be mapped to one or more manifest or package names with the name prefixed with "0" as the primary name. Bug: 150886091 Change-Id: I86e51fcc3183644c1b9f907b3b3a088d55e7e277
1 parent 6e57687 commit 0c7b662

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,15 @@ Unity plugins can be managed by the Version Handler using the following steps:
454454
that lists all the files in your plugin relative to the project root.
455455
Then add the `gvh_manifest` label to the asset to indicate this file is
456456
a plugin manifest.
457+
1. Optional: Add a `gvhp_manifestname-NAME` label to your manifest file
458+
to provide a human readable name for your package. If this isn't provided
459+
the name of the manifest file will be used as the package name.
460+
NAME can match the pattern `[0-9]+[a-zA-Z -]' where a leading integer
461+
will set the priority of the name where `0` is the highest priority
462+
and preferably used as the display name. The lowest value (i.e highest
463+
priority name) will be used as the display name and all other specified
464+
names will be aliases of the display name. Aliases can refer to previous
465+
names of the package allowing renaming across published versions.
457466
1. Redistribute EDM4U Unity plugin with your plugin.
458467
See the [Plugin Redistribution](#plugin-redistribution) for the details.
459468

source/VersionHandlerImpl/src/VersionHandlerImpl.cs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,134 @@ private FileMetadataByVersion FindMetadataByVersion(string filenameCanonical,
12581258
return metadataByVersion;
12591259
}
12601260

1261+
/// <summary>
1262+
/// Find the highest priority name of a manifest.
1263+
/// </summary>
1264+
/// <param name="name">Name to lookup from the graph.</param>
1265+
/// <param name="aliasesByName">Adjacency list (graph) of aliases to search.</param>
1266+
/// <param name="maxDepth">Maximum depth to traverse the graph.</param>
1267+
/// <param name="depth">Graph traversal depth.</param>
1268+
/// <returns>Name and depth in the graph or the supplied name and a depth of -1
1269+
/// if not found.</returns>
1270+
private static KeyValuePair<string, int> FindHighestPriorityManifestName(
1271+
string name, Dictionary<string, HashSet<string>> aliasesByName, int maxDepth,
1272+
int depth = 0) {
1273+
if (depth > maxDepth) {
1274+
Log(String.Format(
1275+
"Detected manifest name alias loop for name {0}, to fix this change the " +
1276+
"list (see below) to not contain a loop:\n{1}" +
1277+
name, String.Join("\n", (new List<string>(aliasesByName.Keys)).ToArray())),
1278+
level: LogLevel.Warning);
1279+
return new KeyValuePair<string, int>(name, -1);
1280+
}
1281+
KeyValuePair<string, int> deepestNameAndDepth =
1282+
new KeyValuePair<string, int>(name, depth);
1283+
HashSet<string> aliases;
1284+
if (!aliasesByName.TryGetValue(name, out aliases)) {
1285+
return deepestNameAndDepth;
1286+
}
1287+
if (aliases.Count == 1 && (new List<string>(aliases))[0] == name) {
1288+
return deepestNameAndDepth;
1289+
}
1290+
foreach (var alias in aliases) {
1291+
var nameAndDepth = FindHighestPriorityManifestName(
1292+
alias, aliasesByName, maxDepth, depth: depth + 1);
1293+
if (nameAndDepth.Value > deepestNameAndDepth.Value) {
1294+
deepestNameAndDepth = nameAndDepth;
1295+
}
1296+
}
1297+
return deepestNameAndDepth;
1298+
}
1299+
1300+
/// <summary>
1301+
/// Create an adjacency list of manifest names.
1302+
/// </summary>
1303+
/// <returns>Adjacency list of manifest names. For example, given the set of manifest
1304+
/// names for a file "foo.txt" [manifestName-0A, manifestName-1B, manifestName-1C]
1305+
/// this returns the set of aliaes for the name of manifest "A", i.e {"A": ["B, "C"]}.
1306+
/// </returns>
1307+
private Dictionary<string, HashSet<string>> GetManifestAliasesByName() {
1308+
// Create an adjacency list of manifest alias to name which can be used to search the
1309+
// highest priority name of a manifest "foo", which is the entry {"foo": ["foo"]}.
1310+
var aliasesByName = new Dictionary<string, HashSet<string>>();
1311+
foreach (var metadataByVersion in Values) {
1312+
var metadata = metadataByVersion.MostRecentVersion;
1313+
if (metadata.isManifest) {
1314+
foreach (var name in metadata.customManifestNames.Values) {
1315+
HashSet<string> aliases = null;
1316+
if (!aliasesByName.TryGetValue(name, out aliases)) {
1317+
aliases = new HashSet<string>();
1318+
aliasesByName[name] = aliases;
1319+
}
1320+
aliases.Add(metadata.customManifestNames.Values[0]);
1321+
}
1322+
}
1323+
}
1324+
// Display adjacency list for debugging.
1325+
var logLines = new List<string>();
1326+
foreach (var nameAndAliases in aliasesByName) {
1327+
logLines.Add(String.Format(
1328+
"name: {0} --> aliases: [{1}]", nameAndAliases.Key,
1329+
String.Join(", ", (new List<string>(nameAndAliases.Value)).ToArray())));
1330+
}
1331+
if (logLines.Count > 0) {
1332+
Log(String.Format("Manifest aliases:\n{0}",
1333+
String.Join("\n", logLines.ToArray())), verbose: true);
1334+
}
1335+
return aliasesByName;
1336+
}
1337+
1338+
/// <summary>
1339+
/// Use manifest aliases to cosolidate manifest metadata.
1340+
/// </summary>
1341+
public void ConsolidateManifests() {
1342+
var aliasesByName = GetManifestAliasesByName();
1343+
// Flatten graph of manifest aliases so that each entry maps to the highest priority
1344+
// name.
1345+
var manifestAliases = new Dictionary<string, string>();
1346+
int numberOfAliases = aliasesByName.Count;
1347+
1348+
var logLines = new List<string>();
1349+
foreach (var name in aliasesByName.Keys) {
1350+
var foundName = FindHighestPriorityManifestName(name, aliasesByName,
1351+
numberOfAliases).Key;
1352+
manifestAliases[name] = foundName;
1353+
logLines.Add(String.Format("name: {0} --> alias: {1}", name, foundName));
1354+
}
1355+
if (logLines.Count > 0) {
1356+
Log(String.Format("Flattened manifest aliases:\n{0}",
1357+
String.Join("\n", logLines.ToArray())), verbose: true);
1358+
}
1359+
1360+
// Create a new metadata map consolidating manifests by their highest priority name.
1361+
var oldMetadataByCanonicalFilename = metadataByCanonicalFilename;
1362+
Clear();
1363+
foreach (var canonicalFilenameAndMetadataByVersion in oldMetadataByCanonicalFilename) {
1364+
var metadata = canonicalFilenameAndMetadataByVersion.Value.MostRecentVersion;
1365+
if (metadata.isManifest) {
1366+
FileMetadataByVersion manifests = canonicalFilenameAndMetadataByVersion.Value;
1367+
// Merge multiple versions of the manifest.
1368+
string manifestName;
1369+
if (!manifestAliases.TryGetValue(metadata.ManifestName, out manifestName)) {
1370+
manifestName = metadata.ManifestName;
1371+
}
1372+
Add(manifestName, manifests);
1373+
1374+
logLines = new List<string>();
1375+
foreach (var manifest in manifests.Values) {
1376+
logLines.Add(String.Format("file: {0}, version: {1}",
1377+
manifest.filename, manifest.versionString));
1378+
}
1379+
Log(String.Format("Add manifests to package '{0}':\n{1}",
1380+
manifestName, String.Join("\n", logLines.ToArray())),
1381+
verbose: true);
1382+
} else {
1383+
Add(canonicalFilenameAndMetadataByVersion.Key,
1384+
canonicalFilenameAndMetadataByVersion.Value);
1385+
}
1386+
}
1387+
}
1388+
12611389
/// <summary>
12621390
/// For each plugin (DLL) referenced by this set, disable targeting
12631391
/// for all versions and re-enable platform targeting for the most
@@ -1553,6 +1681,7 @@ public bool ParseManifests(FileMetadataByVersion metadataByVersion,
15531681
/// obsolete files referenced in each manifest file.</returns>
15541682
public static List<ManifestReferences> FindAndReadManifests(
15551683
FileMetadataSet metadataSet) {
1684+
metadataSet.ConsolidateManifests();
15561685
var manifestReferencesList = new List<ManifestReferences>();
15571686
foreach (var metadataByVersion in metadataSet.Values) {
15581687
ManifestReferences manifestReferences =

0 commit comments

Comments
 (0)