Skip to content

Commit 2372dd3

Browse files
author
davidkline-ms
committed
put back packagemanifest folder
1 parent 5e8ea36 commit 2372dd3

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using UnityEngine;
8+
9+
namespace Microsoft.MixedReality.Toolkit.Utilities.Editor
10+
{
11+
/// <summary>
12+
/// Class that enables MRTK to add scoped registries and/or packages to the Unity Package Mangager manifest
13+
/// </summary>
14+
internal static class PackageManifestUpdater
15+
{
16+
private static string MSBuildRegistryUrl = "https://pkgs.dev.azure.com/UnityDeveloperTools/MSBuildForUnity/_packaging/UnityDeveloperTools/npm/registry";
17+
private static string MSBuildRegistryName = "MS Build for Unity";
18+
private static string[] MSBuildRegistryScopes = new string[] { "com.microsoft" };
19+
20+
private static string MSBuildPackageName = "com.microsoft.msbuildforunity";
21+
private static string MSBuildPackageVersion = "0.8.3";
22+
23+
/// <summary>
24+
/// Ensures the required settings exist in the package manager to allow for
25+
/// installing MSBuild for Unity.
26+
/// </summary>
27+
internal static void EnsureMSBuildForUnity()
28+
{
29+
// Locate the full path to the package manifest.
30+
DirectoryInfo projectRoot = new DirectoryInfo(Application.dataPath).Parent;
31+
string[] paths = { projectRoot.FullName, "Packages", "manifest.json" };
32+
string manifestPath = Path.Combine(paths);
33+
34+
// Verify that the package manifest file exists.
35+
if (!File.Exists(manifestPath))
36+
{
37+
Debug.LogError($"Package manifest file ({manifestPath}) could not be found.");
38+
return;
39+
}
40+
41+
PackageManifest manifest = null;
42+
43+
// Read the package manifest into a list of strings (for easy finding of entries)
44+
// and then deserialize.
45+
List<string> manifestFileLines = new List<string>();
46+
using (FileStream manifestStream = new FileStream(manifestPath, FileMode.Open, FileAccess.Read))
47+
{
48+
using (StreamReader reader = new StreamReader(manifestStream))
49+
{
50+
// Read the manifest file a line at a time.
51+
while (!reader.EndOfStream)
52+
{
53+
string line = reader.ReadLine();
54+
manifestFileLines.Add(line);
55+
}
56+
57+
// Go back to the start of the file.
58+
manifestStream.Seek(0, 0);
59+
60+
// Deserialize the scoped registries portion of the package manifest.
61+
manifest = JsonUtility.FromJson<PackageManifest>(reader.ReadToEnd());
62+
}
63+
}
64+
65+
if (manifest == null)
66+
{
67+
Debug.LogError($"Failed to read the package manifest file ({manifestPath})");
68+
return;
69+
}
70+
71+
// Ensure that pre-exising scoped registries are retained.
72+
List<ScopedRegistry> scopedRegistries = new List<ScopedRegistry>();
73+
if ((manifest.scopedRegistries != null) && (manifest.scopedRegistries.Length > 0))
74+
{
75+
scopedRegistries.AddRange(manifest.scopedRegistries);
76+
}
77+
78+
// Attempt to find an entry in the scoped regstries collection for the MSBuild for Unity url
79+
bool needToAddRegistry = true;
80+
foreach (ScopedRegistry registry in scopedRegistries)
81+
{
82+
if (registry.url == MSBuildRegistryUrl)
83+
{
84+
needToAddRegistry = false;
85+
}
86+
}
87+
88+
// If no entry was found, add one.
89+
if (needToAddRegistry)
90+
{
91+
ScopedRegistry registry = new ScopedRegistry();
92+
registry.name = MSBuildRegistryName;
93+
registry.url = MSBuildRegistryUrl;
94+
registry.scopes = MSBuildRegistryScopes;
95+
96+
scopedRegistries.Add(registry);
97+
}
98+
99+
// Update the manifest's scoped registries, as the collection may have been modified.
100+
manifest.scopedRegistries = scopedRegistries.ToArray();
101+
102+
int dependenciesStartIndex = -1;
103+
int scopedRegistriesStartIndex = -1;
104+
int scopedRegistriesEndIndex = -1;
105+
106+
// Attempt to find the MSBuild for Unity package entry in the dependencies collection
107+
// This loop also identifies the dependecies collection line and the start / end of a
108+
// pre-existing scoped registries collections
109+
bool needToAddPackage = true;
110+
for (int i = 0; i < manifestFileLines.Count; i++)
111+
{
112+
if (manifestFileLines[i].Contains("\"scopedRegistries\":"))
113+
{
114+
scopedRegistriesStartIndex = i;
115+
}
116+
if (manifestFileLines[i].Contains("],") && (scopedRegistriesStartIndex != -1) && (scopedRegistriesEndIndex == -1))
117+
{
118+
scopedRegistriesEndIndex = i;
119+
}
120+
if (manifestFileLines[i].Contains("\"dependencies\": {"))
121+
{
122+
dependenciesStartIndex = i;
123+
}
124+
if (manifestFileLines[i].Contains(MSBuildPackageName))
125+
{
126+
needToAddPackage = false;
127+
}
128+
}
129+
130+
// If no package was found add it to the dependencies collection.
131+
if (needToAddPackage)
132+
{
133+
// Add the package to the collection (pad the entry with four spaces)
134+
manifestFileLines.Insert(dependenciesStartIndex + 1, $" \"{MSBuildPackageName}\": \"{MSBuildPackageVersion}\",");
135+
}
136+
137+
if (needToAddRegistry || needToAddPackage)
138+
{
139+
// If we added a scoped registry or package, rewrite the manifest file.
140+
141+
// First, serialize the scoped registry collection.
142+
string serializedRegistriesJson = JsonUtility.ToJson(manifest, true);
143+
144+
// Ensure that the file is truncated to ensure it is always valid after writing.
145+
using (FileStream outFile = new FileStream(manifestPath, FileMode.Truncate, FileAccess.Write))
146+
{
147+
using (StreamWriter writer = new StreamWriter(outFile))
148+
{
149+
bool scopedRegistriesWritten = false;
150+
151+
// Write each line of the manifest back to the file.
152+
for (int i = 0; i < manifestFileLines.Count; i++)
153+
{
154+
if ((i >= scopedRegistriesStartIndex) && (i <= scopedRegistriesEndIndex))
155+
{
156+
// Skip these lines, they will be replaced.
157+
continue;
158+
}
159+
160+
if (!scopedRegistriesWritten && (i > 0))
161+
{
162+
// Trim the leading '{' and '\n' from the serialized scoped registries
163+
serializedRegistriesJson = serializedRegistriesJson.Remove(0, 2);
164+
// Trim, the trailing '\n' and '}'
165+
serializedRegistriesJson = serializedRegistriesJson.Remove(serializedRegistriesJson.Length - 2);
166+
// Append a trailing ',' to close the scopedRegistries node
167+
serializedRegistriesJson = serializedRegistriesJson.Insert(serializedRegistriesJson.Length, ",");
168+
writer.WriteLine(serializedRegistriesJson);
169+
170+
scopedRegistriesWritten = true;
171+
}
172+
173+
writer.WriteLine(manifestFileLines[i]);
174+
}
175+
}
176+
}
177+
}
178+
}
179+
}
180+
181+
/// <summary>
182+
/// This class encapsulates the portion of the package manifest
183+
/// file format that is of greatest interest to the MRTK.
184+
/// </summary>
185+
[Serializable]
186+
internal class PackageManifest
187+
{
188+
public ScopedRegistry[] scopedRegistries = null;
189+
}
190+
191+
/// <summary>
192+
/// This class defines a scoped registry, per the manifest file format.
193+
/// </summary>
194+
[Serializable]
195+
internal class ScopedRegistry
196+
{
197+
public string name = null;
198+
public string url = null;
199+
public string[] scopes = null;
200+
}
201+
}

Assets/MixedRealityToolkit/Utilities/Editor/PackageManifest/PackageManifestUpdater.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)