13 Commits
Author SHA1 Message Date
Josh Abernathy bde5ff2983 Merge pull request #190 from slyngbaek/master
Add auth headers to zip download requests not just feed requests.
2016-11-08 10:38:28 -05:00
Steffen Lyngbaek ae78589d3a Update block type name 2016-11-07 14:56:36 -08:00
Steffen Lyngbaek abec74ed3f Add block to initializer to provide custom download requests.
Add a second initializer with with a block argument to handle
customization of download url requests.

Add a generic download request to the original initializer without
changing the current api.
2016-11-07 12:19:02 -08:00
Steffen Lyngbaek a994876d98 Don't clobber headers explicitly set on the zip download request. 2016-11-04 10:32:54 -07:00
Steffen Lyngbaek 9d5464c693 Add auth headers to zip download requests not just feed requests. 2016-11-03 14:14:51 -07:00
Keith Duncan f00ad7e91b Merge pull request #186 from Squirrel/dont-check-for-updates-when-readonly
Error if there's an update available but the app's on a read-only volume
2016-10-18 11:03:53 +11:00
joshaber 4b0d5ffe18 Error check the statfs call 2016-10-17 14:04:20 -04:00
joshaber d93abe66ec Use a better description 2016-10-17 14:04:09 -04:00
joshaber 196abf93b8 Use a unique error code 2016-10-17 14:03:59 -04:00
joshaber a0079fdee0 Only error once we know if it matters 2016-10-14 10:47:24 -04:00
joshaber fdb4ffa000 Throw an error instead of silently failing 2016-10-14 10:43:56 -04:00
joshaber cc047bdc6f Get outta town if the volume's readonly 2016-10-14 10:43:09 -04:00
joshaber 7231919408 Added -isRunningOnReadOnlyVolume 2016-10-14 10:40:33 -04:00
2 changed files with 61 additions and 1 deletions
+24
View File
@@ -23,6 +23,9 @@ typedef enum : NSUInteger {
SQRLUpdaterStateAwaitingRelaunch,
} SQRLUpdaterState;
// Block for providing download requests given a download url
typedef NSURLRequest * (^SQRLRequestForDownload)(NSURL *);
// The domain for errors originating within SQRLUpdater.
extern NSString * const SQRLUpdaterErrorDomain;
@@ -92,6 +95,15 @@ extern NSString * const SQRLUpdaterJSONObjectErrorKey;
// This property must never be set to nil.
@property (atomic, copy) NSURLRequest *updateRequest;
// The block used for fetching a given download request
//
// The default value is the argument that was originally passed to
// -initWithUpdateRequest:requestForDownload:.
//
// If initialized with -initWithUpdateRequest: this block will
// return a generic NSURLRequest with the provided url.
@property (nonatomic, copy) SQRLRequestForDownload requestForDownload;
// The `SQRLUpdate` subclass to instantiate with the server's response.
//
// By default, this is `SQRLUpdate` itself, but it can be set to a custom
@@ -111,6 +123,18 @@ extern NSString * const SQRLUpdaterJSONObjectErrorKey;
// Returns the initialized `SQRLUpdater`.
- (id)initWithUpdateRequest:(NSURLRequest *)updateRequest;
// Initializes an updater that will send the given request to check for updates
// and passes a block to provide requests for the update downloads.
//
// updateRequest - Same as with initWithUpdateRequest
// requestForDownload - Once the update url is found for the update download, allow
// providing custom requests that can be costomized as desired.
// Useful for including `Authorization` headers just like the
// updateRequest param.
//
// Returns the initialized `SQRLUpdater`.
- (id)initWithUpdateRequest:(NSURLRequest *)updateRequest requestForDownload:(SQRLRequestForDownload)requestForDownload;
// Executes `checkForUpdatesCommand` (if enabled) every `interval` seconds.
//
// The first check will not occur until `interval` seconds have passed.
+37 -1
View File
@@ -20,6 +20,7 @@
#import "SQRLShipItRequest.h"
#import <ReactiveCocoa/EXTScope.h>
#import <ReactiveCocoa/ReactiveCocoa.h>
#import <sys/mount.h>
NSString * const SQRLUpdaterErrorDomain = @"SQRLUpdaterErrorDomain";
NSString * const SQRLUpdaterServerDataErrorKey = @"SQRLUpdaterServerDataErrorKey";
@@ -32,6 +33,9 @@ const NSInteger SQRLUpdaterErrorInvalidServerResponse = 5;
const NSInteger SQRLUpdaterErrorInvalidJSON = 6;
const NSInteger SQRLUpdaterErrorInvalidServerBody = 7;
/// The application's being run on a read-only volume.
const NSInteger SQRLUpdaterErrorReadOnlyVolume = 8;
// The prefix used when creating temporary directories for updates. This will be
// followed by a random string of characters.
static NSString * const SQRLUpdaterUniqueTemporaryDirectoryPrefix = @"update.";
@@ -140,11 +144,19 @@ static NSString * const SQRLUpdaterUniqueTemporaryDirectoryPrefix = @"update.";
}
- (id)initWithUpdateRequest:(NSURLRequest *)updateRequest {
return [self initWithUpdateRequest:updateRequest requestForDownload:^(NSURL *downloadURL) {
return [NSURLRequest requestWithURL:downloadURL];
}];
}
- (id)initWithUpdateRequest:(NSURLRequest *)updateRequest requestForDownload:(SQRLRequestForDownload)requestForDownload {
NSParameterAssert(updateRequest != nil);
NSParameterAssert(requestForDownload != nil);
self = [super init];
if (self == nil) return nil;
_requestForDownload = [requestForDownload copy];
_updateRequest = [updateRequest copy];
_updateClass = SQRLUpdate.class;
@@ -194,6 +206,16 @@ static NSString * const SQRLUpdaterUniqueTemporaryDirectoryPrefix = @"update.";
if (httpResponse.statusCode == 204 /* No Content */) {
return [RACSignal empty];
}
BOOL readOnlyVolume = [self isRunningOnReadOnlyVolume];
if (readOnlyVolume) {
NSDictionary *errorInfo = @{
NSLocalizedDescriptionKey: NSLocalizedString(@"Cannot update while running on a read-only volume", nil),
NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"The application is on a read-only volume. Please move the application and try again. If you're on macOS Sierra or later, you'll need to move the application out of the Downloads directory. See https://github.com/Squirrel/Squirrel.Mac/issues/182 for more information.", nil),
};
NSError *error = [NSError errorWithDomain:SQRLUpdaterErrorDomain code:SQRLUpdaterErrorReadOnlyVolume userInfo:errorInfo];
return [RACSignal error:error];
}
}
return [RACSignal return:bodyData];
@@ -369,7 +391,8 @@ static NSString * const SQRLUpdaterUniqueTemporaryDirectoryPrefix = @"update.";
return [[RACSignal
defer:^{
NSURL *zipDownloadURL = update.updateURL;
NSMutableURLRequest *zipDownloadRequest = [NSMutableURLRequest requestWithURL:zipDownloadURL];
NSMutableURLRequest *zipDownloadRequest = [self.requestForDownload(zipDownloadURL) mutableCopy];
[zipDownloadRequest setValue:@"application/zip" forHTTPHeaderField:@"Accept"];
if (self.etag != nil) {
[zipDownloadRequest setValue:self.etag forHTTPHeaderField:@"If-None-Match"];
@@ -492,6 +515,19 @@ static NSString * const SQRLUpdaterUniqueTemporaryDirectoryPrefix = @"update.";
setNameWithFormat:@"%@ -shipItStateURL", self];
}
/// Is the host app running on a read-only volume?
- (BOOL)isRunningOnReadOnlyVolume {
struct statfs statfsInfo;
NSURL *bundleURL = NSRunningApplication.currentApplication.bundleURL;
int result = statfs(bundleURL.fileSystemRepresentation, &statfsInfo);
if (result == 0) {
return (statfsInfo.f_flags & MNT_RDONLY) != 0;
} else {
// If we can't even check if the volume is read-only, assume it is.
return true;
}
}
- (RACSignal *)performHousekeeping {
return [[RACSignal
merge:@[ [self pruneUpdateDirectories], [self truncateLogs] ]]