44using System ;
55using System . Collections . Generic ;
66using System . IO ;
7+ using UnityEditor . PackageManager ;
78using UnityEngine ;
89
910namespace Microsoft . MixedReality . Toolkit . Utilities . Editor
@@ -17,14 +18,14 @@ internal static class PackageManifestUpdater
1718 private static string MSBuildRegistryName = "MS Build for Unity" ;
1819 private static string [ ] MSBuildRegistryScopes = new string [ ] { "com.microsoft" } ;
1920
20- private static string MSBuildPackageName = "com.microsoft.msbuildforunity" ;
21- private static string MSBuildPackageVersion = "0.9.1" ;
21+ internal const string MSBuildPackageName = "com.microsoft.msbuildforunity" ;
22+ internal const string MSBuildPackageVersion = "0.9.1" ;
2223
2324 /// <summary>
24- /// Ensures the required settings exist in the package manager to allow for
25- /// installing MSBuild for Unity.
25+ /// Finds and returns the fully qualified path to the Unity Package Manager manifest
2626 /// </summary>
27- internal static void EnsureMSBuildForUnity ( )
27+ /// <returns>The path to the manifest file, or null.</returns>
28+ private static string GetPackageManifestFilePath ( )
2829 {
2930 // Locate the full path to the package manifest.
3031 DirectoryInfo projectRoot = new DirectoryInfo ( Application . dataPath ) . Parent ;
@@ -35,11 +36,83 @@ internal static void EnsureMSBuildForUnity()
3536 if ( ! File . Exists ( manifestPath ) )
3637 {
3738 Debug . LogError ( $ "Package manifest file ({ manifestPath } ) could not be found.") ;
38- return ;
39+ return null ;
40+ }
41+
42+ return manifestPath ;
43+ }
44+
45+ /// <summary>
46+ /// Reports whether or not the appropriate version of MSBuild for Unity is specified
47+ /// in the Unity Package Manager manifest.
48+ /// </summary>
49+ /// <returns></returns>
50+ internal static bool IsMSBuildForUnityEnabled ( )
51+ {
52+ string manifestPath = GetPackageManifestFilePath ( ) ;
53+ if ( string . IsNullOrWhiteSpace ( manifestPath ) )
54+ {
55+ return false ;
56+ }
57+
58+ // Load the manifest file.
59+ string manifestFileContents = File . ReadAllText ( manifestPath ) ;
60+ if ( string . IsNullOrWhiteSpace ( manifestFileContents ) )
61+ {
62+ return false ;
63+ }
64+
65+ // Read the package manifest a line at a time.
66+ bool msBuildFound = false ;
67+ bool isAppropriateVersion = false ;
68+ Version minVersion = Version . Parse ( MSBuildPackageVersion ) ;
69+ using ( FileStream manifestStream = new FileStream ( manifestPath , FileMode . Open , FileAccess . Read ) )
70+ {
71+ using ( StreamReader reader = new StreamReader ( manifestStream ) )
72+ {
73+ // Read the manifest file a line at a time.
74+ while ( ! reader . EndOfStream )
75+ {
76+ string line = reader . ReadLine ( ) ;
77+ if ( line . Contains ( MSBuildPackageName ) )
78+ {
79+ msBuildFound = true ;
80+
81+ // Next, check the version.
82+ string [ ] splitLine = line . Split ( new char [ ] { ':' } ) ;
83+ if ( splitLine . Length == 2 )
84+ {
85+ string versionString = splitLine [ 1 ] . Trim ( new char [ ] { ' ' , '\" ' , ',' } ) ;
86+
87+ Version version ;
88+ if ( Version . TryParse ( versionString , out version ) )
89+ {
90+ isAppropriateVersion = version >= minVersion ;
91+ }
92+ }
93+
94+ break ;
95+ }
96+ }
97+ }
3998 }
4099
100+ return ( msBuildFound && isAppropriateVersion ) ;
101+ }
102+
103+ /// <summary>
104+ /// Ensures the required settings exist in the package manager to allow for using MSBuild for Unity.
105+ /// </summary>
106+ internal static void EnsureMSBuildForUnity ( )
107+ {
41108 PackageManifest manifest = null ;
42109
110+ string manifestPath = GetPackageManifestFilePath ( ) ;
111+ if ( string . IsNullOrWhiteSpace ( manifestPath ) )
112+ {
113+ return ;
114+ }
115+
43116 // Read the package manifest into a list of strings (for easy finding of entries)
44117 // and then deserialize.
45118 List < string > manifestFileLines = new List < string > ( ) ;
@@ -102,11 +175,12 @@ internal static void EnsureMSBuildForUnity()
102175 int dependenciesStartIndex = - 1 ;
103176 int scopedRegistriesStartIndex = - 1 ;
104177 int scopedRegistriesEndIndex = - 1 ;
178+ int packageLine = - 1 ;
105179
106180 // Attempt to find the MSBuild for Unity package entry in the dependencies collection
107181 // This loop also identifies the dependecies collection line and the start / end of a
108182 // pre-existing scoped registries collections
109- bool needToAddPackage = true ;
183+ bool addPackage = true ;
110184 for ( int i = 0 ; i < manifestFileLines . Count ; i ++ )
111185 {
112186 if ( manifestFileLines [ i ] . Contains ( "\" scopedRegistries\" :" ) )
@@ -123,55 +197,57 @@ internal static void EnsureMSBuildForUnity()
123197 }
124198 if ( manifestFileLines [ i ] . Contains ( MSBuildPackageName ) )
125199 {
126- needToAddPackage = false ;
200+ packageLine = i ;
201+ addPackage = false ;
127202 }
128203 }
129204
130205 // If no package was found add it to the dependencies collection.
131- if ( needToAddPackage )
206+ if ( addPackage )
132207 {
133208 // Add the package to the collection (pad the entry with four spaces)
134209 manifestFileLines . Insert ( dependenciesStartIndex + 1 , $ " \" { MSBuildPackageName } \" : \" { MSBuildPackageVersion } \" ,") ;
135210 }
136-
137- if ( needToAddRegistry || needToAddPackage )
211+ else
138212 {
139- // If we added a scoped registry or package, rewrite the manifest file.
213+ // Replace the line that currently exists
214+ manifestFileLines [ packageLine ] = $ " \" { MSBuildPackageName } \" : \" { MSBuildPackageVersion } \" ,";
215+ }
140216
141- // First, serialize the scoped registry collection.
142- string serializedRegistriesJson = JsonUtility . ToJson ( manifest , true ) ;
217+ // Update the manifest file.
218+ // First, serialize the scoped registry collection.
219+ string serializedRegistriesJson = JsonUtility . ToJson ( manifest , true ) ;
143220
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 ) )
221+ // Ensure that the file is truncated to ensure it is always valid after writing.
222+ using ( FileStream outFile = new FileStream ( manifestPath , FileMode . Truncate , FileAccess . Write ) )
223+ {
224+ using ( StreamWriter writer = new StreamWriter ( outFile ) )
146225 {
147- using ( StreamWriter writer = new StreamWriter ( outFile ) )
148- {
149- bool scopedRegistriesWritten = false ;
226+ bool scopedRegistriesWritten = false ;
150227
151- // Write each line of the manifest back to the file.
152- for ( int i = 0 ; i < manifestFileLines . Count ; i ++ )
228+ // Write each line of the manifest back to the file.
229+ for ( int i = 0 ; i < manifestFileLines . Count ; i ++ )
230+ {
231+ if ( ( i >= scopedRegistriesStartIndex ) && ( i <= scopedRegistriesEndIndex ) )
153232 {
154- if ( ( i >= scopedRegistriesStartIndex ) && ( i <= scopedRegistriesEndIndex ) )
155- {
156- // Skip these lines, they will be replaced.
157- continue ;
158- }
233+ // Skip these lines, they will be replaced.
234+ continue ;
235+ }
159236
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- }
237+ if ( ! scopedRegistriesWritten && ( i > 0 ) )
238+ {
239+ // Trim the leading '{' and '\n' from the serialized scoped registries
240+ serializedRegistriesJson = serializedRegistriesJson . Remove ( 0 , 2 ) ;
241+ // Trim, the trailing '\n' and '}'
242+ serializedRegistriesJson = serializedRegistriesJson . Remove ( serializedRegistriesJson . Length - 2 ) ;
243+ // Append a trailing ',' to close the scopedRegistries node
244+ serializedRegistriesJson = serializedRegistriesJson . Insert ( serializedRegistriesJson . Length , "," ) ;
245+ writer . WriteLine ( serializedRegistriesJson ) ;
172246
173- writer . WriteLine ( manifestFileLines [ i ] ) ;
247+ scopedRegistriesWritten = true ;
174248 }
249+
250+ writer . WriteLine ( manifestFileLines [ i ] ) ;
175251 }
176252 }
177253 }
0 commit comments