@@ -6,7 +6,7 @@ import semver = require("semver");
66import npm = require( "npm" ) ;
77import constants = require( "./constants" ) ;
88
9- export class NpmInstallationManager {
9+ export class NpmInstallationManager implements INpmInstallationManager {
1010 private static NPM_LOAD_FAILED = "Failed to retrieve data from npm. Please try again a little bit later." ;
1111 private versionsCache : IDictionary < string [ ] > ;
1212
@@ -27,13 +27,18 @@ export class NpmInstallationManager {
2727 public getCachedPackagePath ( packageName : string , version : string ) : string {
2828 return path . join ( this . getCacheRootPath ( ) , packageName , version , "package" ) ;
2929 }
30-
30+
3131 public addToCache ( packageName : string , version : string ) : IFuture < void > {
3232 return ( ( ) => {
33- this . $npm . cache ( packageName , version ) . wait ( ) ;
34- let packagePath = path . join ( this . getCacheRootPath ( ) , packageName , version , "package" ) ;
35- if ( ! this . isPackageUnpacked ( packagePath ) . wait ( ) ) {
36- this . cacheUnpack ( packageName , version ) . wait ( ) ;
33+ let cachedPackagePath = this . getCachedPackagePath ( packageName , version ) ;
34+ if ( ! this . $fs . exists ( cachedPackagePath ) . wait ( ) ) {
35+ this . addToCacheCore ( packageName , version ) . wait ( ) ;
36+ }
37+
38+ if ( ! this . isShasumOfPackageCorrect ( packageName , version ) . wait ( ) ) {
39+ // In some cases the package is not fully downloaded and the framework directory is missing
40+ // Try removing the old package and add the real one to cache again
41+ this . addCleanCopyToCache ( packageName , version ) . wait ( ) ;
3742 }
3843 } ) . future < void > ( ) ( ) ;
3944 }
@@ -73,6 +78,43 @@ export class NpmInstallationManager {
7378 } ) . future < string > ( ) ( ) ;
7479 }
7580
81+ public addCleanCopyToCache ( packageName : string , version : string ) : IFuture < void > {
82+ return ( ( ) => {
83+ let packagePath = path . join ( this . getCacheRootPath ( ) , packageName , version ) ;
84+ this . $logger . trace ( `Deleting: ${ packagePath } .` ) ;
85+ this . $fs . deleteDirectory ( packagePath ) . wait ( ) ;
86+ this . addToCacheCore ( packageName , version ) . wait ( ) ;
87+ if ( ! this . isShasumOfPackageCorrect ( packageName , version ) . wait ( ) ) {
88+ this . $errors . failWithoutHelp ( `Unable to add package ${ packageName } with version ${ version } to npm cache. Try cleaning your cache and execute the command again.` )
89+ }
90+ } ) . future < void > ( ) ( ) ;
91+ }
92+
93+ private addToCacheCore ( packageName : string , version : string ) : IFuture < void > {
94+ return ( ( ) => {
95+ this . $npm . cache ( packageName , version ) . wait ( ) ;
96+ let packagePath = path . join ( this . getCacheRootPath ( ) , packageName , version , "package" ) ;
97+ if ( ! this . isPackageUnpacked ( packagePath ) . wait ( ) ) {
98+ this . cacheUnpack ( packageName , version ) . wait ( ) ;
99+ }
100+ } ) . future < void > ( ) ( ) ;
101+ }
102+
103+ private isShasumOfPackageCorrect ( packageName : string , version : string ) : IFuture < boolean > {
104+ return ( ( ) : boolean => {
105+ let shasumProperty = "dist.shasum" ;
106+ let cachedPackagePath = this . getCachedPackagePath ( packageName , version ) ;
107+ let realShasum = this . $npm . view ( `${ packageName } @${ version } ` , shasumProperty ) . wait ( ) [ version ] [ shasumProperty ] ;
108+ let packageTgz = cachedPackagePath + ".tgz" ;
109+ let currentShasum = "" ;
110+ if ( this . $fs . exists ( packageTgz ) . wait ( ) ) {
111+ currentShasum = this . $fs . getFileShasum ( packageTgz ) . wait ( ) ;
112+ }
113+ this . $logger . trace ( `Checking shasum of package: ${ packageName } @${ version } : expected ${ realShasum } , actual ${ currentShasum } .` ) ;
114+ return realShasum === currentShasum ;
115+ } ) . future < boolean > ( ) ( ) ;
116+ }
117+
76118 private installCore ( packageName : string , pathToSave : string , version : string ) : IFuture < string > {
77119 return ( ( ) => {
78120 if ( this . $options . frameworkPath ) {
0 commit comments