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

Multi-game fixes #3308

Merged
merged 1 commit into from
Mar 5, 2021
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
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.
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