@@ -234,6 +234,8 @@ SyncSettings =
234
234
if atom .config .get (' sync-settings.syncPackages' )
235
235
callbackAsync = true
236
236
@ installMissingPackages JSON .parse (file .content ), cb
237
+ if atom .config .get (' sync-settings.removeObsoletePackage' )
238
+ @ removeObsoletePackages JSON .parse (file .content ), cb
237
239
238
240
when ' keymap.cson'
239
241
fs .writeFileSync atom .keymaps .getUserKeymapPath (), file .content if atom .config .get (' sync-settings.syncKeymap' )
@@ -305,6 +307,64 @@ SyncSettings =
305
307
console .debug " config.set #{ keyPath[1 ... ]} =#{ value} "
306
308
atom .config .set keyPath[1 ... ], value
307
309
310
+ removeObsoletePackages : (remaining_packages , cb ) ->
311
+ installed_packages = @ getPackages ()
312
+ obsolete_packages = []
313
+ for pkg in installed_packages
314
+ keep_installed_package = (p for p in remaining_packages when p .name is pkg .name )
315
+ if keep_installed_package .length is 0
316
+ obsolete_packages .push (pkg)
317
+ if obsolete_packages .length is 0
318
+ atom .notifications .addInfo " Sync-settings: no packages to remove"
319
+ return cb? ()
320
+
321
+ notifications = {}
322
+ succeeded = []
323
+ failed = []
324
+ removeNextPackage = =>
325
+ if obsolete_packages .length > 0
326
+ # start removing next package
327
+ pkg = obsolete_packages .shift ()
328
+ i = succeeded .length + failed .length + Object .keys (notifications).length + 1
329
+ count = i + obsolete_packages .length
330
+ notifications[pkg .name ] = atom .notifications .addInfo " Sync-settings: removing #{ pkg .name } (#{ i} /#{ count} )" , {dismissable : true }
331
+ do (pkg ) =>
332
+ @ removePackage pkg, (error ) ->
333
+ # removal of package finished
334
+ notifications[pkg .name ].dismiss ()
335
+ delete notifications[pkg .name ]
336
+ if error?
337
+ failed .push (pkg .name )
338
+ atom .notifications .addWarning " Sync-settings: failed to remove #{ pkg .name } "
339
+ else
340
+ succeeded .push (pkg .name )
341
+ # trigger next package
342
+ removeNextPackage ()
343
+ else if Object .keys (notifications).length is 0
344
+ # last package removal finished
345
+ if failed .length is 0
346
+ atom .notifications .addSuccess " Sync-settings: finished removing #{ succeeded .length } packages"
347
+ else
348
+ failed .sort ()
349
+ failedStr = failed .join (' , ' )
350
+ atom .notifications .addWarning " Sync-settings: finished removing packages (#{ failed .length } failed: #{ failedStr} )" , {dismissable : true }
351
+ cb? ()
352
+ # start as many package removal in parallel as desired
353
+ concurrency = Math .min obsolete_packages .length , 8
354
+ for i in [0 ... concurrency]
355
+ removeNextPackage ()
356
+
357
+ removePackage : (pack , cb ) ->
358
+ type = if pack .theme then ' theme' else ' package'
359
+ console .info (" Removing #{ type} #{ pack .name } ..." )
360
+ packageManager = new PackageManager ()
361
+ packageManager .uninstall pack, (error ) ->
362
+ if error?
363
+ console .error (" Removing #{ type} #{ pack .name } failed" , error .stack ? error, error .stderr )
364
+ else
365
+ console .info (" Removing #{ type} #{ pack .name } " )
366
+ cb? (error)
367
+
308
368
installMissingPackages : (packages , cb ) ->
309
369
available_packages = @ getPackages ()
310
370
missing_packages = []
0 commit comments