Skip to content

Commit

Permalink
Shows auto-updater progress in the same way as the modules
Browse files Browse the repository at this point in the history
Closes #1347 and #839 
incorporates changes from PR #1359 (to show update progress in the same window)
  • Loading branch information
politas committed Jul 13, 2016
1 parent ff85f71 commit 5428e94
Show file tree
Hide file tree
Showing 15 changed files with 270 additions and 164 deletions.
3 changes: 2 additions & 1 deletion AutoUpdate/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
*
* This simple program is used to replace the local ckan.exe with the latest one i.e. auto-update.
* It is a command-line tool only, meant to be invoked by the main CKAN process and not manually.
* Argument launch must be one of: launch, nolaunch
*
* Invoked as:
* AutoUpdate.exe <running CKAN PID> <running CKAN path> <updated CKAN path>
* AutoUpdate.exe <running CKAN PID> <running CKAN path> <updated CKAN path> <launch>
*/

namespace AutoUpdater
Expand Down
4 changes: 2 additions & 2 deletions Cmdline/Action/Upgrade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ public int RunCommand(CKAN.KSP ksp, object raw_options)

}

ModuleInstaller.GetInstance(ksp, User).Upgrade(to_upgrade, new NetAsyncDownloader(User));
ModuleInstaller.GetInstance(ksp, User).Upgrade(to_upgrade, new NetAsyncModulesDownloader(User));
}
else
{
// TODO: These instances all need to go.
ModuleInstaller.GetInstance(ksp, User).Upgrade(options.modules, new NetAsyncDownloader(User));
ModuleInstaller.GetInstance(ksp, User).Upgrade(options.modules, new NetAsyncModulesDownloader(User));
}
}
catch (ModuleNotFoundKraken kraken)
Expand Down
5 changes: 3 additions & 2 deletions Core/CKAN-core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<Compile Include="GameVersionProviders\KspBuildMap.cs" />
<Compile Include="Net\AutoUpdate.cs" />
<Compile Include="Net\IDownloader.cs" />
<Compile Include="Net\NetAsyncDownloader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="KSP.cs" />
<Compile Include="ModuleInstaller.cs" />
Expand All @@ -78,7 +79,7 @@
<Compile Include="Types\ModuleInstallDescriptor.cs" />
<Compile Include="Relationships\SanityChecker.cs" />
<Compile Include="Net\Net.cs" />
<Compile Include="Net\NetAsyncDownloader.cs" />
<Compile Include="Net\NetAsyncModulesDownloader.cs" />
<Compile Include="Relationships\RelationshipResolver.cs" />
<Compile Include="Net\Repo.cs" />
<Compile Include="Net\NetFileCache.cs" />
Expand Down Expand Up @@ -113,4 +114,4 @@
<ItemGroup />
<ItemGroup />
<ItemGroup />
</Project>
</Project>
2 changes: 1 addition & 1 deletion Core/ModuleInstaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public static string CachedOrDownload(string identifier, Version version, Uri ur
{
if (downloader == null)
{
downloader = new NetAsyncDownloader(User);
downloader = new NetAsyncModulesDownloader(User);
}

downloader.DownloadModules(ksp.Cache, downloads);
Expand Down
48 changes: 21 additions & 27 deletions Core/Net/AutoUpdate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public class AutoUpdate
private readonly Uri latestUpdaterReleaseApiUrl = new Uri(
"https://api.github.com/repos/KSP-CKAN/CKAN-autoupdate/releases/latest");

private Uri fetchedUpdaterUrl;
private Uri fetchedCkanUrl;
private Tuple<Uri, long> fetchedUpdaterUrl;
private Tuple<Uri, long> fetchedCkanUrl;

public Version LatestVersion { get; private set; }
public string ReleaseNotes { get; private set; }
Expand Down Expand Up @@ -113,7 +113,7 @@ public string ExtractReleaseNotes(string releaseBody)
/// and then launches the helper allowing us to upgrade.
/// </summary>
/// <param name="launchCKANAfterUpdate">If set to <c>true</c> launch CKAN after update.</param>
public void StartUpdateProcess(bool launchCKANAfterUpdate)
public void StartUpdateProcess(bool launchCKANAfterUpdate, IUser user = null)
{
if (!IsFetched())
{
Expand All @@ -122,31 +122,24 @@ public void StartUpdateProcess(bool launchCKANAfterUpdate)

var pid = Process.GetCurrentProcess().Id;

// download updater app
// download updater app and new ckan.exe
string updaterFilename = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".exe";

var web = new WebClient();
web.Headers.Add("user-agent", Net.UserAgentString);
web.DownloadFile(fetchedUpdaterUrl, updaterFilename);

// download new ckan.exe
string ckanFilename = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".exe";
web.DownloadFile(fetchedCkanUrl, ckanFilename);

var path = Assembly.GetEntryAssembly().Location;
Net.DownloadWithProgress(new[]{
new Net.DownloadTarget(fetchedUpdaterUrl.Item1, updaterFilename, fetchedUpdaterUrl.Item2),
new Net.DownloadTarget(fetchedCkanUrl.Item1, ckanFilename, fetchedCkanUrl.Item2),
}, user);

// run updater

SetExecutable(updaterFilename);

var args = String.Format("{0} \"{1}\" \"{2}\" {3}", pid, path, ckanFilename, launchCKANAfterUpdate ? "launch" : "nolaunch");

ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = updaterFilename;
processInfo.Arguments = args;
processInfo.UseShellExecute = false;
Process.Start(processInfo);
var path = Assembly.GetEntryAssembly().Location;
Process.Start(new ProcessStartInfo
{
Verb = "runas",
FileName = updaterFilename,
Arguments = String.Format(@"{0} ""{1}"" ""{2}"" {3}", pid, path, ckanFilename, launchCKANAfterUpdate ? "launch" : "nolaunch"),
UseShellExecute = false
});

// exit this ckan instance
Environment.Exit(0);
Expand All @@ -157,14 +150,15 @@ public void StartUpdateProcess(bool launchCKANAfterUpdate)
/// from the provided github API response
/// </summary>
/// <returns>The URL to the downloadable asset.</returns>
internal Uri RetrieveUrl(dynamic response)
{
internal Tuple<Uri, long> RetrieveUrl(dynamic response)
{
if (response.assets.Count == 0)
{
throw new Kraken("The latest release isn't uploaded yet.");
}
var assets = response.assets[0];
return new Uri(assets.browser_download_url.ToString());
var firstAsset = response.assets[0];
string url = firstAsset.browser_download_url.ToString();
return new Tuple<Uri, long>(new Uri(url), (long)firstAsset.size);
}

/// <summary>
Expand Down
48 changes: 48 additions & 0 deletions Core/Net/Net.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -108,6 +110,52 @@ public static string Download(string url, string filename = null, IUser user = n
return filename;
}

public class DownloadTarget
{
public Uri uri { get; private set; }
public string filename { get; private set; }
public long size { get; private set; }

public DownloadTarget(Uri uri, string filename = null, long size = 0)
{
if (filename == null)
{
filename = FileTransaction.GetTempFileName();
}

this.uri = uri;
this.filename = filename;
this.size = size;
}
}

public static string DownloadWithProgress(string url, string filename = null, IUser user = null)
{
return DownloadWithProgress(new Uri(url), filename, user);
}

public static string DownloadWithProgress(Uri url, string filename = null, IUser user = null)
{
var targets = new[] {new DownloadTarget(url, filename)};
DownloadWithProgress(targets, user);
return targets.First().filename;
}

public static void DownloadWithProgress(ICollection<DownloadTarget> downloadTargets, IUser user = null)
{
new NetAsyncDownloader(user ?? new NullUser())
{
onCompleted = (urls, filenames, errors) =>
{
if (filenames == null || urls == null) return;
for (var i = 0; i < Math.Min(urls.Length, filenames.Length); i++)
{
File.Move(filenames[i], downloadTargets.First(p => p.uri == urls[i]).filename);
}
}
}.DownloadAndWait(downloadTargets.ToDictionary(p => p.uri, p => p.size));
}

public static string DownloadText(Uri url)
{
return DownloadText(url.OriginalString);
Expand Down
Loading

0 comments on commit 5428e94

Please sign in to comment.