3
3
using System . Collections . Generic ;
4
4
using System . Linq ;
5
5
using System . IO ;
6
+ using System . Reflection . Metadata ;
7
+ using System . Reflection . PortableExecutable ;
6
8
using System . Runtime . Versioning ;
7
9
using NuGet ;
8
10
using Microsoft . Framework . Runtime . DependencyManagement ;
9
- using Microsoft . Framework . Runtime ;
10
11
11
12
namespace Microsoft . Framework . PackageManager . Utils
12
13
{
13
14
internal static class LockFileUtils
14
15
{
15
- public static LockFileLibrary CreateLockFileLibraryForProject ( Runtime . Project project , IPackage package , SHA512 sha512 , IEnumerable < FrameworkName > frameworks )
16
+ public static LockFileLibrary CreateLockFileLibraryForProject (
17
+ Runtime . Project project ,
18
+ IPackage package ,
19
+ SHA512 sha512 ,
20
+ IEnumerable < FrameworkName > frameworks ,
21
+ IPackagePathResolver resolver )
16
22
{
17
23
var lockFileLib = new LockFileLibrary ( ) ;
18
24
lockFileLib . Name = package . Id ;
@@ -86,6 +92,17 @@ public static LockFileLibrary CreateLockFileLibraryForProject(Runtime.Project pr
86
92
lockFileLib . FrameworkGroups . Add ( group ) ;
87
93
}
88
94
95
+ var installPath = resolver . GetInstallPath ( package . Id , package . Version ) ;
96
+ foreach ( var assembly in lockFileLib . FrameworkGroups . SelectMany ( f => f . RuntimeAssemblies ) )
97
+ {
98
+ var assemblyPath = Path . Combine ( installPath , assembly ) ;
99
+ if ( IsAssemblyServiceable ( assemblyPath ) )
100
+ {
101
+ lockFileLib . IsServiceable = true ;
102
+ break ;
103
+ }
104
+ }
105
+
89
106
return lockFileLib ;
90
107
}
91
108
@@ -129,5 +146,102 @@ private static List<string> GetPackageAssemblies(IPackage package, FrameworkName
129
146
return results ;
130
147
}
131
148
149
+ internal static bool IsAssemblyServiceable ( string assemblyPath )
150
+ {
151
+ if ( ! File . Exists ( assemblyPath ) )
152
+ {
153
+ return false ;
154
+ }
155
+
156
+ using ( var stream = File . OpenRead ( assemblyPath ) )
157
+ using ( var peReader = new PEReader ( stream ) )
158
+ {
159
+ var mdReader = peReader . GetMetadataReader ( ) ;
160
+ var attrs = mdReader . GetAssemblyDefinition ( ) . GetCustomAttributes ( )
161
+ . Select ( ah => mdReader . GetCustomAttribute ( ah ) ) ;
162
+
163
+ foreach ( var attr in attrs )
164
+ {
165
+ var ctorHandle = attr . Constructor ;
166
+ if ( ctorHandle . Kind != HandleKind . MemberReference )
167
+ {
168
+ continue ;
169
+ }
170
+
171
+ var container = mdReader . GetMemberReference ( ( MemberReferenceHandle ) ctorHandle ) . Parent ;
172
+ var name = mdReader . GetTypeReference ( ( TypeReferenceHandle ) container ) . Name ;
173
+ if ( ! string . Equals ( mdReader . GetString ( name ) , "AssemblyMetadataAttribute" ) )
174
+ {
175
+ continue ;
176
+ }
177
+
178
+ var arguments = GetFixedStringArguments ( mdReader , attr ) ;
179
+ if ( arguments . Count == 2 &&
180
+ string . Equals ( arguments [ 0 ] , "Serviceable" , StringComparison . OrdinalIgnoreCase ) &&
181
+ string . Equals ( arguments [ 1 ] , "True" , StringComparison . OrdinalIgnoreCase ) )
182
+ {
183
+ return true ;
184
+ }
185
+ }
186
+ }
187
+
188
+ return false ;
189
+ }
190
+
191
+ /// <summary>
192
+ /// Gets the fixed (required) string arguments of a custom attribute.
193
+ /// Only attributes that have only fixed string arguments.
194
+ /// </summary>
195
+ private static List < string > GetFixedStringArguments ( MetadataReader reader , CustomAttribute attribute )
196
+ {
197
+ // TODO: Nick Guerrera ([email protected] ) hacked this method for temporary use.
198
+ // There is a blob decoder feature in progress but it won't ship in time for our milestone.
199
+ // Replace this method with the blob decoder feature when later it is availale.
200
+
201
+ var signature = reader . GetMemberReference ( ( MemberReferenceHandle ) attribute . Constructor ) . Signature ;
202
+ var signatureReader = reader . GetBlobReader ( signature ) ;
203
+ var valueReader = reader . GetBlobReader ( attribute . Value ) ;
204
+ var arguments = new List < string > ( ) ;
205
+
206
+ var prolog = valueReader . ReadUInt16 ( ) ;
207
+ if ( prolog != 1 )
208
+ {
209
+ // Invalid custom attribute prolog
210
+ return arguments ;
211
+ }
212
+
213
+ var header = signatureReader . ReadSignatureHeader ( ) ;
214
+ if ( header . Kind != SignatureKind . Method || header . IsGeneric )
215
+ {
216
+ // Invalid custom attribute constructor signature
217
+ return arguments ;
218
+ }
219
+
220
+ int parameterCount ;
221
+ if ( ! signatureReader . TryReadCompressedInteger ( out parameterCount ) )
222
+ {
223
+ // Invalid custom attribute constructor signature
224
+ return arguments ;
225
+ }
226
+
227
+ var returnType = signatureReader . ReadSignatureTypeCode ( ) ;
228
+ if ( returnType != SignatureTypeCode . Void )
229
+ {
230
+ // Invalid custom attribute constructor signature
231
+ return arguments ;
232
+ }
233
+
234
+ for ( int i = 0 ; i < parameterCount ; i ++ )
235
+ {
236
+ var signatureTypeCode = signatureReader . ReadSignatureTypeCode ( ) ;
237
+ if ( signatureTypeCode == SignatureTypeCode . String )
238
+ {
239
+ // Custom attribute constructor must take only strings
240
+ arguments . Add ( valueReader . ReadSerializedString ( ) ) ;
241
+ }
242
+ }
243
+
244
+ return arguments ;
245
+ }
132
246
}
133
247
}
0 commit comments