Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip minor updates separately from major upgrades #1853

Merged
merged 17 commits into from
May 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions Sparkle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,14 @@
7267E5F91D3D92DA00D1BF90 /* Autoupdate in Copy Tools */ = {isa = PBXBuildFile; fileRef = 72B398D21D3D879300EE297F /* Autoupdate */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
7267E5FA1D3DAC3600D1BF90 /* StatusInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 7267E5A41D3D8A8A00D1BF90 /* StatusInfo.m */; };
7267E5FD1D3DD1B700D1BF90 /* SPUResumableUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7267E5FB1D3DD1B700D1BF90 /* SPUResumableUpdate.h */; };
726DF88E1C84277600188804 /* SPUStatusCompletionResults.h in Headers */ = {isa = PBXBuildFile; fileRef = 726DF88D1C84277500188804 /* SPUStatusCompletionResults.h */; settings = {ATTRIBUTES = (Public, ); }; };
7269E494264798200088C213 /* SPUSkippedUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7269E492264798200088C213 /* SPUSkippedUpdate.h */; };
7269E495264798200088C213 /* SPUSkippedUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7269E492264798200088C213 /* SPUSkippedUpdate.h */; };
7269E496264798200088C213 /* SPUSkippedUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269E493264798200088C213 /* SPUSkippedUpdate.m */; };
7269E497264798200088C213 /* SPUSkippedUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269E493264798200088C213 /* SPUSkippedUpdate.m */; };
7269E4982648D3460088C213 /* SPUSkippedUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269E493264798200088C213 /* SPUSkippedUpdate.m */; };
7269E49A2648F7C00088C213 /* SPUUserUpdateState.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269E4992648F7C00088C213 /* SPUUserUpdateState.m */; };
7269E49B2648F7C00088C213 /* SPUUserUpdateState.m in Sources */ = {isa = PBXBuildFile; fileRef = 7269E4992648F7C00088C213 /* SPUUserUpdateState.m */; };
726DF88E1C84277600188804 /* SPUUserUpdateState.h in Headers */ = {isa = PBXBuildFile; fileRef = 726DF88D1C84277500188804 /* SPUUserUpdateState.h */; settings = {ATTRIBUTES = (Public, ); }; };
726E075C1CA3A6D6001A286B /* SPUSecureCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 726E075A1CA3A6D6001A286B /* SPUSecureCoding.h */; };
726E075D1CA3A6D6001A286B /* SPUSecureCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 726E075B1CA3A6D6001A286B /* SPUSecureCoding.m */; };
726E078D1CA891E9001A286B /* SPUUpdaterSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 726E078B1CA891E9001A286B /* SPUUpdaterSettings.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -380,7 +387,7 @@
72A5D5F41D692CF50009E5AC /* SparkleCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72A5D59C1D6927730009E5AC /* SparkleCore.framework */; };
72A5D5F51D692CFE0009E5AC /* SparkleCore.framework in Copy Sparkle */ = {isa = PBXBuildFile; fileRef = 72A5D59C1D6927730009E5AC /* SparkleCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
72A5D5F81D692F2B0009E5AC /* SUExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 14652F8319A9759F00959E44 /* SUExport.h */; settings = {ATTRIBUTES = (Public, ); }; };
72A5D5F91D692F4C0009E5AC /* SPUStatusCompletionResults.h in Headers */ = {isa = PBXBuildFile; fileRef = 726DF88D1C84277500188804 /* SPUStatusCompletionResults.h */; settings = {ATTRIBUTES = (Public, ); }; };
72A5D5F91D692F4C0009E5AC /* SPUUserUpdateState.h in Headers */ = {isa = PBXBuildFile; fileRef = 726DF88D1C84277500188804 /* SPUUserUpdateState.h */; settings = {ATTRIBUTES = (Public, ); }; };
72A5D5FB1D69312F0009E5AC /* SUBundleIcon.m in Sources */ = {isa = PBXBuildFile; fileRef = 7214B8801D456A8500CB5CED /* SUBundleIcon.m */; };
72A6F98A1C94E2D6005F404C /* SUUpdaterDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 72A6F9891C94E2D6005F404C /* SUUpdaterDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
72AC6B261B9AAC8800F62325 /* SparkleTestCodeSignApp.tar.gz in Resources */ = {isa = PBXBuildFile; fileRef = 72AC6B251B9AAC8800F62325 /* SparkleTestCodeSignApp.tar.gz */; };
Expand Down Expand Up @@ -1244,8 +1251,12 @@
7267E5E31D3D90AA00D1BF90 /* SUFileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUFileManager.h; sourceTree = "<group>"; };
7267E5E41D3D90AA00D1BF90 /* SUFileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUFileManager.m; sourceTree = "<group>"; };
7267E5FB1D3DD1B700D1BF90 /* SPUResumableUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUResumableUpdate.h; sourceTree = "<group>"; };
7269E492264798200088C213 /* SPUSkippedUpdate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPUSkippedUpdate.h; sourceTree = "<group>"; };
7269E493264798200088C213 /* SPUSkippedUpdate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPUSkippedUpdate.m; sourceTree = "<group>"; };
7269E4992648F7C00088C213 /* SPUUserUpdateState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SPUUserUpdateState.m; sourceTree = "<group>"; };
7269E49C2648FC6C0088C213 /* SPUUserUpdateState+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SPUUserUpdateState+Private.h"; sourceTree = "<group>"; };
726B2B5D1C645FC900388755 /* UI Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "UI Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
726DF88D1C84277500188804 /* SPUStatusCompletionResults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUStatusCompletionResults.h; sourceTree = "<group>"; };
726DF88D1C84277500188804 /* SPUUserUpdateState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPUUserUpdateState.h; sourceTree = "<group>"; };
726E075A1CA3A6D6001A286B /* SPUSecureCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SPUSecureCoding.h; path = Sparkle/SPUSecureCoding.h; sourceTree = SOURCE_ROOT; };
726E075B1CA3A6D6001A286B /* SPUSecureCoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SPUSecureCoding.m; path = Sparkle/SPUSecureCoding.m; sourceTree = SOURCE_ROOT; };
726E07681CA616A4001A286B /* libxar.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxar.tbd; path = usr/lib/libxar.tbd; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -1934,6 +1945,8 @@
7267E5E41D3D90AA00D1BF90 /* SUFileManager.m */,
61EF67580E25C5B400F754E0 /* SUHost.h */,
61EF67550E25B58D00F754E0 /* SUHost.m */,
7269E492264798200088C213 /* SPUSkippedUpdate.h */,
7269E493264798200088C213 /* SPUSkippedUpdate.m */,
72162B071C82C9600013C1C5 /* SULocalizations.h */,
55C14F04136EF6DB00649790 /* SULog.h */,
55C14F05136EF6DB00649790 /* SULog.m */,
Expand Down Expand Up @@ -2135,7 +2148,9 @@
725CB9581C7121830064365A /* SPUStandardUserDriver.h */,
725CB9591C7121830064365A /* SPUStandardUserDriver.m */,
726E4A361C89116000C57C6A /* SPUStandardUserDriverDelegate.h */,
726DF88D1C84277500188804 /* SPUStatusCompletionResults.h */,
726DF88D1C84277500188804 /* SPUUserUpdateState.h */,
7269E49C2648FC6C0088C213 /* SPUUserUpdateState+Private.h */,
7269E4992648F7C00088C213 /* SPUUserUpdateState.m */,
725CB9561C7120410064365A /* SPUUserDriver.h */,
);
name = "User Driver";
Expand Down Expand Up @@ -2384,11 +2399,12 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
7269E495264798200088C213 /* SPUSkippedUpdate.h in Headers */,
72A5D5DE1D692ACC0009E5AC /* SparkleCore.h in Headers */,
72B3DECE1E23479000457642 /* SPUInformationalUpdate.h in Headers */,
72A5D5EB1D692BD40009E5AC /* SPUDownloadData.h in Headers */,
721D588E25BE59F900D23BEA /* SUPhasedUpdateGroupInfo.h in Headers */,
72A5D5F91D692F4C0009E5AC /* SPUStatusCompletionResults.h in Headers */,
72A5D5F91D692F4C0009E5AC /* SPUUserUpdateState.h in Headers */,
72A5D5E71D692BB00009E5AC /* SPUUpdatePermissionRequest.h in Headers */,
EA1E286F22B6661D004AA304 /* SUSignatures.h in Headers */,
72A5D5E21D692B770009E5AC /* SPUUpdater.h in Headers */,
Expand Down Expand Up @@ -2429,7 +2445,7 @@
7246E0A31C83B685003B4E75 /* SPUStandardUpdaterController.h in Headers */,
725CB95A1C7121830064365A /* SPUStandardUserDriver.h in Headers */,
726E4A371C89116000C57C6A /* SPUStandardUserDriverDelegate.h in Headers */,
726DF88E1C84277600188804 /* SPUStatusCompletionResults.h in Headers */,
726DF88E1C84277600188804 /* SPUUserUpdateState.h in Headers */,
72B767DA1C9CD2E400A07552 /* SPUUIBasedUpdateDriver.h in Headers */,
7229E1B61C97C91100CB50D0 /* SPUUpdateDriver.h in Headers */,
72DBA37D1D60CC34002594A8 /* SPUUpdatePermissionRequest.h in Headers */,
Expand All @@ -2438,6 +2454,7 @@
72F9EC481D5EA904004AC8B6 /* SPUUpdaterDelegate.h in Headers */,
726E078D1CA891E9001A286B /* SPUUpdaterSettings.h in Headers */,
72F9EC3F1D5E823F004AC8B6 /* SPUUpdaterTimer.h in Headers */,
7269E494264798200088C213 /* SPUSkippedUpdate.h in Headers */,
723ABFC4259D4CB300BDB4FA /* SUWKWebView.h in Headers */,
7293A1AE1CEE933800B957A7 /* SPUURLRequest.h in Headers */,
725CB9571C7120410064365A /* SPUUserDriver.h in Headers */,
Expand Down Expand Up @@ -3260,6 +3277,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
7269E4982648D3460088C213 /* SPUSkippedUpdate.m in Sources */,
721D5ABC25C680A300D23BEA /* SUFlatPackageUnarchiver.m in Sources */,
725F97771C8A62F500265BE4 /* SUAdHocCodeSigning.m in Sources */,
5A4094481C74EA5200983BE0 /* SUAppcastTest.swift in Sources */,
Expand Down Expand Up @@ -3443,6 +3461,7 @@
72A5D5BD1D6929F80009E5AC /* SPUDownloadData.m in Sources */,
72A5D5D01D6929F80009E5AC /* SPUDownloadDriver.m in Sources */,
EA1E287122B66622004AA304 /* SUSignatures.m in Sources */,
7269E497264798200088C213 /* SPUSkippedUpdate.m in Sources */,
72A5D5AF1D6929F80009E5AC /* SPUDownloader.m in Sources */,
72A5D5B71D6929F80009E5AC /* SPUInstallationInfo.m in Sources */,
72A5D5B41D6929F80009E5AC /* SPUInstallationInputData.m in Sources */,
Expand Down Expand Up @@ -3474,6 +3493,7 @@
72A5D5B01D6929F80009E5AC /* SUInstallerConnection.m in Sources */,
72A5D5AE1D6929F80009E5AC /* SUInstallerLauncher.m in Sources */,
72B3DED01E23479000457642 /* SPUInformationalUpdate.m in Sources */,
7269E49B2648F7C00088C213 /* SPUUserUpdateState.m in Sources */,
72A5D5B21D6929F80009E5AC /* SUInstallerStatus.m in Sources */,
72A5D5C51D6929F80009E5AC /* SULog.m in Sources */,
72A5D5C61D6929F80009E5AC /* SUOperatingSystem.m in Sources */,
Expand Down Expand Up @@ -3575,6 +3595,8 @@
61B5FBB709C4FAFF00B25A18 /* SUAppcast.m in Sources */,
72B767CB1C9B707000A07552 /* SUAppcastDriver.m in Sources */,
61B5FC6F09C51F4900B25A18 /* SUAppcastItem.m in Sources */,
7269E496264798200088C213 /* SPUSkippedUpdate.m in Sources */,
7269E49A2648F7C00088C213 /* SPUUserUpdateState.m in Sources */,
725602D61C83551C00DAA70E /* SUApplicationInfo.m in Sources */,
7214B8821D456A8500CB5CED /* SUBundleIcon.m in Sources */,
72DBA37F1D62C23E002594A8 /* SUCodeSigningVerifier.m in Sources */,
Expand Down
12 changes: 12 additions & 0 deletions Sparkle/Base.lproj/Sparkle.strings
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@
/* Take care not to overflow the status window. */
"Installing update..." = "Installing update…";

/* Title confirmation for skipping major upgrade and future updates */
"Are you sure you want to skip this upgrade?" = "Are you sure you want to skip this upgrade?";

/* Confirmation message for skipping major upgrade and future updates */
"Skipping this major upgrade will opt out of alerts for future updates." = "Skipping this major upgrade will opt out of alerts for future updates.";

/* Skipping major upgrade */
"Skip Upgrade" = "Skip Upgrade";

/* Not skipping a major upgrade */
"Don't Skip" = "Don't Skip";

/* the unit for kilobytes */
"KB" = "KB";

Expand Down
2 changes: 1 addition & 1 deletion Sparkle/SPUCoreBasedUpdateDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

#import <Foundation/Foundation.h>
#import "SPUStatusCompletionResults.h"
#import "SPUUserUpdateState.h"
#import "SPUUpdateDriver.h"

NS_ASSUME_NONNULL_BEGIN
Expand Down
38 changes: 38 additions & 0 deletions Sparkle/SPUSkippedUpdate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// SPUSkippedUpdate.h
// Sparkle
//
// Created by Mayur Pawashe on 5/8/21.
// Copyright © 2021 Sparkle Project. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@class SUHost, SUAppcastItem;

/*
A skipped update tracks an optional minor version and an optional major version the user may skip.
The minor and major versions are independent versions, so the user can choose to skip at most two separate versions.
The intent is when the user is faced with a major upgrade, they can skip a major version.
Otherwise they can choose to skip a minor version.
*/
@interface SPUSkippedUpdate : NSObject

+ (nullable SPUSkippedUpdate *)skippedUpdateForHost:(SUHost *)host;

+ (void)clearSkippedUpdateForHost:(SUHost *)host;

+ (void)skipUpdate:(SUAppcastItem *)updateItem host:(SUHost *)host majorUpgrade:(BOOL)majorUpgrade;

// At least one of minorVersion or majorVersion should be non-nil
- (instancetype)initWithMinorVersion:(nullable NSString *)minorVersion majorVersion:(nullable NSString *)majorVersion;

// At least one of these version properties will be non-nil
@property (nonatomic, readonly, nullable) NSString *minorVersion;
@property (nonatomic, readonly, nullable) NSString *majorVersion;

@end

NS_ASSUME_NONNULL_END
65 changes: 65 additions & 0 deletions Sparkle/SPUSkippedUpdate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// SPUSkippedUpdate.m
// Sparkle
//
// Created by Mayur Pawashe on 5/8/21.
// Copyright © 2021 Sparkle Project. All rights reserved.
//

#import "SPUSkippedUpdate.h"
#import "SUHost.h"
#import "SUConstants.h"
#import "SUAppcastItem.h"


#include "AppKitPrevention.h"

@implementation SPUSkippedUpdate

@synthesize minorVersion = _minorVersion;
@synthesize majorVersion = _majorVersion;

- (instancetype)initWithMinorVersion:(nullable NSString *)minorVersion majorVersion:(nullable NSString *)majorVersion
{
self = [super init];
if (self != nil) {
_minorVersion = [minorVersion copy];
_majorVersion = [majorVersion copy];

assert(_minorVersion != nil || _majorVersion != nil);
}
return self;
}

+ (nullable SPUSkippedUpdate *)skippedUpdateForHost:(SUHost *)host
{
NSString *minorVersion = [host objectForUserDefaultsKey:SUSkippedMinorVersionKey];
NSString *majorVersion = [host objectForUserDefaultsKey:SUSkippedMajorVersionKey];

if (minorVersion != nil || majorVersion != nil) {
return [[SPUSkippedUpdate alloc] initWithMinorVersion:minorVersion majorVersion:majorVersion];
} else {
return nil;
}
}

+ (void)clearSkippedUpdateForHost:(SUHost *)host
{
[host setObject:nil forUserDefaultsKey:SUSkippedMinorVersionKey];
[host setObject:nil forUserDefaultsKey:SUSkippedMajorVersionKey];
}

+ (void)skipUpdate:(SUAppcastItem *)updateItem host:(SUHost *)host majorUpgrade:(BOOL)majorUpgrade
{
if (majorUpgrade) {
NSString *majorVersion = updateItem.minimumAutoupdateVersion;
assert(majorVersion != nil);

[host setObject:majorVersion forUserDefaultsKey:SUSkippedMajorVersionKey];
} else {
NSString *version = updateItem.versionString;
[host setObject:version forUserDefaultsKey:SUSkippedMinorVersionKey];
}
}

@end
4 changes: 2 additions & 2 deletions Sparkle/SPUStandardUserDriver.m
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ - (void)applicationDidBecomeActive:(NSNotification *)__unused aNotification

#pragma mark Update Found

- (void)showUpdateFoundWithAppcastItem:(SUAppcastItem *)appcastItem userInitiated:(BOOL)userInitiated state:(SPUUserUpdateState)state reply:(void (^)(SPUUserUpdateChoice))reply
- (void)showUpdateFoundWithAppcastItem:(SUAppcastItem *)appcastItem state:(SPUUserUpdateState *)state reply:(void (^)(SPUUserUpdateChoice))reply
{
assert(NSThread.isMainThread);

Expand All @@ -132,7 +132,7 @@ - (void)showUpdateFoundWithAppcastItem:(SUAppcastItem *)appcastItem userInitiate
weakSelf.activeUpdateAlert = nil;
}];

[self setUpFocusForActiveUpdateAlertWithUserInitiation:userInitiated];
[self setUpFocusForActiveUpdateAlertWithUserInitiation:state.userInitiated];
}

- (void)showUpdateReleaseNotesWithDownloadData:(SPUDownloadData *)downloadData
Expand Down
67 changes: 0 additions & 67 deletions Sparkle/SPUStatusCompletionResults.h

This file was deleted.

Loading