Update: Add option to check for nightly updates

Use Appveyor REST API to obtain information about latest build from master.
This commit is contained in:
ge0rdi
2020-09-14 15:20:20 +02:00
parent ed3da927cc
commit fbcf85559e
6 changed files with 175 additions and 13 deletions

View File

@@ -318,6 +318,7 @@ struct VersionCheckParams
TSettingsComponent component; TSettingsComponent component;
tNewVersionCallback callback; tNewVersionCallback callback;
CProgressDlg *progress; CProgressDlg *progress;
bool nightly = false;
}; };
// 0 - fail, 1 - success, 2 - cancel // 0 - fail, 1 - success, 2 - cancel
@@ -342,7 +343,7 @@ static DWORD WINAPI ThreadVersionCheck( void *param )
VersionData data; VersionData data;
{ {
auto load = data.Load(); auto load = params.nightly ? data.LoadNightly() : data.Load();
#ifdef UPDATE_LOG #ifdef UPDATE_LOG
LogToFile(UPDATE_LOG, L"Load result: %d", load); LogToFile(UPDATE_LOG, L"Load result: %d", load);
@@ -450,6 +451,21 @@ DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionChec
params->callback=callback; params->callback=callback;
params->progress=NULL; params->progress=NULL;
// check the Update setting (uses the current value in the registry, not the one from memory
{
CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser;
bool bUpgrade = OpenSettingsKeys(COMPONENT_SHARED, regSettings, regSettingsUser, regPolicy, regPolicyUser);
CSetting settings[] = {
{L"Nightly",CSetting::TYPE_BOOL,0,0,0},
{NULL}
};
settings[0].LoadValue(regSettings, regSettingsUser, regPolicy, regPolicyUser);
params->nightly = GetSettingBool(settings[0]);
}
if (!owner) if (!owner)
return ThreadVersionCheck(params); return ThreadVersionCheck(params);
@@ -495,19 +511,23 @@ DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionChec
return 0; // check weekly return 0; // check weekly
// check the Update setting (uses the current value in the registry, not the one from memory // check the Update setting (uses the current value in the registry, not the one from memory
bool nightly = false;
{ {
CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser; CRegKey regSettings, regSettingsUser, regPolicy, regPolicyUser;
bool bUpgrade=OpenSettingsKeys(COMPONENT_SHARED,regSettings,regSettingsUser,regPolicy,regPolicyUser); bool bUpgrade=OpenSettingsKeys(COMPONENT_SHARED,regSettings,regSettingsUser,regPolicy,regPolicyUser);
CSetting settings[]={ CSetting settings[]={
{L"Update",CSetting::TYPE_BOOL,0,0,1}, {L"Update",CSetting::TYPE_BOOL,0,0,1},
{L"Nightly",CSetting::TYPE_BOOL,0,0,0},
{NULL} {NULL}
}; };
settings[0].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser); settings[0].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser);
settings[1].LoadValue(regSettings,regSettingsUser,regPolicy,regPolicyUser);
if (!GetSettingBool(settings[0])) if (!GetSettingBool(settings[0]))
return 0; return 0;
nightly = GetSettingBool(settings[1]);
} }
VersionCheckParams *params=new VersionCheckParams; VersionCheckParams *params=new VersionCheckParams;
@@ -515,6 +535,7 @@ DWORD CheckForNewVersion( HWND owner, TSettingsComponent component, TVersionChec
params->component=component; params->component=component;
params->callback=callback; params->callback=callback;
params->progress=NULL; params->progress=NULL;
params->nightly=nightly;
g_bCheckingVersion=true; g_bCheckingVersion=true;
if (check==CHECK_AUTO_WAIT) if (check==CHECK_AUTO_WAIT)
@@ -810,6 +831,116 @@ VersionData::TLoadResult VersionData::Load()
} }
} }
VersionData::TLoadResult VersionData::LoadNightly()
{
Clear();
auto buf = DownloadUrl(L"https://ci.appveyor.com/api/projects/passionate-coder/open-shell-menu/branch/master");
if (buf.empty())
return LOAD_ERROR;
try
{
auto data = json::parse(buf.begin(), buf.end());
auto build = data["build"];
// get version
auto version = build["version"].get<std::string>();
if (version.empty())
return LOAD_BAD_FILE;
{
int v1, v2, v3;
if (sscanf_s(version.c_str(), "%d.%d.%d", &v1, &v2, &v3) != 3)
return LOAD_BAD_FILE;
newVersion = (v1 << 24) | (v2 << 16) | v3;
if (newVersion <= GetVersionEx(g_Instance))
return LOAD_OK;
}
// artifact url
{
auto jobId = build["jobs"][0]["jobId"].get<std::string>();
if (jobId.empty())
return LOAD_BAD_FILE;
std::wstring jobUrl(L"https://ci.appveyor.com/api/buildjobs/");
jobUrl += std::wstring(jobId.begin(), jobId.end());
jobUrl += L"/artifacts";
buf = DownloadUrl(jobUrl.c_str());
if (buf.empty())
return LOAD_ERROR;
auto artifacts = json::parse(buf.begin(), buf.end());
std::string fileName;
for (const auto& artifact : artifacts)
{
auto name = artifact["fileName"].get<std::string>();
if (name.find("OpenShellSetup") == 0)
{
fileName = name;
break;
}
}
if (fileName.empty())
return LOAD_BAD_FILE;
auto artifactUrl(jobUrl);
artifactUrl += L'/';
artifactUrl += std::wstring(fileName.begin(), fileName.end());
downloadUrl = artifactUrl.c_str();
}
// changelog
news.Append(CA2T(version.c_str()));
news.Append(L"\r\n\r\n");
try
{
// use Github API to compare commit that actual version was built from (APPVEYOR_REPO_COMMIT)
// and commit that AppVeyor version was built from (commitId)
auto commitId = build["commitId"].get<std::string>();
std::wstring compareUrl(L"https://api.github.com/repos/Open-Shell/Open-Shell-Menu/compare/");
compareUrl += _T(APPVEYOR_REPO_COMMIT);
compareUrl += L"...";
compareUrl += std::wstring(commitId.begin(), commitId.end());
buf = DownloadUrl(compareUrl.c_str());
auto compare = json::parse(buf.begin(), buf.end());
// then use first lines (subjects) of commit messages as changelog
auto commits = compare["commits"];
for (const auto& commit : commits)
{
auto message = commit["commit"]["message"].get<std::string>();
auto pos = message.find('\n');
if (pos != message.npos)
message.resize(pos);
news.Append(L"- ");
news.Append(CA2T(message.c_str()));
news.Append(L"\r\n");
}
}
catch (...)
{
}
}
catch (...)
{
return LOAD_BAD_FILE;
}
return LOAD_OK;
}
VersionData::TLoadResult VersionData::Load( const wchar_t *fname, bool bLoadFlags ) VersionData::TLoadResult VersionData::Load( const wchar_t *fname, bool bLoadFlags )
{ {
Clear(); Clear();

View File

@@ -60,6 +60,7 @@ struct VersionData
}; };
TLoadResult Load(); TLoadResult Load();
TLoadResult LoadNightly();
TLoadResult Load( const wchar_t *fname, bool bLoadFlags ); TLoadResult Load( const wchar_t *fname, bool bLoadFlags );
private: private:
void operator=( const VersionData& ); void operator=( const VersionData& );

View File

@@ -83,6 +83,11 @@
<OutDir>$(Configuration)64\</OutDir> <OutDir>$(Configuration)64\</OutDir>
<IntDir>$(Configuration)64\</IntDir> <IntDir>$(Configuration)64\</IntDir>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>APPVEYOR_REPO_COMMIT="$(APPVEYOR_REPO_COMMIT)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>

View File

@@ -60,11 +60,13 @@ static CSetting g_Settings[]={
{L"Update",CSetting::TYPE_GROUP}, {L"Update",CSetting::TYPE_GROUP},
{L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_SHARED}, {L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_SHARED},
{L"Update",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_SHARED}, {L"Update",CSetting::TYPE_BOOL,0,0,1,CSetting::FLAG_SHARED},
{L"Nightly",CSetting::TYPE_BOOL,0,0,0,CSetting::FLAG_SHARED},
{NULL} {NULL}
}; };
const int SETTING_UPDATE=2; const int SETTING_UPDATE=2;
const int SETTING_NIGHTLY=3;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@@ -79,6 +81,7 @@ public:
MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo ) MESSAGE_HANDLER( WM_GETMINMAXINFO, OnGetMinMaxInfo )
MESSAGE_HANDLER( WM_CTLCOLORSTATIC, OnColorStatic ) MESSAGE_HANDLER( WM_CTLCOLORSTATIC, OnColorStatic )
COMMAND_HANDLER( IDC_CHECKAUTOCHECK, BN_CLICKED, OnCheckAuto ) COMMAND_HANDLER( IDC_CHECKAUTOCHECK, BN_CLICKED, OnCheckAuto )
COMMAND_HANDLER( IDC_CHECKNIGHTLY, BN_CLICKED, OnCheckNightly )
COMMAND_HANDLER( IDC_BUTTONCHECKNOW, BN_CLICKED, OnCheckNow ) COMMAND_HANDLER( IDC_BUTTONCHECKNOW, BN_CLICKED, OnCheckNow )
COMMAND_HANDLER( IDC_BUTTONDOWNLOAD, BN_CLICKED, OnDownload ) COMMAND_HANDLER( IDC_BUTTONDOWNLOAD, BN_CLICKED, OnDownload )
COMMAND_HANDLER( IDC_CHECKDONT, BN_CLICKED, OnDontRemind ) COMMAND_HANDLER( IDC_CHECKDONT, BN_CLICKED, OnDontRemind )
@@ -114,6 +117,7 @@ protected:
LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); LRESULT OnCancel( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
LRESULT OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled ); LRESULT OnColorStatic( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
LRESULT OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); LRESULT OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
LRESULT OnCheckNightly( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
LRESULT OnCheckNow( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); LRESULT OnCheckNow( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
LRESULT OnDownload( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); LRESULT OnDownload( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
LRESULT OnDontRemind( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled ); LRESULT OnDontRemind( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled );
@@ -161,6 +165,13 @@ LRESULT CUpdateDlg::OnInitDialog( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
CheckDlgButton(IDC_CHECKAUTOCHECK,check?BST_CHECKED:BST_UNCHECKED); CheckDlgButton(IDC_CHECKAUTOCHECK,check?BST_CHECKED:BST_UNCHECKED);
GetDlgItem(IDC_CHECKAUTOCHECK).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK)); GetDlgItem(IDC_CHECKAUTOCHECK).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK));
GetDlgItem(IDC_BUTTONCHECKNOW).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK) || check); GetDlgItem(IDC_BUTTONCHECKNOW).EnableWindow(!(g_Settings[SETTING_UPDATE].flags&CSetting::FLAG_LOCKED_MASK) || check);
bool nightly = false;
if (g_Settings[SETTING_NIGHTLY].value.vt == VT_I4)
nightly = g_Settings[SETTING_NIGHTLY].value.intVal != 0;
CheckDlgButton(IDC_CHECKNIGHTLY, nightly ? BST_CHECKED : BST_UNCHECKED);
GetDlgItem(IDC_CHECKNIGHTLY).EnableWindow(!(g_Settings[SETTING_NIGHTLY].flags & CSetting::FLAG_LOCKED_MASK) && check);
UpdateUI(); UpdateUI();
return TRUE; return TRUE;
@@ -210,6 +221,17 @@ LRESULT CUpdateDlg::OnCheckAuto( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL&
bool check=IsDlgButtonChecked(IDC_CHECKAUTOCHECK)==BST_CHECKED; bool check=IsDlgButtonChecked(IDC_CHECKAUTOCHECK)==BST_CHECKED;
g_Settings[SETTING_UPDATE].value=CComVariant(check?1:0); g_Settings[SETTING_UPDATE].value=CComVariant(check?1:0);
g_Settings[SETTING_UPDATE].flags&=~CSetting::FLAG_DEFAULT; g_Settings[SETTING_UPDATE].flags&=~CSetting::FLAG_DEFAULT;
GetDlgItem(IDC_CHECKNIGHTLY).EnableWindow(check);
UpdateUI();
return 0;
}
LRESULT CUpdateDlg::OnCheckNightly(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
CSettingsLockWrite lock;
bool check = IsDlgButtonChecked(IDC_CHECKNIGHTLY) == BST_CHECKED;
g_Settings[SETTING_NIGHTLY].value = CComVariant(check ? 1 : 0);
g_Settings[SETTING_NIGHTLY].flags &= ~CSetting::FLAG_DEFAULT;
UpdateUI(); UpdateUI();
return 0; return 0;
} }

View File

@@ -123,22 +123,24 @@ END
// Dialog // Dialog
// //
IDD_UPDATE DIALOGEX 0, 0, 316, 183 IDD_UPDATE DIALOGEX 0, 0, 316, 200
STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME STYLE DS_SETFONT | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Open-Shell Update" CAPTION "Open-Shell Update"
FONT 9, "Segoe UI", 400, 0, 0x0 FONT 9, "Segoe UI", 400, 0, 0x0
BEGIN BEGIN
CONTROL "Automatically check for new versions",IDC_CHECKAUTOCHECK, CONTROL "Automatically check for new versions",IDC_CHECKAUTOCHECK,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,129,10 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,129,10
PUSHBUTTON "Check now",IDC_BUTTONCHECKNOW,7,19,50,14 CONTROL "Check for nightly builds",IDC_CHECKNIGHTLY,
LTEXT "message",IDC_STATICLATEST,7,33,302,10,SS_CENTERIMAGE "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,19,151,10
EDITTEXT IDC_EDITTEXT,7,45,302,97,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | WS_VSCROLL PUSHBUTTON "Check now",IDC_BUTTONCHECKNOW,7,34,50,14
PUSHBUTTON "Download",IDC_BUTTONDOWNLOAD,7,146,50,14,NOT WS_VISIBLE LTEXT "message",IDC_STATICLATEST,7,48,302,10,SS_CENTERIMAGE
EDITTEXT IDC_EDITTEXT,7,60,302,97,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | NOT WS_VISIBLE | WS_VSCROLL
PUSHBUTTON "Download",IDC_BUTTONDOWNLOAD,7,161,50,14,NOT WS_VISIBLE
CONTROL "Don't remind me again about this version",IDC_CHECKDONT, CONTROL "Don't remind me again about this version",IDC_CHECKDONT,
"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,61,146,141,14 "Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,61,161,141,14
CONTROL "<a>Open-Shell-Menu</a>",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,166,66,10,WS_EX_TRANSPARENT CONTROL "<a>Open-Shell-Menu</a>",IDC_LINKWEB,"SysLink",WS_TABSTOP,7,181,66,10,WS_EX_TRANSPARENT
DEFPUSHBUTTON "OK",IDOK,202,162,50,14 DEFPUSHBUTTON "OK",IDOK,202,177,50,14
PUSHBUTTON "Cancel",IDCANCEL,259,162,50,14 PUSHBUTTON "Cancel",IDCANCEL,259,177,50,14
END END
@@ -155,7 +157,7 @@ BEGIN
LEFTMARGIN, 7 LEFTMARGIN, 7
RIGHTMARGIN, 309 RIGHTMARGIN, 309
TOPMARGIN, 7 TOPMARGIN, 7
BOTTOMMARGIN, 174 BOTTOMMARGIN, 191
END END
END END
#endif // APSTUDIO_INVOKED #endif // APSTUDIO_INVOKED

View File

@@ -9,6 +9,7 @@
#define IDC_CHECKDONT 1004 #define IDC_CHECKDONT 1004
#define IDC_BUTTONCHECKNOW 1005 #define IDC_BUTTONCHECKNOW 1005
#define IDC_CHECKAUTOCHECK 1006 #define IDC_CHECKAUTOCHECK 1006
#define IDC_CHECKNIGHTLY 1007
#define IDD_UPDATE 6001 #define IDD_UPDATE 6001
#define IDS_UPDATED 6001 #define IDS_UPDATED 6001
#define IDS_OUTOFDATE 6002 #define IDS_OUTOFDATE 6002
@@ -21,7 +22,7 @@
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 227 #define _APS_NEXT_RESOURCE_VALUE 228
#define _APS_NEXT_COMMAND_VALUE 32769 #define _APS_NEXT_COMMAND_VALUE 32769
#define _APS_NEXT_CONTROL_VALUE 262 #define _APS_NEXT_CONTROL_VALUE 262
#define _APS_NEXT_SYMED_VALUE 106 #define _APS_NEXT_SYMED_VALUE 106