forked from sasq64/chipmachine
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCheckForUpdate.mm
More file actions
126 lines (102 loc) · 5.63 KB
/
Copy pathCheckForUpdate.mm
File metadata and controls
126 lines (102 loc) · 5.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#include "version.h"
#include <string>
// The Mac App Store build (CM_MAS) ships NO self-update check: the App Store
// delivers updates, and an app that phones api.github.com and offers a
// "View on GitHub" button to a newer build is both wrong for MAS and an App
// Store guideline violation (self-updating / steering users off-store). For
// CM_MAS the entry point at the bottom is a no-op and none of the
// GitHub-checking code below is compiled into the binary at all.
#ifndef CM_MAS
/**
* Helper to extract a normalized version string (e.g. "1.4.3") from a tag or VERSION_STR.
* It takes the first sequence of digits and dots it finds.
*/
static NSString* ExtractVersionNumber(NSString* source) {
if (!source) return nil;
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[0-9]+(\\.[0-9]+)+" options:0 error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:source options:0 range:NSMakeRange(0, [source length])];
if (match) {
return [source substringWithRange:match.range];
}
return source;
}
static void ProcessVersionComparison(NSString *latestTag) {
if (!latestTag) return;
// Normalize versions for accurate numeric comparison
NSString *cleanedRemoteVersion = ExtractVersionNumber(latestTag);
NSString *currentLocalVersion = ExtractVersionNumber([NSString stringWithUTF8String:VERSION_STR]);
if (!cleanedRemoteVersion || !currentLocalVersion) return;
// Use NSNumericSearch to handle version logic (e.g. 1.0.10 > 1.0.2)
NSComparisonResult result = [cleanedRemoteVersion compare:currentLocalVersion options:NSNumericSearch];
if (result == NSOrderedDescending) {
// A newer version is definitively available
dispatch_async(dispatch_get_main_queue(), ^{
NSAlert *alert = [[NSAlert alloc] init];
// PROGRAM_NAME, not a literal: the product was renamed to
// ChipMachinePlus, and this alert is the one piece of UI that still
// said "ChipMachineAS" to users.
[alert setMessageText:@PROGRAM_NAME " Update"];
NSString *informativeText = [NSString stringWithFormat:
@"You are running version %@. A newer version (%@) is now available.",
[NSString stringWithUTF8String:VERSION_STR], latestTag];
[alert setInformativeText:informativeText];
[alert addButtonWithTitle:@"View on GitHub"];
[alert addButtonWithTitle:@"Later"];
[alert setAlertStyle:NSAlertStyleInformational];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
if ([alert runModal] == NSAlertFirstButtonReturn) {
NSURL *githubURL = [NSURL URLWithString:@"https://github.com/mihailod/chipmachine/releases/latest"];
[[NSWorkspace sharedWorkspace] openURL:githubURL];
}
});
}
}
// Internal implementation of the update check using modern NSURLSession
static void PerformUpdateCheck() {
// --- DEBUG OVERRIDE START ---
// Check for a local file named "DEBUG_UPDATE_VERSION" in the executable directory
NSString *exeDir = [[NSBundle mainBundle] executablePath].stringByDeletingLastPathComponent;
NSString *debugFilePath = [exeDir stringByAppendingPathComponent:@"DEBUG_UPDATE_VERSION"];
if ([[NSFileManager defaultManager] fileExistsAtPath:debugFilePath]) {
NSString *debugVersion = [NSString stringWithContentsOfFile:debugFilePath encoding:NSUTF8StringEncoding error:nil];
if (debugVersion) {
debugVersion = [debugVersion stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(@"[Updater] DEBUG OVERRIDE: Simulating remote version %@", debugVersion);
ProcessVersionComparison(debugVersion);
return;
}
}
// --- DEBUG OVERRIDE END ---
NSString *urlStr = @"https://api.github.com/repos/mihailod/chipmachine/releases/latest";
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"GET"];
// Same rename as the alert title above. GitHub requires *a* User-Agent on
// api.github.com; the exact string is ours to choose.
[request setValue:@PROGRAM_NAME "-Updater" forHTTPHeaderField:@"User-Agent"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error || !data) return;
NSError *jsonError = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if (jsonError || !json || ![json isKindOfClass:[NSDictionary class]]) return;
NSString *latestTag = [json objectForKey:@"tag_name"];
ProcessVersionComparison(latestTag);
}] resume];
}
// Public entry point for C++ callers
extern "C" void InitializeUpdateVerificationSubsystem() {
// NSURLSession data tasks run on a background queue automatically,
// so we can call this directly without spawning a std::thread.
PerformUpdateCheck();
}
#else // CM_MAS
// Mac App Store build: updates are delivered by the App Store. No network
// request, no GitHub URL, no update prompt. Intentional no-op so main.cpp can
// call it unconditionally.
extern "C" void InitializeUpdateVerificationSubsystem() {}
#endif // CM_MAS