-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathmake_stubs_nuget.py
More file actions
224 lines (183 loc) · 8.94 KB
/
make_stubs_nuget.py
File metadata and controls
224 lines (183 loc) · 8.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
import sys
import os
import helpers
import json
import shutil
def write_csproj_prefix(ioWrapper):
ioWrapper.write('<Project Sdk="Microsoft.NET.Sdk">\n')
ioWrapper.write(' <PropertyGroup>\n')
ioWrapper.write(' <TargetFramework>net7.0</TargetFramework>\n')
ioWrapper.write(' <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n')
ioWrapper.write(' <OutputPath>bin\</OutputPath>\n')
ioWrapper.write(
' <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>\n')
ioWrapper.write(' </PropertyGroup>\n\n')
print('Script to generate stub file from a nuget package')
print(' Usage: python3 ' + sys.argv[0] +
' TEMPLATE NUGET_PACKAGE_NAME [VERSION=latest] [WORK_DIR=tempDir]')
print(' The script uses the dotnet cli, codeql cli, and dotnet format global tool')
print(' TEMPLATE should be either classlib or webapp, depending on the nuget package. For example, `Swashbuckle.AspNetCore.Swagger` should use `webapp` while `newtonsoft.json` should use `classlib`.')
if len(sys.argv) < 2:
print("\nPlease supply a template name.")
exit(1)
if len(sys.argv) < 3:
print("\nPlease supply a nuget package name.")
exit(1)
thisScript = sys.argv[0]
thisDir = os.path.abspath(os.path.dirname(thisScript))
template = sys.argv[1]
nuget = sys.argv[2]
# /input contains a dotnet project that's being extracted
workDir = os.path.abspath(helpers.get_argv(4, "tempDir"))
projectNameIn = "input"
projectDirIn = os.path.join(workDir, projectNameIn)
def run_cmd(cmd, msg="Failed to run command"):
helpers.run_cmd_cwd(cmd, workDir, msg)
# /output contains the output of the stub generation
outputDirName = "output"
outputDir = os.path.join(workDir, outputDirName)
# /output/raw contains the bqrs result from the query, the json equivalent
rawOutputDirName = "raw"
rawOutputDir = os.path.join(outputDir, rawOutputDirName)
os.makedirs(rawOutputDir)
# /output/output contains a dotnet project with the generated stubs
projectNameOut = "output"
projectDirOut = os.path.join(outputDir, projectNameOut)
# /db contains the extracted QL DB
dbName = 'db'
dbDir = os.path.join(workDir, dbName)
outputName = "stub"
outputFile = os.path.join(projectDirOut, outputName + '.cs')
bqrsFile = os.path.join(rawOutputDir, outputName + '.bqrs')
jsonFile = os.path.join(rawOutputDir, outputName + '.json')
version = helpers.get_argv(3, "latest")
print("\n* Creating new input project")
run_cmd(['dotnet', 'new', template, "-f", "net7.0", "--language", "C#", '--name',
projectNameIn, '--output', projectDirIn])
helpers.remove_files(projectDirIn, '.cs')
print("\n* Adding reference to package: " + nuget)
cmd = ['dotnet', 'add', projectDirIn, 'package', nuget]
if (version != "latest"):
cmd.append('--version')
cmd.append(version)
run_cmd(cmd)
sdk_version = '7.0.102'
print("\n* Creating new global.json file and setting SDK to " + sdk_version)
run_cmd(['dotnet', 'new', 'globaljson', '--force', '--sdk-version', sdk_version, '--output', workDir])
print("\n* Running stub generator")
helpers.run_cmd_cwd(['dotnet', 'run', '--project', thisDir + '/../../extractor/Semmle.Extraction.CSharp.DependencyStubGenerator/Semmle.Extraction.CSharp.DependencyStubGenerator.csproj'], projectDirIn)
print("\n* Creating new raw output project")
rawSrcOutputDirName = 'src'
rawSrcOutputDir = os.path.join(rawOutputDir, rawSrcOutputDirName)
run_cmd(['dotnet', 'new', template, "--language", "C#",
'--name', rawSrcOutputDirName, '--output', rawSrcOutputDir])
helpers.remove_files(rawSrcOutputDir, '.cs')
# copy each file from projectDirIn to rawSrcOutputDir
pathInfos = {}
codeqlStubsDir = os.path.join(projectDirIn, 'codeql_csharp_stubs')
for root, dirs, files in os.walk(codeqlStubsDir):
for file in files:
if file.endswith('.cs'):
path = os.path.join(root, file)
relPath, _ = os.path.splitext(os.path.relpath(path, codeqlStubsDir))
origDllPath = "/" + relPath + ".dll"
pathInfos[origDllPath] = os.path.join(rawSrcOutputDir, file)
shutil.copy2(path, rawSrcOutputDir)
print("\n --> Generated stub files: " + rawSrcOutputDir)
print("\n* Formatting files")
run_cmd(['dotnet', 'format', 'whitespace', rawSrcOutputDir])
print("\n --> Generated (formatted) stub files: " + rawSrcOutputDir)
print("\n* Processing project.assets.json to generate folder structure")
stubsDirName = 'stubs'
stubsDir = os.path.join(outputDir, stubsDirName)
os.makedirs(stubsDir)
frameworksDirName = '_frameworks'
frameworksDir = os.path.join(stubsDir, frameworksDirName)
frameworks = set()
copiedFiles = set()
assetsJsonFile = os.path.join(projectDirIn, 'obj', 'project.assets.json')
with open(assetsJsonFile) as json_data:
data = json.load(json_data)
if len(data['targets']) > 1:
print("ERROR: More than one target found in " + assetsJsonFile)
exit(1)
target = list(data['targets'].keys())[0]
print("Found target: " + target)
for package in data['targets'][target].keys():
parts = package.split('/')
name = parts[0]
version = parts[1]
packageDir = os.path.join(stubsDir, name, version)
if not os.path.exists(packageDir):
os.makedirs(packageDir)
print(' * Processing package: ' + name + '/' + version)
with open(os.path.join(packageDir, name + '.csproj'), 'a') as pf:
write_csproj_prefix(pf)
pf.write(' <ItemGroup>\n')
dlls = set()
if 'compile' in data['targets'][target][package]:
for dll in data['targets'][target][package]['compile']:
dlls.add(
(name + '/' + version + '/' + dll).lower())
if 'runtime' in data['targets'][target][package]:
for dll in data['targets'][target][package]['runtime']:
dlls.add((name + '/' + version + '/' + dll).lower())
for pathInfo in pathInfos:
for dll in dlls:
if pathInfo.lower().endswith(dll):
copiedFiles.add(pathInfo)
shutil.copy2(pathInfos[pathInfo], packageDir)
if 'dependencies' in data['targets'][target][package]:
for dependency in data['targets'][target][package]['dependencies'].keys():
depVersion = data['targets'][target][package]['dependencies'][dependency]
pf.write(' <ProjectReference Include="../../' +
dependency + '/' + depVersion + '/' + dependency + '.csproj" />\n')
if 'frameworkReferences' in data['targets'][target][package]:
if not os.path.exists(frameworksDir):
os.makedirs(frameworksDir)
for framework in data['targets'][target][package]['frameworkReferences']:
frameworks.add(framework)
frameworkDir = os.path.join(
frameworksDir, framework)
if not os.path.exists(frameworkDir):
os.makedirs(frameworkDir)
pf.write(' <ProjectReference Include="../../' +
frameworksDirName + '/' + framework + '/' + framework + '.csproj" />\n')
pf.write(' <ProjectReference Include="../../' +
frameworksDirName + '/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj" />\n')
pf.write(' </ItemGroup>\n')
pf.write('</Project>\n')
# Processing references frameworks
for framework in frameworks:
with open(os.path.join(frameworksDir, framework, framework + '.csproj'), 'a') as pf:
write_csproj_prefix(pf)
pf.write(' <ItemGroup>\n')
pf.write(
' <ProjectReference Include="../Microsoft.NETCore.App/Microsoft.NETCore.App.csproj" />\n')
pf.write(' </ItemGroup>\n')
pf.write('</Project>\n')
for pathInfo in pathInfos:
if framework.lower() + '.ref' in pathInfo.lower():
copiedFiles.add(pathInfo)
shutil.copy2(pathInfos[pathInfo], os.path.join(
frameworksDir, framework))
# Processing assemblies in Microsoft.NETCore.App.Ref
frameworkDir = os.path.join(frameworksDir, 'Microsoft.NETCore.App')
if not os.path.exists(frameworkDir):
os.makedirs(frameworkDir)
with open(os.path.join(frameworksDir, 'Microsoft.NETCore.App', 'Microsoft.NETCore.App.csproj'), 'a') as pf:
write_csproj_prefix(pf)
pf.write('</Project>\n')
for pathInfo in pathInfos:
if 'microsoft.netcore.app.ref/' in pathInfo.lower():
copiedFiles.add(pathInfo)
shutil.copy2(pathInfos[pathInfo], frameworkDir)
for pathInfo in pathInfos:
if pathInfo not in copiedFiles:
print('Not copied to nuget or framework folder: ' + pathInfo)
othersDir = os.path.join(stubsDir, 'others')
if not os.path.exists(othersDir):
os.makedirs(othersDir)
shutil.copy2(pathInfos[pathInfo], othersDir)
print("\n --> Generated structured stub files: " + stubsDir)
exit(0)