@@ -55,6 +55,7 @@ import { TodoAttributes } from "./models/todo";
5555import { HeaderAttributes } from "./models/header" ;
5656import { LicenseReferenceAttributes } from "./models/licenseReference" ;
5757import { LicenseRuleReferenceAttributes } from "./models/licenseRuleReference" ;
58+ import { NO_RESOURCES_ERROR } from "../constants/errors" ;
5859
5960const { version : workbenchVersion } = packageJson ;
6061
@@ -282,12 +283,12 @@ export class WorkbenchDB {
282283 fileList . forEach ( ( file ) => {
283284 const fileParentPath = file . getDataValue ( "parent" ) ;
284285 const fileNode = pathToNodeMap . get ( file . getDataValue ( "path" ) ) ;
285- if ( Number ( file . getDataValue ( "id" ) ) !== 0 ) {
286+ if ( file . getDataValue ( "parent" ) === "#" ) {
287+ roots . push ( fileNode ) ;
288+ } else {
286289 if ( pathToNodeMap . has ( fileParentPath ) ) {
287290 pathToNodeMap . get ( fileParentPath ) . children ?. push ( fileNode ) ;
288291 }
289- } else {
290- roots . push ( fileNode ) ;
291292 }
292293 } ) ;
293294
@@ -309,11 +310,10 @@ export class WorkbenchDB {
309310 const stream = fs . createReadStream ( jsonFilePath , { encoding : "utf8" } ) ;
310311 let files_count = 0 ;
311312 let dirs_count = 0 ;
312- let index = 0 ;
313- let rootPath : string | null = null ;
314- let hasRootPath = false ;
315313 const batchSize = 1000 ;
316314 let files : Resource [ ] = [ ] ;
315+ const parsedFilePaths = new Set < string > ( ) ;
316+
317317 let progress = 0 ;
318318 let promiseChain : Promise < unknown > = this . sync ;
319319
@@ -379,38 +379,40 @@ export class WorkbenchDB {
379379 . on ( "data" , function ( file ?: Resource ) {
380380 if ( ! file ) return ;
381381
382- if ( ! rootPath ) {
383- rootPath = file . path . split ( "/" ) [ 0 ] ;
384- }
385- if ( rootPath === file . path ) {
386- hasRootPath = true ;
387- }
388382 // @TODO : When/if scancode reports directories in its header, this needs
389383 // to be replaced.
390- if ( index === 0 ) {
384+ if ( parsedFilePaths . size === 0 ) {
391385 dirs_count = file . dirs_count ;
392386 }
393- file . id = index ++ ;
387+ file . id = parsedFilePaths . size ;
394388
395389 primaryPromise . _parseLicenseDetections ( file , TopLevelData ) ;
396390 primaryPromise . _parseLicenseClues ( file , TopLevelData ) ;
397391
398392 files . push ( file ) ;
393+ parsedFilePaths . add ( file . path ) ;
394+
399395 if ( files . length >= batchSize ) {
400396 // Need to set a new variable before handing to promise
401397 this . pause ( ) ;
402398
403399 promiseChain = promiseChain
400+ . then ( ( ) =>
401+ primaryPromise . _imputeIntermediateDirectories (
402+ files ,
403+ parsedFilePaths
404+ )
405+ )
404406 . then ( ( ) => primaryPromise . _batchCreateFiles ( files ) )
405407 . then ( ( ) => {
406408 const currentProgress = Math . round (
407- ( index / ( files_count + dirs_count ) ) * 100
409+ ( parsedFilePaths . size / ( files_count + dirs_count ) ) * 100
408410 ) ;
409411 if ( currentProgress > progress ) {
410412 progress = currentProgress ;
411413 console . info (
412414 `Batch-${ ++ batchCount } completed, \n` ,
413- `JSON Import progress @ ${ progress } % -- ${ index } /${ files_count } +${ dirs_count } `
415+ `JSON Import progress @ ${ progress } % -- ${ parsedFilePaths . size } /${ files_count } +${ dirs_count } `
414416 ) ;
415417 onProgressUpdate ( progress ) ;
416418 }
@@ -426,22 +428,20 @@ export class WorkbenchDB {
426428 // Add root directory into data
427429 // See https://github.com/nexB/scancode-toolkit/issues/543
428430 promiseChain
431+ . then ( ( ) =>
432+ this . _imputeIntermediateDirectories ( files , parsedFilePaths )
433+ )
429434 . then ( ( ) => {
430- if ( rootPath && ! hasRootPath ) {
431- files . push ( {
432- path : rootPath ,
433- name : rootPath ,
434- type : "directory" ,
435- files_count : files_count ,
436- } ) ;
435+ if ( files . length === 0 ) {
436+ throw new Error ( NO_RESOURCES_ERROR ) ;
437437 }
438438 } )
439439 . then ( ( ) => this . _batchCreateFiles ( files ) )
440440 . then ( ( ) => this . db . Header . create ( TopLevelData . parsedHeader ) )
441441 . then ( ( ) => {
442442 console . info (
443443 `Batch-${ ++ batchCount } completed, \n` ,
444- `JSON Import progress @ ${ progress } % -- ${ index } /${ files_count } +${ dirs_count } `
444+ `JSON Import progress @ ${ progress } % -- ${ parsedFilePaths . size } /${ files_count } +${ dirs_count } `
445445 ) ;
446446 onProgressUpdate ( 90 ) ;
447447 } )
@@ -456,10 +456,12 @@ export class WorkbenchDB {
456456 . then ( ( ) => {
457457 onProgressUpdate ( 100 ) ;
458458 console . info ( "JSON parse completed (final step)" ) ;
459- console . timeEnd ( "json-parse-time" ) ;
460459 resolve ( ) ;
461460 } )
462- . catch ( ( e : unknown ) => reject ( e ) ) ;
461+ . catch ( ( e : unknown ) => reject ( e ) )
462+ . finally ( ( ) => {
463+ console . timeEnd ( "json-parse-time" ) ;
464+ } ) ;
463465 } )
464466 . on ( "error" , ( err : unknown ) => {
465467 console . error (
@@ -600,7 +602,7 @@ export class WorkbenchDB {
600602 duration : header . duration ,
601603 options : header ?. options || { } ,
602604 input,
603- files_count : header . extra_data ?. files_count ,
605+ files_count : header . extra_data ?. files_count || 0 ,
604606 output_format_version : header . output_format_version ,
605607 spdx_license_list_version : header . extra_data ?. spdx_license_list_version ,
606608 operating_system : header . extra_data ?. system_environment ?. operating_system ,
@@ -880,6 +882,39 @@ export class WorkbenchDB {
880882 } ) ;
881883 }
882884
885+ // Adds & modifies files array in place, adding missing intermediate directories
886+ _imputeIntermediateDirectories (
887+ files : Resource [ ] ,
888+ parsedFilePaths : Set < string >
889+ ) {
890+ const intermediateDirectories : Resource [ ] = [ ] ;
891+
892+ files . forEach ( ( file ) => {
893+ file . parent = parentPath ( file . path ) ;
894+
895+ // Add intermediate directories if parent not available in files
896+ if ( ! parsedFilePaths . has ( file . parent ) ) {
897+ for (
898+ let currentDir = file . parent ;
899+ currentDir !== parentPath ( currentDir ) &&
900+ ! parsedFilePaths . has ( currentDir ) ;
901+ currentDir = parentPath ( currentDir )
902+ ) {
903+ intermediateDirectories . push ( {
904+ id : parsedFilePaths . size ,
905+ path : currentDir ,
906+ parent : parentPath ( currentDir ) ,
907+ name : path . basename ( currentDir ) ,
908+ type : "directory" ,
909+ files_count : 0 ,
910+ } ) ;
911+ parsedFilePaths . add ( currentDir ) ;
912+ }
913+ }
914+ } ) ;
915+ files . push ( ...intermediateDirectories ) ;
916+ }
917+
883918 _batchCreateFiles ( files : Resource [ ] ) {
884919 // Add batched files to the DB
885920 return this . _addFlattenedFiles ( files ) . then ( ( ) => this . _addFiles ( files ) ) ;
0 commit comments