Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit f091721

Browse files
Chris McConnellmunozemiliovishwacsena
authored
Follow nuget package references. (#755)
* Bump version (#746) * Bump version * Update botframework-cli-mac.yml * update package.json (#750) * Adding Dialog to CLI core * Follow nuget package references. Fix some typos. * Remove readme changes. Co-authored-by: Emilio Munoz <[email protected]> Co-authored-by: Vishwac Sena Kannan <[email protected]>
1 parent 5a7c8cd commit f091721

File tree

3 files changed

+123
-41
lines changed

3 files changed

+123
-41
lines changed

.vscode/launch.json

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
],
1717
"args": [
1818
"luis:build",
19-
"--luConfig",
19+
"--luConfig",
2020
"${env:TEMP}/sandwich.out/luconfig.json"
2121
],
2222
"internalConsoleOptions": "openOnSessionStart",
@@ -183,7 +183,7 @@
183183
{
184184
"type": "node",
185185
"request": "launch",
186-
"name": "Dialog merge test schema",
186+
"name": "Bot Builder merge test schema",
187187
"preLaunchTask": "${defaultBuildTask}",
188188
"program": "${workspaceFolder}/packages/dialog/bin/run",
189189
"outputCapture": "std",
@@ -200,6 +200,26 @@
200200
"internalConsoleOptions": "openOnSessionStart",
201201
"cwd": "${workspaceFolder}/packages/dialog/test/commands/dialog"
202202
},
203+
{
204+
"type": "node",
205+
"request": "launch",
206+
"name": "Runbot schema",
207+
"preLaunchTask": "${defaultBuildTask}",
208+
"program": "${workspaceFolder}/packages/dialog/bin/run",
209+
"outputCapture": "std",
210+
"outFiles": [
211+
"./packages/dialog/lib/**"
212+
],
213+
"args": [
214+
"dialog:merge",
215+
"runbot.csproj",
216+
"-o",
217+
"runbot.schema",
218+
"--verbose"
219+
],
220+
"internalConsoleOptions": "openOnSessionStart",
221+
"cwd": "${workspaceFolder}/../botbuilder-samples/experimental/generation/runbot/"
222+
},
203223
{
204224
"type": "node",
205225
"request": "launch",
@@ -213,10 +233,10 @@
213233
],
214234
"args": [
215235
"luis:build",
216-
"--in",
217-
".",
218236
"--luConfig",
219-
"luconfig.json"
237+
"luconfig.json",
238+
"--authoringKey",
239+
"${env:LUIS_AUTHORING_KEY}"
220240
],
221241
"internalConsoleOptions": "openOnSessionStart",
222242
"cwd": "${env:TEMP}/sandwich.out"

packages/dialog/src/library/schemaMerger.ts

Lines changed: 97 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export default class SchemaMerger {
6161

6262
// State tracking
6363
private readonly projects = {}
64+
private nugetRoot = ''
6465
private readonly validator = new Validator()
6566
private metaSchemaId = ''
6667
private metaSchema: any
@@ -295,7 +296,78 @@ export default class SchemaMerger {
295296
return ppath.normalize(path)
296297
}
297298

298-
// Expand .csproj packages and projects
299+
// Expand nuget package and all of its dependencies
300+
async expandNuget(packageName: string, minVersion: string, root: boolean): Promise<string[]> {
301+
let packages: string[] = []
302+
let pkgPath = ppath.join(this.nugetRoot, packageName)
303+
if (!this.projects[pkgPath] && !packageName.startsWith('System')) {
304+
let oldFile = this.currentFile
305+
try {
306+
this.currentFile = pkgPath
307+
this.projects[pkgPath] = true
308+
let versions: string[] = []
309+
if (await fs.pathExists(pkgPath)) {
310+
for (let pkgVersion of await fs.readdir(pkgPath)) {
311+
versions.push(pkgVersion.toLowerCase())
312+
}
313+
minVersion = minVersion || '0.0.0'
314+
// NOTE: The semver package does not handle more complex nuget range revisions
315+
// We get an exception and will ignore those dependencies.
316+
let version = semver.minSatisfying(versions, minVersion)
317+
pkgPath = this.normalize(ppath.join(pkgPath, version || ''))
318+
this.currentFile = pkgPath
319+
packages.push(pkgPath)
320+
if (this.verbose) {
321+
this.log(` Following nuget ${this.prettyPath(pkgPath)}`)
322+
}
323+
let nuspecPath = ppath.join(pkgPath, `${packageName}.nuspec`)
324+
if (await fs.pathExists(nuspecPath)) {
325+
let nuspec = await this.xmlToJSON(nuspecPath)
326+
let dependencies: any[] = []
327+
walkJSON(nuspec, val => {
328+
if (val.dependencies) {
329+
// NOTE: We assume first framework with dependencies has schema files.
330+
for (let groups of val.dependencies) {
331+
if (groups.dependency) {
332+
// Direct dependencies
333+
for (let dependency of groups.dependency) {
334+
dependencies.push(dependency.$)
335+
}
336+
break
337+
} else {
338+
// Grouped dependencies
339+
for (let group of groups.group) {
340+
if (group.dependency) {
341+
for (let dependency of group.dependency) {
342+
dependencies.push(dependency.$)
343+
}
344+
break
345+
}
346+
}
347+
}
348+
}
349+
return true
350+
}
351+
return false
352+
})
353+
for (let dependent of dependencies) {
354+
let dependentPackages = await this.expandNuget(dependent.id, dependent.version, false)
355+
packages = [...packages, ...dependentPackages]
356+
}
357+
}
358+
} else if (root) {
359+
this.parsingError(' Nuget package does not exist')
360+
}
361+
} catch (e) {
362+
this.parsingWarning(e.message)
363+
} finally {
364+
this.currentFile = oldFile
365+
}
366+
}
367+
return packages
368+
}
369+
370+
// Expand .csproj packages, nugets and projects
299371
async expandCSProj(path: string): Promise<string[]> {
300372
let references: string[] = []
301373
if (!this.projects[path]) {
@@ -306,41 +378,30 @@ export default class SchemaMerger {
306378
}
307379
references.push(this.normalize(ppath.join(ppath.dirname(path), '/**/*.schema')))
308380
let json = await this.xmlToJSON(path)
309-
let packages = await this.findGlobalNuget()
310-
if (packages) {
381+
await this.findGlobalNuget()
382+
if (this.nugetRoot !== '') {
383+
let nugetPackages: any[] = []
311384
walkJSON(json, elt => {
312385
if (elt.PackageReference) {
313386
for (let pkgRef of elt.PackageReference) {
314-
let pkg = pkgRef.$
315-
let pkgName = pkg.Include
316-
let pkgPath = ppath.join(packages, pkgName)
317-
let versions: string[] = []
318-
if (fs.pathExistsSync(pkgPath)) {
319-
for (let version of fs.readdirSync(pkgPath)) {
320-
versions.push(version.toLowerCase())
321-
}
322-
let baseVersion = pkg.Version || '0.0.0'
323-
let version = semver.minSatisfying(versions, `>=${baseVersion.toLowerCase()}`)
324-
pkgPath = this.normalize(ppath.join(pkgPath, version || '', '**/*.schema'))
325-
references.push(pkgPath)
326-
if (this.verbose) {
327-
this.log(` Following nuget ${this.prettyPath(pkgPath)}`)
328-
}
329-
} else {
330-
this.parsingError(`Nuget package does not exist ${pkgPath}`)
331-
}
387+
nugetPackages.push(pkgRef.$)
332388
}
333389
return true
334390
}
335391
return false
336392
})
393+
for (let pkg of nugetPackages) {
394+
let nugetReferences = await this.expandNuget(pkg.Include, pkg.Version, true)
395+
for (let nuget of nugetReferences) {
396+
references.push(this.normalize(ppath.join(nuget, '**/*.schema')))
397+
}
398+
}
337399
}
338400
let projects: string[] = []
339401
walkJSON(json, elt => {
340402
if (elt.ProjectReference) {
341403
for (let ref of elt.ProjectReference) {
342-
let project = ref.$
343-
let projectPath = this.normalize(ppath.join(ppath.dirname(path), project.Include))
404+
let projectPath = this.normalize(ppath.join(ppath.dirname(path), ref.$.Include))
344405
projects.push(projectPath)
345406
}
346407
return true
@@ -419,19 +480,20 @@ export default class SchemaMerger {
419480
}
420481

421482
// Find the global nuget repository
422-
async findGlobalNuget(): Promise<string> {
423-
let result = ''
424-
try {
425-
const {stdout} = await exec('dotnet nuget locals global-packages --list')
426-
const name = 'global-packages:'
427-
let start = stdout.indexOf(name)
428-
if (start > -1) {
429-
result = stdout.substring(start + name.length).trim()
430-
}
431-
} catch {
432-
this.parsingError('Cannot find global nuget packages')
483+
async findGlobalNuget(): Promise<void> {
484+
if (!this.nugetRoot) {
485+
this.nugetRoot = ''
486+
try {
487+
const {stdout} = await exec('dotnet nuget locals global-packages --list')
488+
const name = 'global-packages:'
489+
let start = stdout.indexOf(name)
490+
if (start > -1) {
491+
this.nugetRoot = stdout.substring(start + name.length).trim()
492+
}
493+
} catch {
494+
this.parsingError('Cannot find global nuget packages')
495+
}
433496
}
434-
return result
435497
}
436498

437499
// Convert XML to JSON

packages/qnamaker/src/commands/qnamaker/build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default class QnamakerBuild extends Command {
3535
fallbackLocale: flags.string({description: 'Locale to be used at the fallback if no locale specific recognizer is found. Only valid if --dialog is set'}),
3636
suffix: flags.string({description: 'Environment name as a suffix identifier to include in qnamaker kb name. Defaults to current logged in user alias'}),
3737
dialog: flags.string({description: 'Write out .dialog files whose recognizer type [multiLanguage|crosstrained] is specified by --dialog', default: 'multiLanguage'}),
38-
force: flags.boolean({char: 'f', description: 'If --dialog flag is provided, overwirtes relevant dialog file', default: false}),
38+
force: flags.boolean({char: 'f', description: 'If --dialog flag is provided, overwrites relevant dialog file', default: false}),
3939
log: flags.boolean({description: 'write out log messages to console', default: false}),
4040
}
4141

0 commit comments

Comments
 (0)