Skip to content

Commit

Permalink
Allow an appcast to prevent the new version from being installed auto…
Browse files Browse the repository at this point in the history
…matically (#1688)
  • Loading branch information
pierswalter authored Dec 2, 2020
1 parent d4d4c68 commit 65eb63f
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 3 deletions.
1 change: 1 addition & 0 deletions Sparkle/SUAppcastItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SU_EXPORT @interface SUAppcastItem : NSObject
@property (copy, readonly) NSDictionary *deltaUpdates;
@property (strong, readonly) NSURL *infoURL;
@property (copy, readonly) NSNumber* phasedRolloutInterval;
@property (copy, readonly) NSString *minimumAutoupdateVersion;

// Initializes with data from a dictionary provided by the RSS class.
- (instancetype)initWithDictionary:(NSDictionary *)dict;
Expand Down
6 changes: 5 additions & 1 deletion Sparkle/SUAppcastItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ @interface SUAppcastItem ()
@property (strong, readwrite) NSURL *infoURL;
@property (readwrite, copy) NSDictionary *propertiesDictionary;
@property (copy, readwrite) NSNumber* phasedRolloutInterval;
@property (copy, readwrite) NSString *minimumAutoupdateVersion;
@end

@implementation SUAppcastItem
Expand All @@ -48,6 +49,7 @@ @implementation SUAppcastItem
@synthesize osString;
@synthesize propertiesDictionary;
@synthesize phasedRolloutInterval;
@synthesize minimumAutoupdateVersion;

- (BOOL)isDeltaUpdate
{
Expand Down Expand Up @@ -154,7 +156,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString
}
return nil;
}

if (enclosureURLString) {
NSString *enclosureLengthString = [enclosure objectForKey:SURSSAttributeLength];
long long contentLength = 0;
Expand Down Expand Up @@ -225,6 +227,8 @@ - (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString
}
self.deltaUpdates = deltas;
}

self.minimumAutoupdateVersion = [dict objectForKey:SUAppcastElementMinimumAutoupdateVersion];
}
return self;
}
Expand Down
1 change: 1 addition & 0 deletions Sparkle/SUBasicUpdateDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- (void)checkForUpdatesAtURL:(NSURL *)URL host:(SUHost *)host;

- (BOOL)isItemNewer:(SUAppcastItem *)ui;
- (BOOL)itemPreventsAutoupdate:(SUAppcastItem *)ui;
- (BOOL)hostSupportsItem:(SUAppcastItem *)ui;
- (BOOL)itemContainsSkippedVersion:(SUAppcastItem *)ui;
- (BOOL)itemContainsValidUpdate:(SUAppcastItem *)ui;
Expand Down
12 changes: 12 additions & 0 deletions Sparkle/SUBasicUpdateDriver.m
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ - (BOOL)isItemNewer:(SUAppcastItem *)ui
return [[self versionComparator] compareVersion:[self.host version] toVersion:[ui versionString]] == NSOrderedAscending;
}

- (BOOL)itemPreventsAutoupdate:(SUAppcastItem *)ui
{
return ([ui minimumAutoupdateVersion] && ! [[ui minimumAutoupdateVersion] isEqualToString:@""] && ([[self versionComparator] compareVersion:[self.host version] toVersion:[ui minimumAutoupdateVersion]] == NSOrderedAscending));
}

- (BOOL)itemContainsSkippedVersion:(SUAppcastItem *)ui
{
NSString *skippedVersion = [self.host objectForUserDefaultsKey:SUSkippedVersionKey];
Expand Down Expand Up @@ -239,6 +244,13 @@ - (void)didFindValidUpdate
{
assert(self.updateItem);

// Handle the case where the update indicates that an automatic update is only available for specific versions
if ([self itemPreventsAutoupdate:self.updateItem]) {
[self.updater setAutomaticallyDownloadsUpdates:NO]; // This call will persist this setting (automatic downloads will be permanently deactivated), but that is probably OK after the rare case of a non-automatically updateable update - the user can always reactivate this in the settings or when the update information window appears for the next time.
[self.updater checkForUpdatesInBackground]; // Will end up in SUUIBasedUpdateDriver instead of here
return;
}

id<SUUpdaterPrivate> updater = self.updater;

if ([[updater delegate] respondsToSelector:@selector(updater:didFindValidUpdate:)]) {
Expand Down
1 change: 1 addition & 0 deletions Sparkle/SUConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ extern NSString *const SUAppcastAttributePhasedRolloutInterval;

extern NSString *const SUAppcastElementCriticalUpdate;
extern NSString *const SUAppcastElementDeltas;
extern NSString *const SUAppcastElementMinimumAutoupdateVersion;
extern NSString *const SUAppcastElementMinimumSystemVersion;
extern NSString *const SUAppcastElementMaximumSystemVersion;
extern NSString *const SUAppcastElementReleaseNotesLink;
Expand Down
1 change: 1 addition & 0 deletions Sparkle/SUConstants.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

NSString *const SUAppcastElementCriticalUpdate = @"sparkle:criticalUpdate";
NSString *const SUAppcastElementDeltas = @"sparkle:deltas";
NSString *const SUAppcastElementMinimumAutoupdateVersion = @"sparkle:minimumAutoupdateVersion";
NSString *const SUAppcastElementMinimumSystemVersion = @"sparkle:minimumSystemVersion";
NSString *const SUAppcastElementMaximumSystemVersion = @"sparkle:maximumSystemVersion";
NSString *const SUAppcastElementReleaseNotesLink = @"sparkle:releaseNotesLink";
Expand Down
9 changes: 7 additions & 2 deletions Sparkle/SUUIBasedUpdateDriver.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,21 @@ - (BOOL)shouldShowUpdateAlertForItem:(SUAppcastItem *)__unused item {
- (void)didFindValidUpdate
{
id<SUUpdaterPrivate> updater = self.updater;
SUAppcastItem *updateItem = self.updateItem;
if ([[updater delegate] respondsToSelector:@selector(updater:didFindValidUpdate:)]) {
[[updater delegate] updater:self.updater didFindValidUpdate:self.updateItem];
[[updater delegate] updater:self.updater didFindValidUpdate:updateItem];
}

// Handle the case where the update indicates that an automatic update is only available for specific versions
if ([self itemPreventsAutoupdate:self.updateItem]) {
self.automaticallyInstallUpdates = NO;
}

if (self.automaticallyInstallUpdates) {
[self updateAlertFinishedWithChoice:SUInstallUpdateChoice forItem:nil];
return;
}

SUAppcastItem *updateItem = self.updateItem;
if (![self shouldShowUpdateAlertForItem:updateItem]) {
[self abortUpdate];
return;
Expand Down

0 comments on commit 65eb63f

Please sign in to comment.