mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-13 08:52:20 +00:00
compatibilty for plugins is now fetched from plugin repository
This commit is contained in:
@@ -148,6 +148,8 @@
|
||||
4C6F228C19A4AA700012310C /* MPAutotypeDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6F228B19A4AA700012310C /* MPAutotypeDelay.m */; };
|
||||
4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C701CBB178618A000581B88 /* 12_RemoteTemplate.pdf */; };
|
||||
4C7155D81A10DB6D00979307 /* IconSelection.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C7155DA1A10DB6D00979307 /* IconSelection.xib */; };
|
||||
4C71BCB42167B75900B4CBDA /* MPTestPluginVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71BCB32167B75900B4CBDA /* MPTestPluginVersion.m */; };
|
||||
4C71BCB72167B79C00B4CBDA /* MPPluginVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71BCB62167B79C00B4CBDA /* MPPluginVersion.m */; };
|
||||
4C735FC02035FCBF00708D53 /* MPPluginEntryActionContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */; };
|
||||
4C73B6F1215E64A7009787F7 /* MPWelcomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C73B6EF215E64A7009787F7 /* MPWelcomeViewController.m */; };
|
||||
4C76155C1764C04C0015A1A6 /* GeneralSettings.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C76155E1764C04C0015A1A6 /* GeneralSettings.xib */; };
|
||||
@@ -183,6 +185,7 @@
|
||||
4C7BD07619FE94C900C7AA5C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4C7BD07519FE94C900C7AA5C /* Assets.xcassets */; };
|
||||
4C7F8B681A10B68400CCB83D /* WelcomeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C7F8B6A1A10B68400CCB83D /* WelcomeView.xib */; };
|
||||
4C80304A1E2FBAA300133E4C /* MPTestKeyMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C8030491E2FBAA300133E4C /* MPTestKeyMapper.m */; };
|
||||
4C81867D216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C81867C216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m */; };
|
||||
4C82046A1FCDC07800EB24A4 /* MPPickfieldViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C8204681FCDC07800EB24A4 /* MPPickfieldViewController.m */; };
|
||||
4C82046E1FCDC8A100EB24A4 /* MPPickfieldTableModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C82046D1FCDC8A100EB24A4 /* MPPickfieldTableModel.m */; };
|
||||
4C83814215BF4677001AE468 /* MPDocumentWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C83814115BF4677001AE468 /* MPDocumentWindowController.m */; };
|
||||
@@ -573,6 +576,9 @@
|
||||
4C7155E81A10DB7700979307 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
||||
4C7155EA1A10DB7800979307 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
||||
4C7155EC1A10DB7900979307 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/IconSelection.strings; sourceTree = "<group>"; };
|
||||
4C71BCB32167B75900B4CBDA /* MPTestPluginVersion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPTestPluginVersion.m; sourceTree = "<group>"; };
|
||||
4C71BCB52167B79C00B4CBDA /* MPPluginVersion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginVersion.h; sourceTree = "<group>"; };
|
||||
4C71BCB62167B79C00B4CBDA /* MPPluginVersion.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginVersion.m; sourceTree = "<group>"; };
|
||||
4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginEntryActionContext.h; sourceTree = "<group>"; };
|
||||
4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginEntryActionContext.m; sourceTree = "<group>"; };
|
||||
4C73B6EE215E64A7009787F7 /* MPWelcomeViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPWelcomeViewController.h; sourceTree = "<group>"; };
|
||||
@@ -643,6 +649,8 @@
|
||||
4C7F8B7A1A10B69700CCB83D /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/WelcomeView.strings; sourceTree = "<group>"; };
|
||||
4C7F8B7C1A10B69800CCB83D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/WelcomeView.strings; sourceTree = "<group>"; };
|
||||
4C8030491E2FBAA300133E4C /* MPTestKeyMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTestKeyMapper.m; sourceTree = "<group>"; };
|
||||
4C81867B216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPluginRepositoryItemVersionInfo.h; sourceTree = "<group>"; };
|
||||
4C81867C216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPluginRepositoryItemVersionInfo.m; sourceTree = "<group>"; };
|
||||
4C8204671FCDC07800EB24A4 /* MPPickfieldViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPickfieldViewController.h; sourceTree = "<group>"; };
|
||||
4C8204681FCDC07800EB24A4 /* MPPickfieldViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPPickfieldViewController.m; sourceTree = "<group>"; };
|
||||
4C82046C1FCDC8A100EB24A4 /* MPPickfieldTableModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPPickfieldTableModel.h; sourceTree = "<group>"; };
|
||||
@@ -1194,6 +1202,7 @@
|
||||
4C6BC65F1A36717E00BDDF3D /* MPDatabaseSearch.m */,
|
||||
4C8030491E2FBAA300133E4C /* MPTestKeyMapper.m */,
|
||||
4C8F0C721FCF1B7A00BE157F /* MPTestPickcharsParser.m */,
|
||||
4C71BCB32167B75900B4CBDA /* MPTestPluginVersion.m */,
|
||||
4C45FB1F178E09ED0010007D /* Supporting Files */,
|
||||
);
|
||||
path = MacPassTests;
|
||||
@@ -1663,8 +1672,12 @@
|
||||
4CA78BFF1FD58C92003C8560 /* MPPluginRepository.m */,
|
||||
4CAD338D205169D30068587E /* MPPluginRepositoryItem.h */,
|
||||
4CAD338E205169D30068587E /* MPPluginRepositoryItem.m */,
|
||||
4C81867B216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.h */,
|
||||
4C81867C216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m */,
|
||||
4C735FBE2035FCBF00708D53 /* MPPluginEntryActionContext.h */,
|
||||
4C735FBF2035FCBF00708D53 /* MPPluginEntryActionContext.m */,
|
||||
4C71BCB52167B79C00B4CBDA /* MPPluginVersion.h */,
|
||||
4C71BCB62167B79C00B4CBDA /* MPPluginVersion.m */,
|
||||
);
|
||||
name = Plugin;
|
||||
path = MacPass;
|
||||
@@ -1913,6 +1926,7 @@
|
||||
files = (
|
||||
4C45FB2D178E0BCB0010007D /* MPDatabaseLoading.m in Sources */,
|
||||
4C8DEAA21C314D2C00D24C32 /* MPTestAutotypeDelay.m in Sources */,
|
||||
4C71BCB42167B75900B4CBDA /* MPTestPluginVersion.m in Sources */,
|
||||
4C8F0C731FCF1B7A00BE157F /* MPTestPickcharsParser.m in Sources */,
|
||||
4C45FB30178E0CE20010007D /* MPTestDocument.m in Sources */,
|
||||
4C6BC6601A36717E00BDDF3D /* MPDatabaseSearch.m in Sources */,
|
||||
@@ -1966,6 +1980,7 @@
|
||||
4C888C9316EB6F5E003D34A1 /* MPToolbarItem.m in Sources */,
|
||||
4CA182741F963FF600DD4A4A /* MPTitlebarColorAccessoryViewController.m in Sources */,
|
||||
4C888C9716EB754B003D34A1 /* MPActionHelper.m in Sources */,
|
||||
4C81867D216664C70068DAFB /* MPPluginRepositoryItemVersionInfo.m in Sources */,
|
||||
4CDA35751EBA0CF2003CD59F /* NSString+MPComposedCharacterAdditions.m in Sources */,
|
||||
4CE39ABF16ECE34A000FE29D /* MPIconSelectViewController.m in Sources */,
|
||||
4CE39AC416ECE4F7000FE29D /* MPIconImageView.m in Sources */,
|
||||
@@ -2034,6 +2049,7 @@
|
||||
4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */,
|
||||
4C4B7EE917A45EC6000234C7 /* MPDatePickingViewController.m in Sources */,
|
||||
4C4B7EEE17A467E1000234C7 /* MPGroupInspectorViewController.m in Sources */,
|
||||
4C71BCB72167B79C00B4CBDA /* MPPluginVersion.m in Sources */,
|
||||
4C7B63721C0CB51F00D7038C /* TTTCryptographyTransformers.m in Sources */,
|
||||
4C4B7EF317A467FC000234C7 /* MPEntryInspectorViewController.m in Sources */,
|
||||
4C1BDF2B1E4392640012A3F0 /* MPPluginDataViewController.m in Sources */,
|
||||
|
||||
@@ -189,7 +189,7 @@ Gw
|
||||
<constraint firstItem="6" firstAttribute="leading" secondItem="9" secondAttribute="leading" id="zeJ-6i-fY3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-226" y="45"/>
|
||||
<point key="canvasLocation" x="-312" y="-21"/>
|
||||
</window>
|
||||
</objects>
|
||||
<resources>
|
||||
|
||||
@@ -183,7 +183,7 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi
|
||||
[MPLockDaemon defaultDaemon];
|
||||
[MPAutotypeDaemon defaultDaemon];
|
||||
/* Create Plugin Manager */
|
||||
[MPPluginHost sharedHost];
|
||||
[MPPluginHost.sharedHost loadPlugins];
|
||||
#if !defined(DEBUG) && !defined(NO_SPARKLE)
|
||||
/* Disable updates if in debug or nosparkle */
|
||||
[SUUpdater sharedUpdater];
|
||||
|
||||
@@ -196,17 +196,6 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
||||
}
|
||||
|
||||
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError {
|
||||
/* FIXME: Lockfile handling
|
||||
self.lockFileURL = [url URLByAppendingPathExtension:@"lock"];
|
||||
if([[NSFileManager defaultManager] fileExistsAtPath:[_lockFileURL path]]) {
|
||||
self.readOnly = YES;
|
||||
}
|
||||
else {
|
||||
[[NSFileManager defaultManager] createFileAtPath:[_lockFileURL path] contents:nil attributes:nil];
|
||||
_didLockFile = YES;
|
||||
self.readOnly = NO;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
Delete our old Tree, and just grab the data
|
||||
*/
|
||||
@@ -939,7 +928,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
||||
|
||||
- (void)_cleanupLock {
|
||||
if(_didLockFile) {
|
||||
[[NSFileManager defaultManager] removeItemAtURL:_lockFileURL error:nil];
|
||||
[NSFileManager.defaultManager removeItemAtURL:_lockFileURL error:nil];
|
||||
_didLockFile = NO;
|
||||
}
|
||||
}
|
||||
@@ -971,11 +960,11 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGrou
|
||||
#pragma mark MPModelChangeObserving
|
||||
|
||||
- (void)willChangeModelProperty {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentWillChangeModelPropertyNotification object:self];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:MPDocumentWillChangeModelPropertyNotification object:self];
|
||||
}
|
||||
|
||||
- (void)didChangeModelProperty {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidChangeModelPropertyNotification object:self];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:MPDocumentDidChangeModelPropertyNotification object:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[delegate methodSignatureForSelector:didRecoverSelector]];
|
||||
__block void *contextInfoCopy = contextInfo;
|
||||
if(error.code == MPErrorNoPasswordOrKeyFile) {
|
||||
if([delegate isKindOfClass:[MPDocument class]]) {
|
||||
if([delegate isKindOfClass:MPDocument.class]) {
|
||||
MPDocument *document = delegate;
|
||||
BOOL didRecover = NO;
|
||||
if(recoveryOptionIndex == 0) {
|
||||
@@ -59,7 +59,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Given that an error alert has been presented applicaton-modally to the user, and the user has chosen one of the error's recovery options, attempt recovery from the error, and return YES if error recovery was completely successful, NO otherwise. The recovery option index is an index into the error's array of localized recovery options.
|
||||
|
||||
@@ -35,7 +35,8 @@ FOUNDATION_EXPORT NSString *const MPPluginUnkownVersion;
|
||||
|
||||
@property (copy, readonly) NSString *identifier;
|
||||
@property (copy, readonly) NSString *name;
|
||||
@property (copy, readonly) NSString *version;
|
||||
@property (nonatomic, copy, readonly, nullable) NSString *humanVersionString;
|
||||
@property (nonatomic, copy, readonly) NSString *versionString;
|
||||
@property (nonatomic, strong, readonly) NSBundle *bundle;
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,9 +68,13 @@ NSString *const MPPluginUnkownVersion = @"unkown.plugin.version";
|
||||
return nil == name ? @"Unkown Plugin" : name;
|
||||
}
|
||||
|
||||
- (NSString *)version {
|
||||
- (NSString *)humanVersionString {
|
||||
return self.bundle.infoDictionary[@"CFBundleShortVersionString"];
|
||||
}
|
||||
|
||||
- (NSString *)versionString {
|
||||
if(self.bundle) {
|
||||
NSString *humanVersion = self.bundle.infoDictionary[@"CFBundleShortVersionString"];
|
||||
NSString *humanVersion = self.humanVersionString;
|
||||
NSString *version = self.bundle.infoDictionary[(NSString *)kCFBundleVersionKey];
|
||||
if(humanVersion && version) {
|
||||
return [NSString stringWithFormat:@"%@ (%@)", humanVersion, version];
|
||||
|
||||
@@ -48,6 +48,8 @@ FOUNDATION_EXPORT NSString *const MPPluginHostPluginBundleIdentifiyerKey;
|
||||
- (void)disablePlugin:(MPPlugin *)plugin;
|
||||
- (void)enablePlugin:(MPPlugin *)plugin;
|
||||
|
||||
- (void)loadPlugins;
|
||||
|
||||
/*
|
||||
- (NSArray <MPPlugin __kindof*>*)autotypePlugins;
|
||||
- (NSArray <MPPlugin __kindof*>*)entryContextMenuPlugins;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#import "MPPlugin_Private.h"
|
||||
#import "MPPluginConstants.h"
|
||||
#import "MPPluginEntryActionContext.h"
|
||||
#import "MPPluginRepository.h"
|
||||
#import "MPPluginRepositoryItem.h"
|
||||
|
||||
#import "NSApplication+MPAdditions.h"
|
||||
#import "MPSettingsHelper.h"
|
||||
@@ -79,8 +81,6 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
||||
_entryActionPluginIdentifiers = [[NSMutableArray alloc] init];
|
||||
_customAttributePluginIdentifiers = [[NSMutableArray alloc] init];
|
||||
|
||||
[self _loadPlugins];
|
||||
|
||||
[self bind:NSStringFromSelector(@selector(loadUnsecurePlugins))
|
||||
toObject:NSUserDefaultsController.sharedUserDefaultsController
|
||||
withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyLoadUnsecurePlugins]
|
||||
@@ -94,7 +94,7 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
||||
}
|
||||
|
||||
- (NSString *)version {
|
||||
NSString *version = NSBundle.mainBundle.infoDictionary[(NSString *)kCFBundleVersionKey];
|
||||
NSString *version = NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"];
|
||||
return version;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,13 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
||||
|
||||
#pragma mark - Plugin Loading
|
||||
|
||||
- (void)_loadPlugins {
|
||||
- (void)loadPlugins {
|
||||
[MPPluginRepository.defaultRepository fetchRepositoryDataCompletionHandler:^(NSArray<MPPluginRepositoryItem *> * _Nonnull availablePlugins) {
|
||||
[self _loadPlugins:availablePlugins];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)_loadPlugins:(NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
||||
NSURL *appSupportDir = [NSApp applicationSupportDirectoryURL:YES];
|
||||
NSError *error;
|
||||
NSLog(@"Looking for external plugins at %@.", appSupportDir.path);
|
||||
@@ -190,6 +196,11 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
||||
continue;
|
||||
}
|
||||
|
||||
if(![self _isCompatiblePluginBundle:pluginBundle avaiablePlugins:availablePlugins ]) {
|
||||
[self _addPluginForBundle:pluginBundle error:NSLocalizedString(@"PLUGIN_ERROR_HOST_VERSION_NOT_SUPPORTED", "Plugin is not with this version of MacPass")];
|
||||
continue;
|
||||
}
|
||||
|
||||
if(![pluginBundle loadAndReturnError:&error]) {
|
||||
NSLog(@"Bundle Loading Error %@ %@", error.localizedDescription, error.localizedFailureReason);
|
||||
[self _addPluginForBundle:pluginBundle error:error.localizedDescription];
|
||||
@@ -249,6 +260,17 @@ NSString *const MPPluginHostPluginBundleIdentifiyerKey = @"MPPluginHostPluginBun
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)_isCompatiblePluginBundle:(NSBundle *)bundle avaiablePlugins:(NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
||||
MPPluginRepositoryItem *repoItem;
|
||||
for(MPPluginRepositoryItem *item in availablePlugins) {
|
||||
if([item.bundleIdentifier isEqualToString:bundle.bundleIdentifier]) {
|
||||
repoItem = item;
|
||||
}
|
||||
}
|
||||
NSString *shortVersion = bundle.infoDictionary[@"CFBundleShortVersionString"];
|
||||
return [repoItem isPluginVersion:shortVersion compatibleWithHost:self];
|
||||
}
|
||||
|
||||
- (BOOL)_isValidPluginURL:(NSURL *)url {
|
||||
return (NSOrderedSame == [url.pathExtension compare:MPPluginFileExtension options:NSCaseInsensitiveSearch]);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class MPPluginRepositoryItem;
|
||||
@@ -27,7 +29,9 @@
|
||||
@interface MPPluginRepository : NSObject
|
||||
|
||||
@property (class, strong, readonly) MPPluginRepository *defaultRepository;
|
||||
@property (nonatomic, copy) NSArray<MPPluginRepositoryItem *> *availablePlugins;
|
||||
|
||||
- (void)fetchRepositoryDataCompletionHandler:(void (^)(NSArray<MPPluginRepositoryItem *> *availablePlugins))completionHandler;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -24,9 +24,16 @@
|
||||
#import "MPConstants.h"
|
||||
#import "MPPluginRepositoryItem.h"
|
||||
|
||||
@implementation MPPluginRepository
|
||||
const NSTimeInterval MPPluginRepositoryCacheTimeOut = 60*3; // 1 Minute cache time
|
||||
|
||||
@dynamic availablePlugins;
|
||||
@interface MPPluginRepository ()
|
||||
|
||||
@property NSTimeInterval lastPluginCheckTime;
|
||||
@property BOOL didLoadData;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPluginRepository
|
||||
|
||||
+ (instancetype)defaultRepository {
|
||||
static MPPluginRepository *instance;
|
||||
@@ -39,38 +46,65 @@
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
self.lastPluginCheckTime = NSDate.distantPast.timeIntervalSinceReferenceDate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray<MPPluginRepositoryItem *> *)availablePlugins {
|
||||
- (void)fetchRepositoryDataCompletionHandler:(void (^)(NSArray<MPPluginRepositoryItem *> * _Nonnull))completionHandler {
|
||||
NSString *urlString = NSBundle.mainBundle.infoDictionary[MPBundlePluginRepositoryURLKey];
|
||||
if(!urlString) {
|
||||
return @[];
|
||||
if(completionHandler) {
|
||||
completionHandler(@[]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSURL *jsonURL = [NSURL URLWithString:urlString];
|
||||
if(!jsonURL) {
|
||||
return @[];
|
||||
}
|
||||
NSError *error;
|
||||
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL options:0 error:&error];
|
||||
if(!jsonData) {
|
||||
return @[];
|
||||
}
|
||||
id jsonRoot = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
|
||||
if(!jsonRoot || ![jsonRoot isKindOfClass:NSArray.class]) {
|
||||
return @[];
|
||||
}
|
||||
NSMutableArray *items = [[NSMutableArray alloc] init];
|
||||
for(id item in jsonRoot) {
|
||||
if(![item isKindOfClass:NSDictionary.class]) {
|
||||
continue;
|
||||
}
|
||||
MPPluginRepositoryItem *pluginItem = [MPPluginRepositoryItem pluginItemFromDictionary:item];
|
||||
if(pluginItem.isVaid) {
|
||||
[items addObject:pluginItem];
|
||||
if(completionHandler) {
|
||||
completionHandler(@[]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return [items copy];
|
||||
|
||||
NSURLSessionTask *downloadTask = [NSURLSession.sharedSession dataTaskWithURL:jsonURL completionHandler:^(NSData * _Nullable jsonData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
if(![response isKindOfClass:NSHTTPURLResponse.class]) {
|
||||
if(completionHandler) {
|
||||
completionHandler(@[]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
||||
if(httpResponse.statusCode != 200 || jsonData.length == 0) {
|
||||
if(completionHandler) {
|
||||
completionHandler(@[]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
id jsonRoot = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
|
||||
if(!jsonRoot || ![jsonRoot isKindOfClass:NSArray.class]) {
|
||||
if(completionHandler) {
|
||||
completionHandler(@[]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
NSMutableArray *items = [[NSMutableArray alloc] init];
|
||||
for(id item in jsonRoot) {
|
||||
if(![item isKindOfClass:NSDictionary.class]) {
|
||||
continue;
|
||||
}
|
||||
MPPluginRepositoryItem *pluginItem = [MPPluginRepositoryItem pluginItemFromDictionary:item];
|
||||
if(pluginItem.isVaid) {
|
||||
[items addObject:pluginItem];
|
||||
}
|
||||
}
|
||||
if(completionHandler) {
|
||||
completionHandler([items copy]);
|
||||
}
|
||||
}];
|
||||
|
||||
[downloadTask resume];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,18 +22,26 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class MPPluginHost;
|
||||
|
||||
@interface MPPluginRepositoryItem : NSObject
|
||||
|
||||
@property (copy,readonly) NSString *name;
|
||||
@property (copy,readonly) NSString *currentVersion;
|
||||
@property (copy,readonly) NSString *descriptionText;
|
||||
@property (copy,readonly) NSURL *sourceURL;
|
||||
@property (copy,readonly) NSURL *downloadURL;
|
||||
@property (copy,readonly) NSURL *bundleIdentifier;
|
||||
|
||||
@property (copy,readonly, nullable) NSString *name;
|
||||
@property (copy,readonly, nullable) NSString *currentVersion;
|
||||
@property (copy,readonly, nullable) NSString *descriptionText;
|
||||
@property (copy,readonly, nullable) NSURL *sourceURL;
|
||||
@property (copy,readonly, nullable) NSURL *downloadURL;
|
||||
@property (copy,readonly, nullable) NSString *bundleIdentifier;
|
||||
|
||||
@property (readonly, nonatomic, getter=isVaid) BOOL valid;
|
||||
|
||||
+ (instancetype)pluginItemFromDictionary:(NSDictionary *)dict;
|
||||
- (instancetype)initWithDictionary:(NSDictionary *)dict;
|
||||
- (BOOL)isPluginVersion:(NSString * _Nullable )pluginVersionString compatibleWithHost:(MPPluginHost *)host;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -21,6 +21,11 @@
|
||||
//
|
||||
|
||||
#import "MPPluginRepositoryItem.h"
|
||||
#import "MPPluginRepositoryItemVersionInfo.h"
|
||||
#import "MPPluginVersion.h"
|
||||
#import "MPPluginHost.h"
|
||||
#import "MPPlugin.h"
|
||||
#import "NSError+Messages.h"
|
||||
|
||||
|
||||
NSString *const MPPluginItemNameKey = @"name";
|
||||
@@ -29,6 +34,7 @@ NSString *const MPPluginItemDownloadURLKey = @"download";
|
||||
NSString *const MPPluginItemSourceURLKey = @"source";
|
||||
NSString *const MPPluginItemCurrentVersionKey = @"currentVersion";
|
||||
NSString *const MPPluginItemBundleIdentifierKey = @"bundleIdentifier";
|
||||
NSString *const MPPluginItemCompatibiltyKey = @"compatibilty";
|
||||
|
||||
@interface MPPluginRepositoryItem ()
|
||||
|
||||
@@ -37,7 +43,9 @@ NSString *const MPPluginItemBundleIdentifierKey = @"bundleIdentifier";
|
||||
@property (copy) NSString *descriptionText;
|
||||
@property (copy) NSURL *sourceURL;
|
||||
@property (copy) NSURL *downloadURL;
|
||||
@property (copy) NSURL *bundleIdentifier;
|
||||
@property (copy) NSString *bundleIdentifier;
|
||||
@property (copy) NSArray *compatibilty;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -58,6 +66,8 @@ NSString *const MPPluginItemBundleIdentifierKey = @"bundleIdentifier";
|
||||
self.sourceURL = [NSURL URLWithString:dict[MPPluginItemSourceURLKey]];
|
||||
self.currentVersion = dict[MPPluginItemCurrentVersionKey];
|
||||
self.bundleIdentifier = dict[MPPluginItemBundleIdentifierKey];
|
||||
[self _buildVersionInfos:dict[MPPluginItemCompatibiltyKey]];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -67,4 +77,50 @@ NSString *const MPPluginItemBundleIdentifierKey = @"bundleIdentifier";
|
||||
return (self.name.length > 0 && self.downloadURL);
|
||||
}
|
||||
|
||||
- (BOOL)isPluginVersion:(NSString *)pluginVersionString compatibleWithHost:(MPPluginHost *)host {
|
||||
if(pluginVersionString.length == 0) {
|
||||
return NO;
|
||||
}
|
||||
MPPluginVersion *pluginVersion = [MPPluginVersion versionWithVersionString:pluginVersionString];
|
||||
if(!pluginVersion) {
|
||||
return NO;
|
||||
}
|
||||
if(host.version.length == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
MPPluginVersion *hostVersion = [MPPluginVersion versionWithVersionString:host.version];
|
||||
if(!hostVersion) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSMutableArray<MPPluginRepositoryItemVersionInfo *> *matches = [[NSMutableArray alloc] init];
|
||||
for(MPPluginRepositoryItemVersionInfo *info in self.compatibilty) {
|
||||
if(NSOrderedSame == [info.version compare:pluginVersion]) {
|
||||
[matches addObject:info];
|
||||
}
|
||||
}
|
||||
|
||||
if(matches.count != 1) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
MPPluginRepositoryItemVersionInfo *matchingInfo = matches.firstObject;
|
||||
return [matchingInfo isCompatibleWithHostVersion:hostVersion];
|
||||
}
|
||||
|
||||
- (void)_buildVersionInfos:(NSArray<NSDictionary *>*)infos {
|
||||
NSMutableArray *tmp = [[NSMutableArray alloc] init];
|
||||
for(NSDictionary *dict in infos) {
|
||||
if(![dict isKindOfClass:NSDictionary.class]) {
|
||||
continue;
|
||||
}
|
||||
MPPluginRepositoryItemVersionInfo *info = [MPPluginRepositoryItemVersionInfo versionInfoWithDict:dict];
|
||||
if(info){
|
||||
[tmp addObject:info];
|
||||
}
|
||||
}
|
||||
self.compatibilty = [tmp copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,11 +10,19 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class MPPluginVersion;
|
||||
|
||||
@interface MPPluginRepositoryItemVersionInfo : NSObject
|
||||
|
||||
@property (copy, readonly) MPPluginVersion *version;
|
||||
|
||||
+ (instancetype)versionInfoWithDict:(NSDictionary *)dict;
|
||||
|
||||
- (instancetype)initWithDict:(NSDictionary *)dict NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (BOOL)isCompatibleWithHostVersion:(MPPluginVersion *)hostVersion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -7,30 +7,75 @@
|
||||
//
|
||||
|
||||
#import "MPPluginRepositoryItemVersionInfo.h"
|
||||
#import "MPPluginVersion.h"
|
||||
|
||||
NSString *const MPPluginItemCompatibiltyVersionKey = @"pluginVersion";
|
||||
NSString *const MPPluginItemCompatibiltyMinimumHostVersionKey = @"minimumHostVersion";
|
||||
NSString *const MPPluginItemCompatibiltyMaxiumumHostVersionKey = @"maxiumumHostVersion";
|
||||
NSString *const MPPluginItemCompatibiltyMaxiumumHostVersionKey = @"maximumHostVersion";
|
||||
|
||||
@interface MPPluginRepositoryItemVersionInfo ()
|
||||
|
||||
@property (copy) NSString *version;
|
||||
@property (copy) NSString *minimumHostVersion;
|
||||
@property (copy) NSString *maxiumHostVersion;
|
||||
|
||||
@property (copy) MPPluginVersion *version;
|
||||
@property (copy) MPPluginVersion *minimumHostVersion;
|
||||
@property (copy) MPPluginVersion *maxiumHostVersion;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPluginRepositoryItemVersionInfo
|
||||
|
||||
+ (instancetype)versionInfoWithDict:(NSDictionary *)dict {
|
||||
return [[MPPluginRepositoryItemVersionInfo alloc] initWithDict:dict];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDict:(NSDictionary *)dict {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
self.version = dict[MPPluginItemCompatibiltyVersionKey];
|
||||
self.minimumHostVersion = dict[MPPluginItemCompatibiltyMinimumHostVersionKey];
|
||||
self.maxiumHostVersion = dict[MPPluginItemCompatibiltyMaxiumumHostVersionKey];
|
||||
NSString *versionString = dict[MPPluginItemCompatibiltyVersionKey];
|
||||
if(!versionString) {
|
||||
NSLog(@"Version information is missing required %@ key.", MPPluginItemCompatibiltyVersionKey);
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
self.version = [MPPluginVersion versionWithVersionString:versionString];
|
||||
if(!self.version) {
|
||||
NSLog(@"Malformed plugin version information: %@.", versionString);
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
NSString *minimumHostVersionString = dict[MPPluginItemCompatibiltyMinimumHostVersionKey];
|
||||
if(!minimumHostVersionString) {
|
||||
NSLog(@"Version information is missing required %@ key.", MPPluginItemCompatibiltyMinimumHostVersionKey);
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
self.minimumHostVersion = [MPPluginVersion versionWithVersionString:minimumHostVersionString];
|
||||
if(!self.minimumHostVersion) {
|
||||
NSLog(@"Malformed minimum host version information: %@.", minimumHostVersionString);
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
NSString *maxiumHostVersionString = dict[MPPluginItemCompatibiltyMaxiumumHostVersionKey];
|
||||
if(maxiumHostVersionString) {
|
||||
self.maxiumHostVersion = [MPPluginVersion versionWithVersionString:maxiumHostVersionString];
|
||||
if(!self.maxiumHostVersion) {
|
||||
NSLog(@"Malformed maxium host version information: %@.", maxiumHostVersionString);
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isCompatibleWithHostVersion:(MPPluginVersion *)hostVersion {
|
||||
if(NSOrderedDescending == [self.minimumHostVersion compare:hostVersion]) {
|
||||
return NO;
|
||||
}
|
||||
if(!self.maxiumHostVersion) {
|
||||
return YES;
|
||||
}
|
||||
return (NSOrderedAscending != [self.maxiumHostVersion compare:hostVersion]);
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#import "MPPlugin.h"
|
||||
#import "MPPlugin_Private.h"
|
||||
#import "MPPluginConstants.h"
|
||||
#import "MPPluginRepository.h"
|
||||
#import "MPPluginRepositoryItem.h"
|
||||
|
||||
#import "MPConstants.h"
|
||||
#import "MPSettingsHelper.h"
|
||||
@@ -96,7 +98,7 @@ typedef NS_ENUM(NSUInteger, MPPluginSegmentType) {
|
||||
? [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_NAME_ERROR_%@", "Name for unloaded plugin with errors"), plugin.name]
|
||||
: [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_NAME_DISABLED_%@", "name for disabled unloaded plugin"), plugin.name]);
|
||||
}
|
||||
view.addionalTextField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_VERSION_%@", "Plugin version. Include a %@ placeholder for version string"), plugin.version];
|
||||
view.addionalTextField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"PLUGIN_VERSION_%@", "Plugin version. Include a %@ placeholder for version string"), plugin.versionString];
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
31
MacPass/MPPluginVersion.h
Normal file
31
MacPass/MPPluginVersion.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// MPPluginVersion.h
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 05.10.18.
|
||||
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSString *MPPluginVersionWildcard;
|
||||
|
||||
@interface MPPluginVersion : NSObject <NSCopying>
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *versionString;
|
||||
@property (nonatomic, copy, readonly) NSString *mayorVersion;
|
||||
@property (nonatomic, copy, readonly) NSString *minorVersion;
|
||||
@property (nonatomic, copy, readonly) NSString *patchVersion;
|
||||
|
||||
+ (instancetype)versionWithVersionString:(NSString *)versionString;
|
||||
|
||||
- (instancetype)initWithVersionString:(NSString *)versionString NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (NSComparisonResult)compare:(MPPluginVersion *)version;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
122
MacPass/MPPluginVersion.m
Normal file
122
MacPass/MPPluginVersion.m
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// MPPluginVersion.m
|
||||
// MacPass
|
||||
//
|
||||
// Created by Michael Starke on 05.10.18.
|
||||
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPPluginVersion.h"
|
||||
|
||||
NSString *MPPluginVersionWildcard = @"*";
|
||||
|
||||
@interface MPPluginVersion ()
|
||||
|
||||
@property (nonatomic, copy) NSString *versionString;
|
||||
@property (nonatomic, copy) NSString *mayorVersion;
|
||||
@property (nonatomic, copy) NSString *minorVersion;
|
||||
@property (nonatomic, copy) NSString *patchVersion;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPPluginVersion
|
||||
|
||||
+ (instancetype)versionWithVersionString:(NSString *)versionString {
|
||||
return [[MPPluginVersion alloc] initWithVersionString:versionString];
|
||||
}
|
||||
|
||||
- (instancetype)initWithVersionString:(NSString *)versionString {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
self.mayorVersion = @"0";
|
||||
self.minorVersion = @"0";
|
||||
self.patchVersion = @"0";
|
||||
|
||||
NSArray<NSString *>* components = [versionString componentsSeparatedByString:@"."];
|
||||
if(components.count >= 1) {
|
||||
|
||||
NSString *mayorVersion = components[0].length > 0 ? components[0] : @"0";
|
||||
if([mayorVersion isEqualToString:MPPluginVersionWildcard]) {
|
||||
self.mayorVersion = MPPluginVersionWildcard;
|
||||
self.minorVersion = MPPluginVersionWildcard;
|
||||
self.patchVersion = MPPluginVersionWildcard;
|
||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
||||
return self;
|
||||
}
|
||||
NSCharacterSet *invalidSet = NSCharacterSet.decimalDigitCharacterSet.invertedSet;
|
||||
NSRange mayorRange = [mayorVersion rangeOfCharacterFromSet:invalidSet];
|
||||
if(mayorRange.location != NSNotFound) {
|
||||
NSLog(@"Invalid Format for Mayor Version");
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
self.mayorVersion = mayorVersion;
|
||||
|
||||
if(components.count >= 2) {
|
||||
NSString *minorVersion = components[1].length > 0 ? components[1] : @"0";
|
||||
if([minorVersion isEqualToString:MPPluginVersionWildcard]) {
|
||||
self.minorVersion = MPPluginVersionWildcard;
|
||||
self.patchVersion = MPPluginVersionWildcard;
|
||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
||||
return self;
|
||||
}
|
||||
NSRange minorRange = [minorVersion rangeOfCharacterFromSet:invalidSet];
|
||||
if(minorRange.location != NSNotFound) {
|
||||
NSLog(@"Invalid Format for Minor Version");
|
||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
self.minorVersion = minorVersion;
|
||||
|
||||
if(components.count == 3) {
|
||||
NSString *patchVersion = components[2].length > 0 ? components[2] : @"0";
|
||||
if([patchVersion isEqualToString:MPPluginVersionWildcard]) {
|
||||
self.patchVersion = MPPluginVersionWildcard;
|
||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
||||
return self;
|
||||
}
|
||||
NSRange patchRange = [patchVersion rangeOfCharacterFromSet:invalidSet];
|
||||
if(patchRange.location != NSNotFound) {
|
||||
NSLog(@"Invalid Format for Patch Version");
|
||||
self = nil;
|
||||
return self;
|
||||
}
|
||||
self.patchVersion = patchVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.versionString = [NSString stringWithFormat:@"%@.%@.%@", self.mayorVersion, self.minorVersion, self.patchVersion];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSComparisonResult)compare:(MPPluginVersion *)version {
|
||||
if([self.versionString isEqualToString:version.versionString]) {
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
NSArray<NSString *> *myVersions = @[self.mayorVersion, self.minorVersion, self.patchVersion];
|
||||
NSArray<NSString *> *otherVersions = @[version.mayorVersion, version.minorVersion, version.patchVersion];
|
||||
|
||||
for(NSUInteger index = 0; index < 3; index++) {
|
||||
NSString *myVersion = myVersions[index];
|
||||
NSString *otherVersion = otherVersions[index];
|
||||
|
||||
if([myVersion isEqualToString:MPPluginVersionWildcard] || [otherVersion isEqualToString:MPPluginVersionWildcard]) {
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
NSComparisonResult compare = [myVersion compare:otherVersion options:NSNumericSearch|NSCaseInsensitiveSearch];
|
||||
if(compare != NSOrderedSame) {
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
return NSOrderedSame;
|
||||
}
|
||||
|
||||
@end
|
||||
150
MacPassTests/MPTestPluginVersion.m
Normal file
150
MacPassTests/MPTestPluginVersion.m
Normal file
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// MPTestPluginVersion.m
|
||||
// MacPassTests
|
||||
//
|
||||
// Created by Michael Starke on 05.10.18.
|
||||
// Copyright © 2018 HicknHack Software GmbH. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "MPPluginVersion.h"
|
||||
|
||||
@interface MPTestPluginVersion : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPTestPluginVersion
|
||||
|
||||
- (void)testVersionExtraction {
|
||||
MPPluginVersion *version = [[MPPluginVersion alloc] initWithVersionString:@"1."];
|
||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"1.0.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.5"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"5", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.5.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@".5"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"5", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.5.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"5"];
|
||||
XCTAssertEqualObjects(@"5", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"5.0.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@".1."];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.1.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@".1.1"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.1.1", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"..1"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.0.1", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.0.0"];
|
||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"1.0.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.1.0"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.1.0", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.1.1"];
|
||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"1.1.1", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.0.5"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"5", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.0.5", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.0.3"];
|
||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"0", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"3", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"1.0.3", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.1.4"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"4", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.1.4", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"0.1.*"];
|
||||
XCTAssertEqualObjects(@"0", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"1", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"*", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"0.1.*", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"*.1.0"];
|
||||
XCTAssertEqualObjects(@"*", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"*", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"*", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"*.*.*", version.versionString);
|
||||
|
||||
version = [[MPPluginVersion alloc] initWithVersionString:@"1.*.0"];
|
||||
XCTAssertEqualObjects(@"1", version.mayorVersion);
|
||||
XCTAssertEqualObjects(@"*", version.minorVersion);
|
||||
XCTAssertEqualObjects(@"*", version.patchVersion);
|
||||
XCTAssertEqualObjects(@"1.*.*", version.versionString);
|
||||
}
|
||||
|
||||
- (void)testeVersionCompare {
|
||||
|
||||
NSArray *data = @[
|
||||
@[ @"*", @"*", @(NSOrderedSame)],
|
||||
@[ @"1.0.1", @"*", @(NSOrderedSame)],
|
||||
@[ @"*", @"1.0.1", @(NSOrderedSame)],
|
||||
@[ @"1.*", @"1.*", @(NSOrderedSame)],
|
||||
@[ @"1.1.*", @"1.1.*", @(NSOrderedSame)],
|
||||
@[ @"1.1.1", @"1.1.1", @(NSOrderedSame)],
|
||||
@[ @"1.0.1", @"*", @(NSOrderedSame)],
|
||||
@[ @"0.10.*", @"0.10.1", @(NSOrderedSame)],
|
||||
@[ @"10.*.1", @"10.99.*", @(NSOrderedSame)],
|
||||
@[ @"0.9.89", @"0.9.89", @(NSOrderedSame)],
|
||||
@[ @"0.0.1", @"0.0.2", @(NSOrderedAscending)],
|
||||
@[ @"1.10.10", @"1.12.10", @(NSOrderedAscending)],
|
||||
@[ @"20.0.1", @"20.1.0", @(NSOrderedAscending)],
|
||||
@[ @"1.1.1", @"2.*", @(NSOrderedAscending)],
|
||||
@[ @"1.*", @"2.0.*", @(NSOrderedAscending)],
|
||||
@[ @"2.1.1", @"2.0.0", @(NSOrderedDescending)],
|
||||
@[ @"0.1.1", @"0.1.0", @(NSOrderedDescending)],
|
||||
@[ @"1.2.*", @"1.1.*", @(NSOrderedDescending)],
|
||||
@[ @"2.*", @"1.*", @(NSOrderedDescending)]
|
||||
];
|
||||
for(NSUInteger index = 0; index < data.count; index++) {
|
||||
NSArray *set = data[index];
|
||||
MPPluginVersion *versionA = [[MPPluginVersion alloc] initWithVersionString:set[0]];
|
||||
MPPluginVersion *versionB = [[MPPluginVersion alloc] initWithVersionString:set[1]];
|
||||
NSComparisonResult result = [set[2] integerValue];
|
||||
XCTAssertEqual(result, [versionA compare:versionB]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user