Skip to content

Commit

Permalink
Merge #3308 Multi-game fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Mar 5, 2021
2 parents 491e042 + 4531b91 commit 19f8b44
Show file tree
Hide file tree
Showing 22 changed files with 208 additions and 148 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ All notable changes to this project will be documented in this file.
### Features

- [Multiple] Store remote version file URL in metadata resources (#3259 by: HebaruSan; reviewed: DasSkelett)
- [Multiple] Abstract out game-specific logic (#3223 by: HebaruSan; reviewed: DasSkelett)
- [Multiple] Abstract out game-specific logic (#3223, #3308 by: HebaruSan; reviewed: DasSkelett)
- [GUI] Allow label to pin installed mod version (#3220 by: HebaruSan; reviewed: DasSkelett)
- [GUI] language: fr-FR (#3272, #3285 by: vinix38; reviewed: HebaruSan)
- [ConsoleUI] Dark theme for ConsoleUI (#3226 by: HebaruSan; reviewed: DasSkelett)
Expand Down
72 changes: 38 additions & 34 deletions Core/GameInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,44 +325,48 @@ public GameVersionCriteria VersionCriteria()
/// </returns>
public bool Scan()
{
var manager = RegistryManager.Instance(this);
using (TransactionScope tx = CkanTransaction.CreateTransactionScope())
if (Directory.Exists(game.PrimaryModDirectory(this)))
{
var oldDlls = new HashSet<string>(manager.registry.InstalledDlls);
manager.registry.ClearDlls();

// TODO: It would be great to optimise this to skip .git directories and the like.
// Yes, I keep my GameData in git.

// Alas, EnumerateFiles is *case-sensitive* in its pattern, which causes
// DLL files to be missed under Linux; we have to pick .dll, .DLL, or scanning
// GameData *twice*.
//
// The least evil is to walk it once, and filter it ourselves.
IEnumerable<string> files = Directory
.EnumerateFiles(game.PrimaryModDirectory(this), "*", SearchOption.AllDirectories)
.Where(file => file.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase))
.Select(CKANPathUtils.NormalizePath)
.Where(absPath => !game.StockFolders.Any(f =>
ToRelativeGameDir(absPath).StartsWith($"{f}/")));

foreach (string dll in files)
var manager = RegistryManager.Instance(this);
using (TransactionScope tx = CkanTransaction.CreateTransactionScope())
{
manager.registry.RegisterDll(this, dll);
var oldDlls = new HashSet<string>(manager.registry.InstalledDlls);
manager.registry.ClearDlls();

// TODO: It would be great to optimise this to skip .git directories and the like.
// Yes, I keep my GameData in git.

// Alas, EnumerateFiles is *case-sensitive* in its pattern, which causes
// DLL files to be missed under Linux; we have to pick .dll, .DLL, or scanning
// GameData *twice*.
//
// The least evil is to walk it once, and filter it ourselves.
IEnumerable<string> files = Directory
.EnumerateFiles(game.PrimaryModDirectory(this), "*", SearchOption.AllDirectories)
.Where(file => file.EndsWith(".dll", StringComparison.CurrentCultureIgnoreCase))
.Select(CKANPathUtils.NormalizePath)
.Where(absPath => !game.StockFolders.Any(f =>
ToRelativeGameDir(absPath).StartsWith($"{f}/")));

foreach (string dll in files)
{
manager.registry.RegisterDll(this, dll);
}
var newDlls = new HashSet<string>(manager.registry.InstalledDlls);
bool dllChanged = !oldDlls.SetEquals(newDlls);
bool dlcChanged = manager.ScanDlc();

if (dllChanged || dlcChanged)
{
manager.Save(false);
}

tx.Complete();

return dllChanged || dlcChanged;
}
var newDlls = new HashSet<string>(manager.registry.InstalledDlls);
bool dllChanged = !oldDlls.SetEquals(newDlls);
bool dlcChanged = manager.ScanDlc();

if (dllChanged || dlcChanged)
{
manager.Save(false);
}

tx.Complete();

return dllChanged || dlcChanged;
}
return false;
}

#endregion
Expand Down
4 changes: 3 additions & 1 deletion Core/Games/IGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public interface IGame
// What do we contain?
string PrimaryModDirectoryRelative { get; }
string PrimaryModDirectory(GameInstance inst);
string[] StockFolders { get; }
string[] StockFolders { get; }
string[] ReservedPaths { get; }
string[] CreateableDirs { get; }
bool IsReservedDirectory(GameInstance inst, string path);
bool AllowInstallationIn(string name, out string path);
void RebuildSubdirectories(GameInstance inst);
Expand Down
10 changes: 10 additions & 0 deletions Core/Games/KerbalSpaceProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ public string PrimaryModDirectory(GameInstance inst)
"GameData/SquadExpansion"
};

public string[] ReservedPaths => new string[]
{
"GameData", "Ships", "Missions"
};

public string[] CreateableDirs => new string[]
{
"GameData", "Tutorial", "Scenarios", "Missions", "Ships/Script"
};

/// <summary>
/// Checks the path against a list of reserved game directories
/// </summary>
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
82 changes: 37 additions & 45 deletions Core/Net/Repo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ public static RepoUpdateResult UpdateAllRepositories(RegistryManager registry_ma
// Merge all the lists
allAvail.AddRange(avail);
repository.Value.last_server_etag = newETag;
user.RaiseMessage("Updated {0}", repository.Value.name);
user.RaiseMessage("Updated {0} ({1} modules)",
repository.Value.name, avail.Count);
}
++index;
}
Expand Down Expand Up @@ -98,6 +99,7 @@ public static RepoUpdateResult UpdateAllRepositories(RegistryManager registry_ma
else
{
// Return failure
user.RaiseMessage("No modules found!");
return RepoUpdateResult.Failed;
}
}
Expand Down Expand Up @@ -381,44 +383,34 @@ private static List<CkanModule> UpdateRegistryFromTarGz(string path, out SortedD
// Create a handle for the tar stream.
using (TarInputStream tarStream = new TarInputStream(gzipStream))
{
// Walk the archive, looking for .ckan files.
const string filter = @"\.ckan$";

while (true)
TarEntry entry;
while ((entry = tarStream.GetNextEntry()) != null)
{
TarEntry entry = tarStream.GetNextEntry();

// Check for EOF.
if (entry == null)
{
break;
}

string filename = entry.Name;

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

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

// Read each file into a buffer.
string metadata_json = tarStreamString(tarStream, entry);
// Read each file into a buffer.
string metadata_json = tarStreamString(tarStream, entry);

CkanModule module = ProcessRegistryMetadataFromJSON(metadata_json, filename);
if (module != null)
CkanModule module = ProcessRegistryMetadataFromJSON(metadata_json, filename);
if (module != null)
{
modules.Add(module);
}
}
else
{
modules.Add(module);
// Skip things we don't want.
log.DebugFormat("Skipping archive entry {0}", filename);
}
}
}
Expand Down Expand Up @@ -460,35 +452,35 @@ private static List<CkanModule> UpdateRegistryFromZip(string path)
List<CkanModule> modules = new List<CkanModule>();
using (var zipfile = new ZipFile(path))
{
// Walk the archive, looking for .ckan files.
const string filter = @"\.ckan$";

foreach (ZipEntry entry in zipfile)
{
string filename = entry.Name;

// Skip things we don't want.
if (! Regex.IsMatch(filename, filter))
if (filename.EndsWith(".ckan"))
{
log.DebugFormat("Skipping archive entry {0}", filename);
continue;
}
log.DebugFormat("Reading CKAN data from {0}", filename);

log.DebugFormat("Reading CKAN data from {0}", filename);
// Read each file into a string.
string metadata_json;
using (var stream = new StreamReader(zipfile.GetInputStream(entry)))
{
metadata_json = stream.ReadToEnd();
stream.Close();
}

// Read each file into a string.
string metadata_json;
using (var stream = new StreamReader(zipfile.GetInputStream(entry)))
{
metadata_json = stream.ReadToEnd();
stream.Close();
CkanModule module = ProcessRegistryMetadataFromJSON(metadata_json, filename);
if (module != null)
{
modules.Add(module);
}
}

CkanModule module = ProcessRegistryMetadataFromJSON(metadata_json, filename);
if (module != null)
else
{
modules.Add(module);
// Skip things we don't want.
log.DebugFormat("Skipping archive entry {0}", filename);
continue;
}

}

zipfile.Close();
Expand Down
24 changes: 12 additions & 12 deletions Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -881,18 +881,18 @@ public void RegisterDlc(string identifier, UnmanagedModuleVersion version)
if (dlcModule == null)
{
// Don't have the real thing, make a fake one
dlcModule = new CkanModule()
{
spec_version = new ModuleVersion("v1.28"),
identifier = identifier,
name = identifier,
@abstract = "An official expansion pack for KSP",
author = new List<string>() { "SQUAD" },
version = version,
kind = "dlc",
license = new List<License>() { new License("restricted") },
};
dlcModule.CalculateSearchables();
dlcModule = new CkanModule(
new ModuleVersion("v1.28"),
identifier,
identifier,
"An official expansion pack for KSP",
null,
new List<string>() { "SQUAD" },
new List<License>() { new License("restricted") },
version,
null,
"dlc"
);
}
installed_modules.Add(
identifier,
Expand Down
25 changes: 14 additions & 11 deletions Core/Registry/RegistryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -314,14 +314,14 @@ private void LoadOrCreate()
log.ErrorFormat("Uncaught exception loading registry: {0}", ex.ToString());
throw;
}

AscertainDefaultRepo();
}

private void Create()
{
log.InfoFormat("Creating new CKAN registry at {0}", path);
registry = Registry.Empty();
AscertainDefaultRepo();
Save();
}

Expand Down Expand Up @@ -435,17 +435,20 @@ public CkanModule GenerateModpack(bool recommends = false, bool with_versions =
{
string kspInstanceName = ksp.Name;
string name = $"installed-{kspInstanceName}";
var module = new CkanModule()
{
var module = new CkanModule(
// v1.18 to allow Unlicense
spec_version = new ModuleVersion("v1.18"),
identifier = Identifier.Sanitize(name),
name = name,
author = new List<string>() { System.Environment.UserName },
@abstract = $"A list of modules installed on the {kspInstanceName} KSP instance",
kind = "metapackage",
version = new ModuleVersion(DateTime.UtcNow.ToString("yyyy.MM.dd.hh.mm.ss")),
license = new List<License>() { new License("unknown") },
new ModuleVersion("v1.18"),
Identifier.Sanitize(name),
name,
$"A list of modules installed on the {kspInstanceName} KSP instance",
null,
new List<string>() { System.Environment.UserName },
new List<License>() { new License("unknown") },
new ModuleVersion(DateTime.UtcNow.ToString("yyyy.MM.dd.hh.mm.ss")),
null,
"metapackage"
)
{
download_content_type = "application/zip",
release_date = DateTime.Now,
};
Expand Down
Loading

0 comments on commit 19f8b44

Please sign in to comment.