Skip to content

Commit

Permalink
Support reading BuildIDs
Browse files Browse the repository at this point in the history
  • Loading branch information
dbent committed May 6, 2016
1 parent 0a656fe commit 9052adf
Show file tree
Hide file tree
Showing 46 changed files with 2,013 additions and 607 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
build/
/.vs/
packages/
CKAN/*/bin
CKAN/*/obj
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file.

### Internal

- [Core] CKAN will now read BuildID.txt for more accurate KSP versions (#1645 by: dbent)
- [Multiple] Removed various references and code for processing mods on KerbalStuff. Thank you, Sircmpwn, for providing us with such a great service for so long. (#1615 by: Olympic1; reviewed: pjf)
- [Spec] Updated Spec with the `kind` field which was introduced in v1.6. (#1597 by: plague006; reviewed: Daz)
- [spec] ckan.schema now enforces structure of install directives (#1578 by: Zane6888; reviewed: pjf, Daz)
Expand Down
18 changes: 13 additions & 5 deletions Core/CKAN-core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<OutputPath>bin\Debug</OutputPath>
<WarningLevel>4</WarningLevel>
<DebugSymbols>true</DebugSymbols>
<LangVersion>5</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="CommandLine">
Expand Down Expand Up @@ -50,6 +51,11 @@
<Compile Include="Exporters\IExporter.cs" />
<Compile Include="Exporters\MarkdownExporter.cs" />
<Compile Include="Exporters\PlainTextExporter.cs" />
<Compile Include="GameVersionProviders\IKspBuildMap.cs" />
<Compile Include="GameVersionProviders\KspBuildIdVersionProvider.cs" />
<Compile Include="GameVersionProviders\KspVersionSource.cs" />
<Compile Include="GameVersionProviders\IGameVersionProvider.cs" />
<Compile Include="GameVersionProviders\KspBuildMap.cs" />
<Compile Include="Net\AutoUpdate.cs" />
<Compile Include="Net\IDownloader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand All @@ -61,7 +67,6 @@
<Compile Include="Types\ExportFileType.cs" />
<Compile Include="User.cs" />
<Compile Include="Types\Version.cs" />
<Compile Include="Types\KSPVersion.cs" />
<Compile Include="Meta.cs" />
<Compile Include="Types\Kraken.cs" />
<Compile Include="KSPManager.cs" />
Expand All @@ -83,6 +88,10 @@
<Compile Include="Converters\JsonSingleOrArrayConverter.cs" />
<Compile Include="Types\License.cs" />
<Compile Include="Types\ReleaseStatus.cs" />
<Compile Include="GameVersionProviders\KspReadmeVersionProvider.cs" />
<Compile Include="Versioning\KspVersion.cs" />
<Compile Include="Versioning\KspVersionBound.cs" />
<Compile Include="Versioning\KspVersionRange.cs" />
<Compile Include="Win32Registry.cs" />
<Compile Include="Types\FileType.cs" />
<Compile Include="FileIdentifier.cs" />
Expand All @@ -99,10 +108,9 @@
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<None Include="packages.config" />
<EmbeddedResource Include="builds.json" />
</ItemGroup>
<ItemGroup />
<ItemGroup />
<ItemGroup>
<Folder Include="Types\GameComparator\" />
</ItemGroup>
</Project>
<ItemGroup />
</Project>
9 changes: 9 additions & 0 deletions Core/GameVersionProviders/IGameVersionProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using CKAN.Versioning;

namespace CKAN.GameVersionProviders
{
public interface IGameVersionProvider
{
bool TryGetVersion(string directory, out KspVersion result);
}
}
11 changes: 11 additions & 0 deletions Core/GameVersionProviders/IKspBuildMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using CKAN.Versioning;

namespace CKAN.GameVersionProviders
{
public interface IKspBuildMap
{
KspVersion this[string buildId] { get; }

void Refresh();
}
}
49 changes: 49 additions & 0 deletions Core/GameVersionProviders/KspBuildIdVersionProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using CKAN.Versioning;

namespace CKAN.GameVersionProviders
{
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class KspBuildIdVersionProvider : IGameVersionProvider
{
private static readonly Regex BuildIdPattern = new Regex(@"^build id\s+=\s+0*(?<buildid>\d+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled
);

private readonly IKspBuildMap _kspBuildMap;

public KspBuildIdVersionProvider(IKspBuildMap kspBuildMap)
{
_kspBuildMap = kspBuildMap;
}

public bool TryGetVersion(string directory, out KspVersion result)
{
var buildIdPath = Path.Combine(directory, "buildID.txt");

if (File.Exists(buildIdPath))
{
var match = File
.ReadAllLines(buildIdPath)
.Select(i => BuildIdPattern.Match(i))
.FirstOrDefault(i => i.Success);

if (match != null)
{
var version = _kspBuildMap[match.Groups["buildid"].Value];

if (version != null)
{
result = version;
return true;
}
}
}

result = default(KspVersion);
return false;
}
}
}
175 changes: 175 additions & 0 deletions Core/GameVersionProviders/KspBuildMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using CKAN.Versioning;
using log4net;
using Newtonsoft.Json;

namespace CKAN.GameVersionProviders
{
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class KspBuildMap : IKspBuildMap
{
// TODO: Need a way for the client to configure this
private static readonly Uri BuildMapUri =
new Uri("https://raw.githubusercontent.com/KSP-CKAN/CKAN-meta/master/builds.json");

// TODO: Get this through dependency injection
private readonly ILog _log = LogManager.GetLogger(typeof(KspBuildMap));

private readonly object _buildMapLock = new object();
private JBuilds _jBuilds;

private readonly IWin32Registry _registry;

public KspVersion this[string buildId]
{
get
{
EnsureBuildMap();

string version;
return _jBuilds.Builds.TryGetValue(buildId, out version) ? KspVersion.Parse(version) : null;
}
}

public KspBuildMap(IWin32Registry registry)
{
_registry = registry;
}

private void EnsureBuildMap()
{
if (ReferenceEquals(_jBuilds, null))
{
lock(_buildMapLock)
{
if (ReferenceEquals(_jBuilds, null))
{
Refresh(useCachedVersion: true);
}
}
}
}

public void Refresh()
{
Refresh(useCachedVersion: false);
}

private void Refresh(bool useCachedVersion)
{
if (useCachedVersion)
{
// Attempt to set the build map from the cached version in the registry
if (TrySetRegistryBuildMap()) return;

// Attempt to set the build map from the repository
if (TrySetRemoteBuildMap()) return;
}
else
{
// Attempt to set the build map from the repository
if (TrySetRemoteBuildMap()) return;

// Attempt to set the build map from the cached version in the registry
if (TrySetRegistryBuildMap()) return;
}

// If that fails attempt to set the build map from the embedded version
if (TrySetEmbeddedBuildMap()) return;

_log.Warn("Could not refresh the build map from any source");
}

private bool TrySetBuildMap(string buildMapJson)
{
try
{
_jBuilds = JsonConvert.DeserializeObject<JBuilds>(buildMapJson);
return true;
}
catch(Exception e)
{
_log.WarnFormat("Could not parse build map");
_log.DebugFormat("{0}\n{1}", buildMapJson, e);
return false;
}
}

private bool TrySetRemoteBuildMap()
{
try
{
var json = Net.DownloadText(BuildMapUri);

if (TrySetBuildMap(json))
{
_registry.SetKSPBuilds(json);
return true;
}
else
{
return false;
}
}
catch (Exception e)
{
_log.WarnFormat("Could not retrieve latest build map from: {0}", BuildMapUri);
_log.Debug(e);
return false;
}
}

private bool TrySetRegistryBuildMap()
{
try
{
var json = _registry.GetKSPBuilds();
return json != null && TrySetBuildMap(json);
}
catch(Exception e)
{
_log.WarnFormat("Could not retrieve build map from registry");
_log.Debug(e);
return false;
}
}

private bool TrySetEmbeddedBuildMap()
{
try
{
var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("CKAN.builds.json");

if (resourceStream != null)
{
using (var reader = new StreamReader(resourceStream))
{
TrySetBuildMap(reader.ReadToEnd());
return true;
}
}
else
{
return false;
}
}
catch(Exception e)
{
_log.WarnFormat("Could not retrieve build map from embedded resource");
_log.Debug(e);
return false;
}
}

// ReSharper disable once ClassNeverInstantiated.Local
private sealed class JBuilds
{
[JsonProperty("builds")]
// ReSharper disable once UnusedAutoPropertyAccessor.Local
public Dictionary<string, string> Builds { get; set; }
}
}
}
37 changes: 37 additions & 0 deletions Core/GameVersionProviders/KspReadmeVersionProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using CKAN.Versioning;

namespace CKAN.GameVersionProviders
{
// ReSharper disable once ClassNeverInstantiated.Global
public sealed class KspReadmeVersionProvider : IGameVersionProvider
{
private static readonly Regex VersionPattern = new Regex(@"^Version\s+(?<version>\d+\.\d+\.\d+)",
RegexOptions.IgnoreCase | RegexOptions.Compiled
);

public bool TryGetVersion(string directory, out KspVersion result)
{
var readmePath = Path.Combine(directory, "readme.txt");

if (File.Exists(readmePath))
{
var match = File
.ReadAllLines(readmePath)
.Select(i => VersionPattern.Match(i))
.FirstOrDefault(i => i.Success);

if (match != null)
{
result = KspVersion.Parse(match.Groups["version"].Value);
return true;
}
}

result = default(KspVersion);
return false;
}
}
}
8 changes: 8 additions & 0 deletions Core/GameVersionProviders/KspVersionSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace CKAN.GameVersionProviders
{
public enum KspVersionSource
{
BuildId = 1,
Readme = 2
}
}
Loading

0 comments on commit 9052adf

Please sign in to comment.