Skip to content

Commit fbcf855

Browse files
committed
Update: Add option to check for nightly updates
Use Appveyor REST API to obtain information about latest build from master.
1 parent ed3da92 commit fbcf855

File tree

6 files changed

+175
-13
lines changed

6 files changed

+175
-13
lines changed

Src/Lib/DownloadHelper.cpp

Lines changed: 133 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ struct VersionCheckParams
318318
TSettingsComponent component;
319319
tNewVersionCallback callback;
320320
CProgressDlg *progress;
321+
bool nightly = false;
321322
};
322323

323324
// 0 - fail, 1 - success, 2 - cancel
@@ -342,7 +343,7 @@ static DWORD WINAPI ThreadVersionCheck( void *param )
342343
VersionData data;
343344

344345
{
345-
auto load = data.Load();
346+
auto load = params.nightly ? data.LoadNightly() : data.Load();
346347

347348
#ifdef UPDATE_LOG
348349
LogToFile(UPDATE_LOG, L"Load result: %d", load);
@@ -450,6 +451,21 @@ DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionChec
450451
params->callback=callback;
451452
params->progress=NULL;
452453

454+
// check the Update setting (uses the current value in the registry, not the one from memory
455+
{
456+
CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser;
457+
bool bUpgrade = OpenSettingsKeys(COMPONENT_SHARED, regSettings, regSettingsUser, regPolicy, regPolicyUser);
458+
459+
CSetting settings[] = {
460+
{L"Nightly",CSetting::TYPE_BOOL,0,0,0},
461+
{NULL}
462+
};
463+
464+
settings[0].LoadValue(regSettings, regSettingsUser, regPolicy, regPolicyUser);
465+
466+
params->nightly = GetSettingBool(settings[0]);
467+
}
468+
453469
if (!owner)
454470
return ThreadVersionCheck(params);
455471

@@ -495,26 +511,31 @@ DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionChec
495511
return 0; // check weekly
496512

497513
// check the Update setting (uses the current value in the registry, not the one from memory
514+
bool nightly = false;
498515
{
499516
CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser;
500517
bool bUpgrade=OpenSettingsKeys(COMPONENT_SHARED,regSettings,regSettingsUser,regPolicy,regPolicyUser);
501518

502519
CSetting settings[]={
503520
{L"Update",CSetting::TYPE_BOOL,0,0,1},
521+
{L"Nightly",CSetting::TYPE_BOOL,0,0,0},
504522
{NULL}
505523
};
506524

507525
settings[0].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser);
526+
settings[1].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser);
508527

509528
if (!GetSettingBool(settings[0]))
510-
return 0;
529+
return 0;
530+
nightly = GetSettingBool(settings[1]);
511531
}
512532

513533
VersionCheckParams *params=new VersionCheckParams;
514534
params->check=check;
515535
params->component=component;
516536
params->callback=callback;
517537
params->progress=NULL;
538+
params->nightly=nightly;
518539

519540
g_bCheckingVersion=true;
520541
if (check==CHECK_AUTO_WAIT)
@@ -810,6 +831,116 @@ VersionData::TLoadResult VersionData::Load()
810831
}
811832
}
812833

834+
VersionData::TLoadResult VersionData::LoadNightly()
835+
{
836+
Clear();
837+
838+
auto buf = DownloadUrl(L"https://ci.appveyor.com/api/projects/passionate-coder/open-shell-menu/branch/master");
839+
if (buf.empty())
840+
return LOAD_ERROR;
841+
842+
try
843+
{
844+
auto data = json::parse(buf.begin(), buf.end());
845+
auto build = data["build"];
846+
847+
// get version
848+
auto version = build["version"].get<std::string>();
849+
if (version.empty())
850+
return LOAD_BAD_FILE;
851+
852+
{
853+
int v1, v2, v3;
854+
if (sscanf_s(version.c_str(), "%d.%d.%d", &v1, &v2, &v3) != 3)
855+
return LOAD_BAD_FILE;
856+
857+
newVersion = (v1 << 24) | (v2 << 16) | v3;
858+
859+
if (newVersion <= GetVersionEx(g_Instance))
860+
return LOAD_OK;
861+
}
862+
863+
// artifact url
864+
{
865+
auto jobId = build["jobs"][0]["jobId"].get<std::string>();
866+
if (jobId.empty())
867+
return LOAD_BAD_FILE;
868+
869+
std::wstring jobUrl(L"https://ci.appveyor.com/api/buildjobs/");
870+
jobUrl += std::wstring(jobId.begin(), jobId.end());
871+
jobUrl += L"/artifacts";
872+
873+
buf = DownloadUrl(jobUrl.c_str());
874+
if (buf.empty())
875+
return LOAD_ERROR;
876+
877+
auto artifacts = json::parse(buf.begin(), buf.end());
878+
879+
std::string fileName;
880+
for (const auto& artifact : artifacts)
881+
{
882+
auto name = artifact["fileName"].get<std::string>();
883+
if (name.find("OpenShellSetup") == 0)
884+
{
885+
fileName = name;
886+
break;
887+
}
888+
}
889+
890+
if (fileName.empty())
891+
return LOAD_BAD_FILE;
892+
893+
auto artifactUrl(jobUrl);
894+
artifactUrl += L'/';
895+
artifactUrl += std::wstring(fileName.begin(), fileName.end());
896+
897+
downloadUrl = artifactUrl.c_str();
898+
}
899+
900+
// changelog
901+
news.Append(CA2T(version.c_str()));
902+
news.Append(L"\r\n\r\n");
903+
try
904+
{
905+
// use Github API to compare commit that actual version was built from (APPVEYOR_REPO_COMMIT)
906+
// and commit that AppVeyor version was built from (commitId)
907+
auto commitId = build["commitId"].get<std::string>();
908+
909+
std::wstring compareUrl(L"https://api.github.com/repos/Open-Shell/Open-Shell-Menu/compare/");
910+
compareUrl += _T(APPVEYOR_REPO_COMMIT);
911+
compareUrl += L"...";
912+
compareUrl += std::wstring(commitId.begin(), commitId.end());
913+
914+
buf = DownloadUrl(compareUrl.c_str());
915+
auto compare = json::parse(buf.begin(), buf.end());
916+
917+
// then use first lines (subjects) of commit messages as changelog
918+
auto commits = compare["commits"];
919+
for (const auto& commit : commits)
920+
{
921+
auto message = commit["commit"]["message"].get<std::string>();
922+
923+
auto pos = message.find('\n');
924+
if (pos != message.npos)
925+
message.resize(pos);
926+
927+
news.Append(L"- ");
928+
news.Append(CA2T(message.c_str()));
929+
news.Append(L"\r\n");
930+
}
931+
}
932+
catch (...)
933+
{
934+
}
935+
}
936+
catch (...)
937+
{
938+
return LOAD_BAD_FILE;
939+
}
940+
941+
return LOAD_OK;
942+
}
943+
813944
VersionData::TLoadResult VersionData::Load( const wchar_t *fname, bool bLoadFlags )
814945
{
815946
Clear();

Src/Lib/DownloadHelper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct VersionData
6060
};
6161

6262
TLoadResult Load();
63+
TLoadResult LoadNightly();
6364
TLoadResult Load( const wchar_t *fname, bool bLoadFlags );
6465
private:
6566
void operator=( const VersionData& );

Src/Lib/Lib.vcxproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@
8383
<OutDir>$(Configuration)64\</OutDir>
8484
<IntDir>$(Configuration)64\</IntDir>
8585
</PropertyGroup>
86+
<ItemDefinitionGroup>
87+
<ClCompile>
88+
<PreprocessorDefinitions>APPVEYOR_REPO_COMMIT="$(APPVEYOR_REPO_COMMIT)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
89+
</ClCompile>
90+
</ItemDefinitionGroup>
8691
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
8792
<ClCompile>
8893
<Optimization>Disabled</Optimization>

Src/Update/Update.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,13 @@ static CSetting g_Settings[]={
6060
{L"Update",CSetting::TYPE_GROUP},
6161
{L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_SHARED},
6262
{L"Update",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_SHARED},
63+
{L"Nightly",CSetting::TYPE_BOOL,0,0,0,CSetting::FLAG_SHARED},
6364

6465
{NULL}
6566
};
6667

6768
const int SETTING_UPDATE=2;
69+
const int SETTING_NIGHTLY=3;
6870

6971
///////////////////////////////////////////////////////////////////////////////
7072

@@ -79,6 +81,7 @@ class CUpdateDlg: public CResizeableDlg<CUpdateDlg>
7981
MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo )
8082
MESSAGE_HANDLER( WM_CTLCOLORSTATIC, OnColorStatic )
8183
COMMAND_HANDLER( IDC_CHECKAUTOCHECK, BN_CLICKED, OnCheckAuto )
84+
COMMAND_HANDLER( IDC_CHECKNIGHTLY, BN_CLICKED, OnCheckNightly )
8285
COMMAND_HANDLER( IDC_BUTTONCHECKNOW, BN_CLICKED, OnCheckNow )
8386
COMMAND_HANDLER( IDC_BUTTONDOWNLOAD, BN_CLICKED, OnDownload )
8487
COMMAND_HANDLER( IDC_CHECKDONT, BN_CLICKED, OnDontRemind )
@@ -114,6 +117,7 @@ class CUpdateDlg: public CResizeableDlg<CUpdateDlg>
114117
LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
115118
LRESULT OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
116119
LRESULT OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
120+
LRESULT OnCheckNightly( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
117121
LRESULT OnCheckNow( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
118122
LRESULT OnDownload( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
119123
LRESULT OnDontRemind( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
@@ -161,6 +165,13 @@ LRESULT CUpdateDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
161165
CheckDlgButton(IDC_CHECKAUTOCHECK,check?BST_CHECKED:BST_UNCHECKED);
162166
GetDlgItem(IDC_CHECKAUTOCHECK).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK));
163167
GetDlgItem(IDC_BUTTONCHECKNOW).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK) || check);
168+
169+
bool nightly = false;
170+
if (g_Settings[SETTING_NIGHTLY].value.vt == VT_I4)
171+
nightly = g_Settings[SETTING_NIGHTLY].value.intVal != 0;
172+
CheckDlgButton(IDC_CHECKNIGHTLY, nightly ? BST_CHECKED : BST_UNCHECKED);
173+
GetDlgItem(IDC_CHECKNIGHTLY).EnableWindow(!(g_Settings[SETTING_NIGHTLY].flags & CSetting::FLAG_LOCKED_MASK) && check);
174+
164175
UpdateUI();
165176

166177
return TRUE;
@@ -210,6 +221,17 @@ LRESULT CUpdateDlg::OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL&
210221
bool check=IsDlgButtonChecked(IDC_CHECKAUTOCHECK)==BST_CHECKED;
211222
g_Settings[SETTING_UPDATE].value=CComVariant(check?1:0);
212223
g_Settings[SETTING_UPDATE].flags&=~CSetting::FLAG_DEFAULT;
224+
GetDlgItem(IDC_CHECKNIGHTLY).EnableWindow(check);
225+
UpdateUI();
226+
return 0;
227+
}
228+
229+
LRESULT CUpdateDlg::OnCheckNightly(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
230+
{
231+
CSettingsLockWrite lock;
232+
bool check = IsDlgButtonChecked(IDC_CHECKNIGHTLY) == BST_CHECKED;
233+
g_Settings[SETTING_NIGHTLY].value = CComVariant(check ? 1 : 0);
234+
g_Settings[SETTING_NIGHTLY].flags &= ~CSetting::FLAG_DEFAULT;
213235
UpdateUI();
214236
return 0;
215237
}

Src/Update/Update.rc

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,22 +123,24 @@ END
123123
// Dialog
124124
//
125125

126-
IDD_UPDATE DIALOGEX 0, 0, 316, 183
126+
IDD_UPDATE DIALOGEX 0, 0, 316, 200
127127
STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
128128
CAPTION "Open-Shell Update"
129129
FONT 9, "Segoe UI", 400, 0, 0x0
130130
BEGIN
131131
CONTROL "Automatically check for new versions",IDC_CHECKAUTOCHECK,
132132
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,129,10
133-
PUSHBUTTON "Check now",IDC_BUTTONCHECKNOW,7,19,50,14
134-
LTEXT "message",IDC_STATICLATEST,7,33,302,10,SS_CENTERIMAGE
135-
EDITTEXT IDC_EDITTEXT,7,45,302,97,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | WS_VSCROLL
136-
PUSHBUTTON "Download",IDC_BUTTONDOWNLOAD,7,146,50,14,NOT WS_VISIBLE
133+
CONTROL "Check for nightly builds",IDC_CHECKNIGHTLY,
134+
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,19,151,10
135+
PUSHBUTTON "Check now",IDC_BUTTONCHECKNOW,7,34,50,14
136+
LTEXT "message",IDC_STATICLATEST,7,48,302,10,SS_CENTERIMAGE
137+
EDITTEXT IDC_EDITTEXT,7,60,302,97,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | WS_VSCROLL
138+
PUSHBUTTON "Download",IDC_BUTTONDOWNLOAD,7,161,50,14,NOT WS_VISIBLE
137139
CONTROL "Don't remind me again about this version",IDC_CHECKDONT,
138-
"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,61,146,141,14
139-
CONTROL "<a>Open-Shell-Menu</a>",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,166,66,10,WS_EX_TRANSPARENT
140-
DEFPUSHBUTTON "OK",IDOK,202,162,50,14
141-
PUSHBUTTON "Cancel",IDCANCEL,259,162,50,14
140+
"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,61,161,141,14
141+
CONTROL "<a>Open-Shell-Menu</a>",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,181,66,10,WS_EX_TRANSPARENT
142+
DEFPUSHBUTTON "OK",IDOK,202,177,50,14
143+
PUSHBUTTON "Cancel",IDCANCEL,259,177,50,14
142144
END
143145

144146

@@ -155,7 +157,7 @@ BEGIN
155157
LEFTMARGIN, 7
156158
RIGHTMARGIN, 309
157159
TOPMARGIN, 7
158-
BOTTOMMARGIN, 174
160+
BOTTOMMARGIN, 191
159161
END
160162
END
161163
#endif // APSTUDIO_INVOKED

Src/Update/resource.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define IDC_CHECKDONT 1004
1010
#define IDC_BUTTONCHECKNOW 1005
1111
#define IDC_CHECKAUTOCHECK 1006
12+
#define IDC_CHECKNIGHTLY 1007
1213
#define IDD_UPDATE 6001
1314
#define IDS_UPDATED 6001
1415
#define IDS_OUTOFDATE 6002
@@ -21,7 +22,7 @@
2122
//
2223
#ifdef APSTUDIO_INVOKED
2324
#ifndef APSTUDIO_READONLY_SYMBOLS
24-
#define _APS_NEXT_RESOURCE_VALUE 227
25+
#define _APS_NEXT_RESOURCE_VALUE 228
2526
#define _APS_NEXT_COMMAND_VALUE 32769
2627
#define _APS_NEXT_CONTROL_VALUE 262
2728
#define _APS_NEXT_SYMED_VALUE 106

0 commit comments

Comments
 (0)