3939define ( function ( require , exports , module ) {
4040 "use strict" ;
4141
42- var FileUtils = require ( "file/FileUtils" ) ,
42+ var _ = require ( "thirdparty/lodash" ) ,
43+ FileUtils = require ( "file/FileUtils" ) ,
4344 Package = require ( "extensibility/Package" ) ,
4445 Async = require ( "utils/Async" ) ,
4546 ExtensionLoader = require ( "utils/ExtensionLoader" ) ,
@@ -105,13 +106,28 @@ define(function (require, exports, module) {
105106 }
106107
107108 entry . installInfo . owner = entry . registryInfo . owner ;
108- if ( entry . installInfo . metadata && entry . installInfo . metadata . version && semver . lt ( entry . installInfo . metadata . version , entry . registryInfo . metadata . version ) ) {
109+
110+ // Assume false
111+ entry . installInfo . updateAvailable = false ;
112+ entry . registryInfo . updateAvailable = false ;
113+ entry . installInfo . updateCompatible = false ;
114+ entry . registryInfo . updateCompatible = false ;
115+
116+ var currentVersion = entry . installInfo . metadata ? entry . installInfo . metadata . version : null ;
117+ if ( currentVersion && semver . lt ( currentVersion , entry . registryInfo . metadata . version ) ) {
109118 // Note: available update may still be incompatible; we check for this when rendering the Update button in ExtensionManagerView._renderItem()
110- entry . registryInfo . updateAvailable = true ;
111- entry . installInfo . updateAvailable = true ;
112- } else {
113- entry . installInfo . updateAvailable = false ;
114- entry . registryInfo . updateAvailable = false ;
119+ entry . registryInfo . updateAvailable = true ;
120+ entry . installInfo . updateAvailable = true ;
121+ // Calculate updateCompatible to check if there's an update for current version of Brackets
122+ var lastCompatibleVersionInfo = _ . findLast ( entry . registryInfo . versions , function ( versionInfo ) {
123+ return semver . satisfies ( brackets . metadata . apiVersion , versionInfo . brackets ) ;
124+ } ) ;
125+ if ( lastCompatibleVersionInfo && lastCompatibleVersionInfo . version && semver . lt ( currentVersion , lastCompatibleVersionInfo . version ) ) {
126+ entry . installInfo . updateCompatible = true ;
127+ entry . registryInfo . updateCompatible = true ;
128+ entry . installInfo . lastCompatibleVersion = lastCompatibleVersionInfo . version ;
129+ entry . registryInfo . lastCompatibleVersion = lastCompatibleVersionInfo . version ;
130+ }
115131 }
116132
117133 $ ( exports ) . triggerHandler ( "registryUpdate" , [ id ] ) ;
@@ -160,6 +176,7 @@ define(function (require, exports, module) {
160176 extensions [ id ] . registryInfo = data [ id ] ;
161177 synchronizeEntry ( id ) ;
162178 } ) ;
179+ $ ( exports ) . triggerHandler ( "registryDownload" ) ;
163180 result . resolve ( ) ;
164181 } )
165182 . fail ( function ( ) {
@@ -506,39 +523,94 @@ define(function (require, exports, module) {
506523 ) ;
507524 }
508525
526+ /**
527+ * Gets an array of extensions that are currently installed and can be updated to a new version
528+ * @return {Array.<{id: string, installVersion: string, registryVersion: string}> }
529+ * where id = extensionId
530+ * installVersion = currently installed version of extension
531+ * registryVersion = latest version compatible with current Brackets
532+ */
533+ function getAvailableUpdates ( ) {
534+ var result = [ ] ;
535+ Object . keys ( extensions ) . forEach ( function ( extensionId ) {
536+ var extensionInfo = extensions [ extensionId ] ;
537+ // skip extensions that are not installed or are not in the registry
538+ if ( ! extensionInfo . installInfo || ! extensionInfo . registryInfo ) {
539+ return ;
540+ }
541+ if ( extensionInfo . registryInfo . updateCompatible ) {
542+ result . push ( {
543+ id : extensionId ,
544+ installVersion : extensionInfo . installInfo . metadata . version ,
545+ registryVersion : extensionInfo . registryInfo . lastCompatibleVersion
546+ } ) ;
547+ }
548+ } ) ;
549+ return result ;
550+ }
551+
552+ /**
553+ * Takes the array returned from getAvailableUpdates() as an input and removes those entries
554+ * that are no longer current - when currently installed version of an extension
555+ * is equal or newer than registryVersion returned by getAvailableUpdates().
556+ * This function is designed to work without the necessity to download extension registry
557+ * @param {Array.<{id: string, installVersion: string, registryVersion: string}> } updates
558+ * previous output of getAvailableUpdates()
559+ * @return {Array.<{id: string, installVersion: string, registryVersion: string}> }
560+ * filtered input as function description
561+ */
562+ function cleanAvailableUpdates ( updates ) {
563+ return updates . reduce ( function ( arr , updateInfo ) {
564+ var extDefinition = extensions [ updateInfo . id ] ;
565+ if ( ! extDefinition || ! extDefinition . installInfo ) {
566+ // extension has been uninstalled in the meantime
567+ return arr ;
568+ }
569+
570+ var installedVersion = extDefinition . installInfo . metadata . version ;
571+ if ( semver . lt ( installedVersion , updateInfo . registryVersion ) ) {
572+ arr . push ( updateInfo ) ;
573+ }
574+
575+ return arr ;
576+ } , [ ] ) ;
577+ }
578+
509579 // Listen to extension load and loadFailed events
510580 $ ( ExtensionLoader )
511581 . on ( "load" , _handleExtensionLoad )
512582 . on ( "loadFailed" , _handleExtensionLoad ) ;
513583
514584 // Public exports
515- exports . downloadRegistry = downloadRegistry ;
516- exports . getCompatibilityInfo = getCompatibilityInfo ;
517- exports . getExtensionURL = getExtensionURL ;
518- exports . remove = remove ;
519- exports . update = update ;
520- exports . extensions = extensions ;
521- exports . cleanupUpdates = cleanupUpdates ;
522- exports . markForRemoval = markForRemoval ;
523- exports . isMarkedForRemoval = isMarkedForRemoval ;
524- exports . unmarkAllForRemoval = unmarkAllForRemoval ;
525- exports . hasExtensionsToRemove = hasExtensionsToRemove ;
526- exports . updateFromDownload = updateFromDownload ;
527- exports . removeUpdate = removeUpdate ;
528- exports . isMarkedForUpdate = isMarkedForUpdate ;
529- exports . hasExtensionsToUpdate = hasExtensionsToUpdate ;
530- exports . removeMarkedExtensions = removeMarkedExtensions ;
531- exports . updateExtensions = updateExtensions ;
585+ exports . downloadRegistry = downloadRegistry ;
586+ exports . getCompatibilityInfo = getCompatibilityInfo ;
587+ exports . getExtensionURL = getExtensionURL ;
588+ exports . remove = remove ;
589+ exports . update = update ;
590+ exports . extensions = extensions ;
591+ exports . cleanupUpdates = cleanupUpdates ;
592+ exports . markForRemoval = markForRemoval ;
593+ exports . isMarkedForRemoval = isMarkedForRemoval ;
594+ exports . unmarkAllForRemoval = unmarkAllForRemoval ;
595+ exports . hasExtensionsToRemove = hasExtensionsToRemove ;
596+ exports . updateFromDownload = updateFromDownload ;
597+ exports . removeUpdate = removeUpdate ;
598+ exports . isMarkedForUpdate = isMarkedForUpdate ;
599+ exports . hasExtensionsToUpdate = hasExtensionsToUpdate ;
600+ exports . removeMarkedExtensions = removeMarkedExtensions ;
601+ exports . updateExtensions = updateExtensions ;
602+ exports . getAvailableUpdates = getAvailableUpdates ;
603+ exports . cleanAvailableUpdates = cleanAvailableUpdates ;
532604
533- exports . ENABLED = ENABLED ;
534- exports . START_FAILED = START_FAILED ;
605+ exports . ENABLED = ENABLED ;
606+ exports . START_FAILED = START_FAILED ;
535607
536- exports . LOCATION_DEFAULT = LOCATION_DEFAULT ;
537- exports . LOCATION_DEV = LOCATION_DEV ;
538- exports . LOCATION_USER = LOCATION_USER ;
539- exports . LOCATION_UNKNOWN = LOCATION_UNKNOWN ;
608+ exports . LOCATION_DEFAULT = LOCATION_DEFAULT ;
609+ exports . LOCATION_DEV = LOCATION_DEV ;
610+ exports . LOCATION_USER = LOCATION_USER ;
611+ exports . LOCATION_UNKNOWN = LOCATION_UNKNOWN ;
540612
541613 // For unit testing only
542- exports . _reset = _reset ;
543- exports . _setExtensions = _setExtensions ;
544- } ) ;
614+ exports . _reset = _reset ;
615+ exports . _setExtensions = _setExtensions ;
616+ } ) ;
0 commit comments