33using System . IO ;
44using System . Linq ;
55using System . Threading . Tasks ;
6- using System . Xml . Linq ;
76
87namespace Xamarin . Android . Prepare
98{
109 partial class Step_GenerateCGManifest : Step
1110 {
12- static readonly HashSet < string > DevelopmentDependencies = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) {
13- "7-Zip.CommandLine" ,
14- "Kajabity.Tools.Java" ,
15- "Mono.Linq.Expressions" ,
16- "mono/debugger-libs" ,
17- "Newtonsoft.Json" ,
18- "System.CommandLine" ,
19- "Xamarin.Forms" ,
20- "xunit" ,
21- "xunit.abstractions" ,
22- "xunit.analyzers" ,
23- "xunit.assert" ,
24- "xunit.core" ,
25- "xunit.extensibility.core" ,
26- "xunit.extensibility.execution" ,
27- "xunit.runner.utility" ,
28-
29- // ???
30- "Microsoft.Build" ,
31- "Microsoft.Build.Framework" ,
32- "Microsoft.Build.Tasks.Core" ,
33- "Microsoft.Build.Utilities.Core" ,
34- "Microsoft.VisualStudio.CoreUtility" ,
35- "Microsoft.VisualStudio.Imaging" ,
36- "Microsoft.VisualStudio.OLE.Interop" ,
37- "Microsoft.VisualStudio.Shell.15.0" ,
38- "Microsoft.VisualStudio.Shell.Framework" ,
39- "Microsoft.VisualStudio.Shell.Interop" ,
40- "Microsoft.VisualStudio.Shell.Interop.8.0" ,
41- "Microsoft.VisualStudio.Shell.Interop.9.0" ,
42- "Microsoft.VisualStudio.TextManager.Interop" ,
43- "Microsoft.VisualStudio.TextManager.Interop.8.0" ,
44- "Microsoft.VisualStudio.Threading" ,
45- "Microsoft.VisualStudio.Utilities" ,
46- "Microsoft.VisualStudio.Validation" ,
47- "Microsoft.VSSDK.BuildTools" ,
48- } ;
49-
5011 public Step_GenerateCGManifest ( )
51- : base ( "Generate CGManifest .json" )
12+ : base ( "Generate cgmanifest .json" )
5213 { }
5314
5415 protected override async Task < bool > Execute ( Context context )
5516 {
56- var nugets = MSBuildPackageReferenceInfo . GetPackageReferences ( ) ;
5717 var git = new GitRunner ( context ) ;
5818 var gitSubmoduleInfo = await git . ConfigList ( new [ ] { "--blob" , "HEAD:.gitmodules" } ) ;
5919 var gitSubmoduleStatus = await git . SubmoduleStatus ( ) ;
60- var gitSubmodules = GitSubmoduleInfo . GetGitSubmodules ( gitSubmoduleInfo , gitSubmoduleStatus ) ;
20+ var gitSubmodules = GitSubmoduleInfo . GetGitSubmodules ( gitSubmoduleInfo , gitSubmoduleStatus )
21+ . OrderBy ( e => e . RepositoryUrl , StringComparer . OrdinalIgnoreCase ) ;
6122
62- var cgManifestEntries = ( ( IEnumerable < CGManifestEntry > ) nugets ) . Concat ( gitSubmodules )
63- . OrderBy ( e => e . Name ) ;
64-
65- var jsonPath = Path . Combine ( Configurables . Paths . BuildBinDir , "CGManifest.json" ) ;
23+ var jsonPath = Path . Combine ( Configurables . Paths . BuildBinDir , "cgmanifest.json" ) ;
6624 using var json = File . CreateText ( jsonPath ) ;
6725
6826 json . WriteLine ( "{" ) ;
6927 json . WriteLine ( " \" $schema\" : \" https://json.schemastore.org/component-detection-manifest.json\" ," ) ;
7028 json . WriteLine ( " \" version\" : 1," ) ;
7129 json . WriteLine ( " \" registrations\" : [" ) ;
7230
73- var properties = new Dictionary < string , string > ( ) ;
74-
7531 bool first = true ;
7632
77- foreach ( var entry in cgManifestEntries ) {
33+ foreach ( var entry in gitSubmodules ) {
7834 if ( first ) {
79- first = false ;
35+ first = false ;
8036 } else {
8137 json . WriteLine ( "," ) ;
8238 }
8339
84- WriteComponent ( json , entry , properties ) ;
40+ json . WriteLine ( $ " {{") ;
41+ json . WriteLine ( $ " \" component\" : {{") ;
42+ json . WriteLine ( $ " \" type\" : \" git\" ,") ;
43+ json . WriteLine ( $ " \" git\" : {{") ;
44+ json . WriteLine ( $ " \" commitHash\" : \" { entry . CommitHash } \" ,") ;
45+ json . WriteLine ( $ " \" repositoryUrl\" : \" { entry . RepositoryUrl } \" ") ;
46+ json . WriteLine ( $ " }}") ;
47+ json . WriteLine ( $ " }}") ;
48+ json . Write ( $ " }}") ;
8549 }
8650
8751 json . WriteLine ( ) ;
@@ -90,53 +54,11 @@ protected override async Task<bool> Execute (Context context)
9054
9155 return true ;
9256 }
93-
94- void WriteComponent ( TextWriter json , CGManifestEntry entry , Dictionary < string , string > properties )
95- {
96- string dev = DevelopmentDependencies . Contains ( entry . Name )
97- ? "true"
98- : "false" ;
99-
100- properties . Clear ( ) ;
101- entry . FillComponentProperties ( properties ) ;
102-
103- json . WriteLine ( $ " {{") ;
104- json . WriteLine ( $ " \" component\" : {{") ;
105- json . WriteLine ( $ " \" type\" : \" { entry . Type . ToLowerInvariant ( ) } \" ,") ;
106- json . WriteLine ( $ " \" { entry . Type } \" : {{") ;
107- bool firstProp = true ;
108- foreach ( var key in properties . Keys . OrderBy ( p => p , StringComparer . OrdinalIgnoreCase ) ) {
109- var value = properties [ key ] ;
110- if ( firstProp ) {
111- firstProp = false ;
112- } else {
113- json . WriteLine ( "," ) ;
114- }
115- json . Write ( $ " \" { key } \" : \" { value } \" ") ;
116- }
117- json . WriteLine ( ) ;
118- json . WriteLine ( $ " }}") ;
119- json . WriteLine ( $ " }},") ;
120- json . WriteLine ( $ " \" developmentDependency\" :{ dev } ") ;
121- json . Write ( $ " }}") ;
122- }
12357 }
12458
125- abstract class CGManifestEntry {
126-
127- public abstract string Name { get ; }
128- public abstract string Type { get ; }
129-
130- public abstract void FillComponentProperties ( Dictionary < string , string > properties ) ;
131-
132- protected CGManifestEntry ( )
133- {
134- }
135- }
136-
137- sealed class GitSubmoduleInfo : CGManifestEntry {
138-
139- public override string Name {
59+ sealed class GitSubmoduleInfo
60+ {
61+ public string Name {
14062 get {
14163 const string github = "github.com/" ;
14264 int i = RepositoryUrl . IndexOf ( github , StringComparison . OrdinalIgnoreCase ) ;
@@ -146,100 +68,84 @@ public override string Name {
14668 }
14769 }
14870
149- public override string Type => "git" ;
150-
151- public string RepositoryUrl { get ; private set ; } = String . Empty ;
152- public string CommitHash { get ; private set ; } = String . Empty ;
153- public string LocalPath { get ; private set ; } = String . Empty ;
71+ public string RepositoryUrl { get ; private set ; } = String . Empty ;
72+ public string CommitHash { get ; private set ; } = String . Empty ;
73+ public string LocalPath { get ; private set ; } = String . Empty ;
15474
15575 GitSubmoduleInfo ( )
15676 {
15777 }
15878
159- public override void FillComponentProperties ( Dictionary < string , string > properties )
160- {
161- properties [ "repositoryUrl" ] = RepositoryUrl ;
162- properties [ "commitHash" ] = CommitHash ;
163- }
164-
16579 const string Submodule = "submodule.external/" ;
16680
16781 public static IEnumerable < GitSubmoduleInfo > GetGitSubmodules ( List < string > ? config , List < string > ? submoduleStatus )
16882 {
16983 if ( config == null ) {
170- yield return CreateEmptySubmoduleInfo ( ) ;
84+ yield break ;
17185 }
17286
17387 string ? entryId = null ;
17488 string ? path = null ;
17589 string ? url = null ;
17690
177- foreach ( var line in config ! ) {
91+ foreach ( var line in config ) {
17892 if ( ! line . StartsWith ( Submodule , StringComparison . Ordinal ) )
17993 continue ;
18094
18195 string ? id = GetSubmoduleId ( line ) ;
18296 if ( id != entryId ) {
18397 if ( url != null && path != null )
184- yield return CreateSubmoduleInfo ( url , path ) ;
98+ yield return CreateSubmoduleInfo ( url , path , submoduleStatus ) ;
18599
186100 entryId = id ;
187101 path = null ;
188102 url = null ;
189103 }
190104
191- const string Path = ".path=" ;
192- const string Url = ".url=" ;
193- const string Git = ".git" ;
105+ const string Path = ".path=" ;
106+ const string Url = ".url=" ;
107+ const string Git = ".git" ;
194108
195- int pathIndex = line . IndexOf ( Path , StringComparison . Ordinal ) ;
109+ int pathIndex = line . IndexOf ( Path , StringComparison . Ordinal ) ;
196110 if ( pathIndex > 0 ) {
197- path = line . Substring ( pathIndex + Path . Length ) ;
111+ path = line . Substring ( pathIndex + Path . Length ) ;
198112 continue ;
199113 }
200114
201- int urlIndex = line . IndexOf ( Url , StringComparison . Ordinal ) ;
115+ int urlIndex = line . IndexOf ( Url , StringComparison . Ordinal ) ;
202116 if ( urlIndex > 0 ) {
203- int start = urlIndex + Url . Length ;
204- int count = line . Length - start ;
117+ int start = urlIndex + Url . Length ;
118+ int count = line . Length - start ;
205119 if ( line . EndsWith ( Git , StringComparison . Ordinal ) )
206120 count -= Git . Length ;
207- url = line . Substring ( start , count ) ;
121+ url = line . Substring ( start , count ) ;
208122 continue ;
209123 }
210124 }
211125
212126 if ( url != null && path != null )
213- yield return CreateSubmoduleInfo ( url , path ) ;
127+ yield return CreateSubmoduleInfo ( url , path , submoduleStatus ) ;
128+ }
214129
215- GitSubmoduleInfo CreateSubmoduleInfo ( string url , string path )
216- {
217- if ( submoduleStatus == null ) {
218- return CreateEmptySubmoduleInfo ( ) ;
219- }
130+ static GitSubmoduleInfo CreateSubmoduleInfo ( string url , string path , List < string > ? submoduleStatus )
131+ {
132+ string commitHash = String . Empty ;
220133
221- string ? hash = null ;
134+ if ( submoduleStatus ! = null ) {
222135 foreach ( var e in submoduleStatus ) {
223- int pi = e . IndexOf ( path , StringComparison . OrdinalIgnoreCase ) ;
136+ int pi = e . IndexOf ( path , StringComparison . OrdinalIgnoreCase ) ;
224137 if ( pi < 1 || e [ pi - 1 ] != ' ' )
225138 continue ;
226- hash = e . Substring ( 1 , pi - 2 ) ;
139+ commitHash = e . Substring ( 1 , pi - 2 ) ;
227140 break ;
228141 }
229- return new GitSubmoduleInfo ( ) {
230- LocalPath = path ,
231- RepositoryUrl = url ,
232- CommitHash = hash ?? String . Empty ,
233- } ;
234142 }
235143
236- GitSubmoduleInfo CreateEmptySubmoduleInfo ( )
237- {
238- return new GitSubmoduleInfo {
239- RepositoryUrl = String . Empty ,
240- CommitHash = String . Empty ,
241- } ;
242- }
144+ return new GitSubmoduleInfo {
145+ LocalPath = path ,
146+ RepositoryUrl = url ,
147+ CommitHash = commitHash ,
148+ } ;
243149 }
244150
245151 static string ? GetSubmoduleId ( string line )
@@ -251,86 +157,4 @@ GitSubmoduleInfo CreateEmptySubmoduleInfo ()
251157 return line . Substring ( Submodule . Length , lastDot - Submodule . Length ) ;
252158 }
253159 }
254-
255- sealed class MSBuildPackageReferenceInfo : CGManifestEntry {
256-
257- string name ;
258-
259- public override string Name => name ;
260- public override string Type => "nuget" ;
261-
262- public string Version { get ; private set ; }
263-
264- MSBuildPackageReferenceInfo ( string name , string version )
265- {
266- this . name = name ;
267- Version = version ;
268- }
269-
270- public override void FillComponentProperties ( Dictionary < string , string > properties )
271- {
272- properties [ "name" ] = Name ;
273- properties [ "version" ] = Version ;
274- }
275-
276- static readonly XNamespace MSBuildXmlns = XNamespace . Get ( "http://schemas.microsoft.com/developer/msbuild/2003" ) ;
277-
278- public static IEnumerable < MSBuildPackageReferenceInfo > GetPackageReferences ( )
279- {
280- var files = Directory . EnumerateFiles ( BuildPaths . XamarinAndroidSourceRoot , "*.csproj" , SearchOption . AllDirectories )
281- . Concat ( Directory . EnumerateFiles ( BuildPaths . XamarinAndroidSourceRoot , "*.targets" , SearchOption . AllDirectories ) )
282- . Concat ( Directory . EnumerateFiles ( BuildPaths . XamarinAndroidSourceRoot , "*.projitems" , SearchOption . AllDirectories ) )
283- ;
284- var packages = new Dictionary < string , HashSet < string > > ( ) ;
285- var versions = new Dictionary < string , HashSet < string > > ( ) ;
286- foreach ( var file in files ) {
287- var contents = File . ReadAllText ( file ) ;
288- if ( contents . IndexOf ( "PackageReference" , StringComparison . Ordinal ) < 0 ||
289- contents . IndexOf ( "PropertyGroup" , StringComparison . Ordinal ) < 0 )
290- continue ;
291- var proj = XDocument . Parse ( contents ) ;
292- var packageReferences = proj . Elements ( MSBuildXmlns + "Project" )
293- . Elements ( MSBuildXmlns + "ItemGroup" )
294- . Elements ( MSBuildXmlns + "PackageReference" ) ;
295- foreach ( var packageReference in packageReferences ) {
296- var name = ( string ? ) packageReference . Attribute ( "Include" ) ;
297- var version = ( string ? ) packageReference . Attribute ( "Version" ) ??
298- packageReference . Element ( MSBuildXmlns + "Version" ) ? . Value ;
299- if ( name == null || version == null )
300- continue ;
301- if ( ! packages . TryGetValue ( name , out var v ) ) {
302- packages . Add ( name , v = new HashSet < string > ( ) ) ;
303- }
304- v . Add ( version ) ;
305- }
306- var properties = proj . Elements ( MSBuildXmlns + "Project" )
307- . Elements ( MSBuildXmlns + "PropertyGroup" )
308- . Elements ( ) ;
309- foreach ( var property in properties ) {
310- var name = $ "$({ property . Name . LocalName } )";
311- if ( ! property . Name . LocalName . EndsWith ( "Version" , StringComparison . Ordinal ) )
312- continue ;
313- if ( ! versions . TryGetValue ( name , out var v ) ) {
314- versions . Add ( name , v = new HashSet < string > ( ) ) ;
315- }
316- v . Add ( property . Value . Trim ( ) ) ;
317- }
318- }
319-
320- foreach ( var package in packages ) {
321- string name = package . Key ;
322- foreach ( var version in package . Value ) {
323- if ( version . Length > 0 && version [ 0 ] != '$' ) {
324- yield return new MSBuildPackageReferenceInfo ( name , version ) ;
325- continue ;
326- }
327- if ( ! versions . TryGetValue ( version , out var propertyVersions ) )
328- continue ;
329- foreach ( var propertyVersion in propertyVersions ) {
330- yield return new MSBuildPackageReferenceInfo ( name , propertyVersion ) ;
331- }
332- }
333- }
334- }
335- }
336160}
0 commit comments