Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add download count column to GUI #2518

Merged
merged 1 commit into from
Oct 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 46 additions & 25 deletions Core/Net/Repo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.Zip;
using log4net;
using Newtonsoft.Json;

namespace CKAN
{
Expand All @@ -34,7 +35,9 @@ public static int UpdateAllRepositories(RegistryManager registry_manager, KSP ks
foreach (KeyValuePair<string, Repository> repository in sortedRepositories)
{
log.InfoFormat("About to update {0}", repository.Value.name);
List<CkanModule> avail = UpdateRegistry(repository.Value.uri, ksp, user);
SortedDictionary<string, int> downloadCounts;
List<CkanModule> avail = UpdateRegistry(repository.Value.uri, ksp, user, out downloadCounts);
registry_manager.registry.SetDownloadCounts(downloadCounts);
if (avail == null)
{
// Report failure if any repo fails, rather than losing half the list.
Expand Down Expand Up @@ -76,9 +79,10 @@ public static int UpdateAllRepositories(RegistryManager registry_manager, KSP ks
/// <summary>
/// Retrieve available modules from the URL given.
/// </summary>
private static List<CkanModule> UpdateRegistry(Uri repo, KSP ksp, IUser user)
private static List<CkanModule> UpdateRegistry(Uri repo, KSP ksp, IUser user, out SortedDictionary<string, int> downloadCounts)
{
TxFileManager file_transaction = new TxFileManager();
downloadCounts = null;

// Use this opportunity to also update the build mappings... kind of hacky
ServiceLocator.Container.Resolve<IKspBuildMap>().Refresh();
Expand All @@ -103,7 +107,7 @@ private static List<CkanModule> UpdateRegistry(Uri repo, KSP ksp, IUser user)
switch (type)
{
case FileType.TarGz:
newAvailable = UpdateRegistryFromTarGz(repo_file);
newAvailable = UpdateRegistryFromTarGz(repo_file, out downloadCounts);
break;
case FileType.Zip:
newAvailable = UpdateRegistryFromZip(repo_file);
Expand Down Expand Up @@ -387,7 +391,11 @@ public static int Update(RegistryManager registry_manager, KSP ksp, IUser user,
repo = CKAN.Repository.default_ckan_repo_uri;
}

List<CkanModule> newAvail = UpdateRegistry(repo, ksp, user);
SortedDictionary<string, int> downloadCounts;
List<CkanModule> newAvail = UpdateRegistry(repo, ksp, user, out downloadCounts);

registry_manager.registry.SetDownloadCounts(downloadCounts);

if (newAvail != null && newAvail.Count > 0)
{
registry_manager.registry.SetAllAvailable(newAvail);
Expand All @@ -404,10 +412,11 @@ public static int Update(RegistryManager registry_manager, KSP ksp, IUser user,
/// <summary>
/// Returns available modules from the supplied tar.gz file.
/// </summary>
private static List<CkanModule> UpdateRegistryFromTarGz(string path)
private static List<CkanModule> UpdateRegistryFromTarGz(string path, out SortedDictionary<string, int> downloadCounts)
{
log.DebugFormat("Starting registry update from tar.gz file: \"{0}\".", path);

downloadCounts = null;
List<CkanModule> modules = new List<CkanModule>();
// Open the gzip'ed file.
using (Stream inputStream = File.OpenRead(path))
Expand All @@ -433,34 +442,23 @@ private static List<CkanModule> UpdateRegistryFromTarGz(string path)

string filename = entry.Name;

// Skip things we don't want.
if (!Regex.IsMatch(filename, filter))
if (filename.EndsWith("download_counts.json"))
{
downloadCounts = JsonConvert.DeserializeObject<SortedDictionary<string, int>>(
tarStreamString(tarStream, entry)
);
}
else if (!Regex.IsMatch(filename, filter))
{
// Skip things we don't want.
log.DebugFormat("Skipping archive entry {0}", filename);
continue;
}

log.DebugFormat("Reading CKAN data from {0}", filename);

// Read each file into a buffer.
int buffer_size;

try
{
buffer_size = Convert.ToInt32(entry.Size);
}
catch (OverflowException)
{
log.ErrorFormat("Error processing {0}: Metadata size too large.", entry.Name);
continue;
}

byte[] buffer = new byte[buffer_size];

tarStream.Read(buffer, 0, buffer_size);

// Convert the buffer data to a string.
string metadata_json = Encoding.ASCII.GetString(buffer);
string metadata_json = tarStreamString(tarStream, entry);

CkanModule module = ProcessRegistryMetadataFromJSON(metadata_json, filename);
if (module != null)
Expand All @@ -474,6 +472,29 @@ private static List<CkanModule> UpdateRegistryFromTarGz(string path)
return modules;
}

private static string tarStreamString(TarInputStream stream, TarEntry entry)
{
// Read each file into a buffer.
int buffer_size;

try
{
buffer_size = Convert.ToInt32(entry.Size);
}
catch (OverflowException)
{
log.ErrorFormat("Error processing {0}: Metadata size too large.", entry.Name);
return null;
}

byte[] buffer = new byte[buffer_size];

stream.Read(buffer, 0, buffer_size);

// Convert the buffer data to a string.
return Encoding.ASCII.GetString(buffer);
}

/// <summary>
/// Returns available modules from the supplied zip file.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions Core/Registry/IRegistryQuerier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public interface IRegistryQuerier
IEnumerable<string> InstalledDlls { get; }
IDictionary<string, UnmanagedModuleVersion> InstalledDlc { get; }

int? DownloadCount(string identifier);

/// <summary>
/// Returns a simple array of all latest available modules for
/// the specified version of KSP.
Expand Down
23 changes: 23 additions & 0 deletions Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,29 @@ public class Registry : IEnlistmentNotification, IRegistryQuerier
[JsonProperty] private Dictionary<string, InstalledModule> installed_modules;
[JsonProperty] private Dictionary<string, string> installed_files; // filename => module

[JsonProperty] public readonly SortedDictionary<string, int> download_counts = new SortedDictionary<string, int>();

public int? DownloadCount(string identifier)
{
int count;
if (download_counts.TryGetValue(identifier, out count))
{
return count;
}
return null;
}

public void SetDownloadCounts(SortedDictionary<string, int> counts)
{
if (counts != null)
{
foreach (var kvp in counts)
{
download_counts[kvp.Key] = kvp.Value;
}
}
}

// Index of which mods provide what, format:
// providers[provided] = { provider1, provider2, ... }
// Built by BuildProvidesIndex, makes LatestAvailableWithProvides much faster.
Expand Down
2 changes: 2 additions & 0 deletions GUI/GUIMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public sealed class GUIMod
public DateTime? InstallDate { get; private set; }
public string LatestVersion { get; private set; }
public string DownloadSize { get; private set; }
public int? DownloadCount { get; private set; }
public bool IsCached { get; private set; }

// These indicate the maximum KSP version that the maximum available
Expand Down Expand Up @@ -127,6 +128,7 @@ public GUIMod(string identifier, IRegistryQuerier registry, KspVersionCriteria c
Identifier = identifier;
IsIncompatible = incompatible;
IsAutodetected = registry.IsAutodetected(identifier);
DownloadCount = registry.DownloadCount(identifier);

ModuleVersion latest_version = null;
try
Expand Down
11 changes: 11 additions & 0 deletions GUI/Main.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions GUI/MainModList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ private IEnumerable<DataGridViewRow> _SortRowsByColumn(IEnumerable<DataGridViewR
case 0: case 1: return Sort(rows, CheckboxSorter);
case 7: return Sort(rows, DownloadSizeSorter);
case 8: return Sort(rows, InstallDateSorter);
case 9: return Sort(rows, r => (r.Tag as GUIMod)?.DownloadCount ?? 0);
}
return Sort(rows, DefaultSorter);
}
Expand Down Expand Up @@ -766,12 +767,13 @@ private DataGridViewRow MakeRow(GUIMod mod, List<ModChange> changes, bool hideEp
: mod.LatestVersion)
};

var compat = new DataGridViewTextBoxCell() { Value = mod.KSPCompatibility };
var size = new DataGridViewTextBoxCell() { Value = mod.DownloadSize };
var installDate = new DataGridViewTextBoxCell() { Value = mod.InstallDate };
var desc = new DataGridViewTextBoxCell() { Value = mod.Abstract };
var compat = new DataGridViewTextBoxCell() { Value = mod.KSPCompatibility };
var size = new DataGridViewTextBoxCell() { Value = mod.DownloadSize };
var installDate = new DataGridViewTextBoxCell() { Value = mod.InstallDate };
var downloadCount = new DataGridViewTextBoxCell() { Value = mod.DownloadCount };
var desc = new DataGridViewTextBoxCell() { Value = mod.Abstract };

item.Cells.AddRange(selecting, updating, name, author, installVersion, latestVersion, compat, size, installDate, desc);
item.Cells.AddRange(selecting, updating, name, author, installVersion, latestVersion, compat, size, installDate, downloadCount, desc);

selecting.ReadOnly = selecting is DataGridViewTextBoxCell;
updating.ReadOnly = updating is DataGridViewTextBoxCell;
Expand Down