Skip to content

Commit d6d1b81

Browse files
committed
Merge #4462 Use temp dir in instance for mod file transactions
2 parents e545238 + b2d58dc commit d6d1b81

21 files changed

+114
-90
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file.
2626
- [ConsoleUI] Recommendations of full changeset in ConsoleUI (#4416 by: HebaruSan)
2727
- [GUI] Fix GUI exceptions for module not in available modules list (#4431 by: HebaruSan)
2828
- [Core] Don't clone with symlinks on Linux (#4441 by: HebaruSan)
29+
- [Core] Use temp dir in instance for mod file transactions (#4462 by: HebaruSan)
2930

3031
### Internal
3132

Core/CKAN-core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
5353
<PackageReference Include="Autofac" Version="4.9.4" />
5454
<PackageReference Include="SharpZipLib" Version="1.3.3" />
55-
<PackageReference Include="TxFileManager.NETStandard" Version="2.0.0" />
55+
<PackageReference Include="TxFileManager" Version="1.5.0.1" />
5656
<PackageReference Include="log4net" Version="2.0.15" />
5757
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
5858
<PackageReference Include="NJsonSchema" Version="10.9.0" />

Core/GameInstance.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using System.Diagnostics;
88
using System.Diagnostics.CodeAnalysis;
99

10-
using ChinhDo.Transactions.FileManager;
10+
using ChinhDo.Transactions;
1111
using log4net;
1212
using Newtonsoft.Json;
1313

@@ -73,7 +73,7 @@ private void SetupCkanDirectories()
7373
log.InfoFormat("Initialising {0}", CkanDir);
7474

7575
// TxFileManager knows if we are in a transaction
76-
TxFileManager txFileMgr = new TxFileManager();
76+
var txFileMgr = new TxFileManager(CkanDir);
7777

7878
if (!Directory.Exists(CkanDir))
7979
{

Core/GameInstanceManager.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.Diagnostics.CodeAnalysis;
77

88
using Autofac;
9-
using ChinhDo.Transactions.FileManager;
9+
using ChinhDo.Transactions;
1010
using log4net;
1111

1212
using CKAN.IO;
@@ -305,7 +305,7 @@ public void CloneInstance(GameInstance existingInstance,
305305
public GameInstance FakeInstance(IGame game, string newName, string newPath, GameVersion version,
306306
Dictionary<IDlcDetector, GameVersion>? dlcs = null)
307307
{
308-
TxFileManager fileMgr = new TxFileManager();
308+
var txFileMgr = new TxFileManager();
309309
using (TransactionScope transaction = CkanTransaction.CreateTransactionScope())
310310
{
311311
if (HasInstance(newName))
@@ -326,13 +326,13 @@ public GameInstance FakeInstance(IGame game, string newName, string newPath, Gam
326326
log.DebugFormat("Creating folder structure and text files at {0} for {1} version {2}", Path.GetFullPath(newPath), game.ShortName, version.ToString());
327327

328328
// Create a game root directory, containing a GameData folder, a buildID.txt/buildID64.txt and a readme.txt
329-
fileMgr.CreateDirectory(newPath);
330-
fileMgr.CreateDirectory(Path.Combine(newPath, game.PrimaryModDirectoryRelative));
329+
txFileMgr.CreateDirectory(newPath);
330+
txFileMgr.CreateDirectory(Path.Combine(newPath, game.PrimaryModDirectoryRelative));
331331
game.RebuildSubdirectories(newPath);
332332

333333
foreach (var anchor in game.InstanceAnchorFiles)
334334
{
335-
fileMgr.WriteAllText(Path.Combine(newPath, anchor),
335+
txFileMgr.WriteAllText(Path.Combine(newPath, anchor),
336336
version.WithoutBuild.ToString());
337337
}
338338

@@ -341,13 +341,13 @@ public GameInstance FakeInstance(IGame game, string newName, string newPath, Gam
341341
{
342342
foreach (var b in KspBuildIdVersionProvider.buildIDfilenames)
343343
{
344-
fileMgr.WriteAllText(Path.Combine(newPath, b),
344+
txFileMgr.WriteAllText(Path.Combine(newPath, b),
345345
string.Format("build id = {0}", version.Build));
346346
}
347347
}
348348

349349
// Create the readme.txt WITHOUT build number
350-
fileMgr.WriteAllText(Path.Combine(newPath, "readme.txt"),
350+
txFileMgr.WriteAllText(Path.Combine(newPath, "readme.txt"),
351351
string.Format("Version {0}",
352352
version.WithoutBuild.ToString()));
353353

@@ -367,8 +367,8 @@ public GameInstance FakeInstance(IGame game, string newName, string newPath, Gam
367367
}
368368

369369
string dlcDir = Path.Combine(newPath, dlcDetector.InstallPath());
370-
fileMgr.CreateDirectory(dlcDir);
371-
fileMgr.WriteAllText(
370+
txFileMgr.CreateDirectory(dlcDir);
371+
txFileMgr.WriteAllText(
372372
Path.Combine(dlcDir, "readme.txt"),
373373
string.Format("Version {0}", dlcVersion));
374374
}

Core/IO/DirectoryLink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using System.Text;
77
using Microsoft.Win32.SafeHandles;
88

9-
using ChinhDo.Transactions.FileManager;
9+
using ChinhDo.Transactions;
1010

1111
namespace CKAN.IO
1212
{

Core/IO/HardLink.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
99
using FileMode = System.IO.FileMode;
1010

11-
using ChinhDo.Transactions.FileManager;
11+
using ChinhDo.Transactions;
1212
using log4net;
1313

1414
namespace CKAN.IO
@@ -44,16 +44,16 @@ public static void Create(string target, string linkPath)
4444
/// </summary>
4545
/// <param name="target">The original file</param>
4646
/// <param name="linkPath">The place where we want to make a link or copy</param>
47-
/// <param name="file_transaction">Transaction in case we need to roll back</param>
47+
/// <param name="txFileMgr">Transaction in case we need to roll back</param>
4848
public static void CreateOrCopy(string target,
4949
string linkPath,
50-
TxFileManager file_transaction)
50+
TxFileManager txFileMgr)
5151
{
5252
log.DebugFormat("Creating hard link or copy from {0} to {1}...", target, linkPath);
5353
if (!CreateImpl(target, linkPath))
5454
{
5555
// If we can't create a hard link (e.g., if the paths are on separate volumes), copy instead
56-
file_transaction.Copy(target, linkPath, false);
56+
txFileMgr.Copy(target, linkPath, false);
5757
}
5858
}
5959

Core/IO/InstalledFilesDeduplicator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.Linq;
44
using System.IO;
55

6-
using ChinhDo.Transactions.FileManager;
6+
using ChinhDo.Transactions;
77
using log4net;
88

99
using CKAN.Versioning;
@@ -136,13 +136,13 @@ public void DeduplicateAll(IUser user)
136136
log.DebugFormat("Deduplicating all...");
137137
using (var tx = CkanTransaction.CreateTransactionScope())
138138
{
139-
var file_transaction = new TxFileManager();
139+
var txFileMgr = new TxFileManager();
140140
foreach (var grp in fileGroups)
141141
{
142142
var target = grp.First();
143143
foreach (var linkPath in grp.Skip(1))
144144
{
145-
file_transaction.Delete(linkPath);
145+
txFileMgr.Delete(linkPath);
146146
// If this fails (e.g., if the files are on different volumes), it throws,
147147
// the transaction is aborted, and all changes are reverted.
148148
HardLink.Create(target, linkPath);
@@ -183,19 +183,19 @@ public void DeduplicateAll(IUser user)
183183

184184
public static void CreateOrCopy(FileInfo target,
185185
string linkPath,
186-
TxFileManager file_transaction)
186+
TxFileManager txFileMgr)
187187
{
188188
if (target.Length >= MinDedupFileSize)
189189
{
190190
// If >=128KiB, try making a hard link, then fall back to copying if it fails
191191
log.DebugFormat("Creating a hard link from {0} to {1}...", target, linkPath);
192-
HardLink.CreateOrCopy(target.FullName, linkPath, file_transaction);
192+
HardLink.CreateOrCopy(target.FullName, linkPath, txFileMgr);
193193
}
194194
else
195195
{
196196
// If <128KiB, just copy the file
197197
log.DebugFormat("Copying from {0} to {1}...", target, linkPath);
198-
file_transaction.Copy(target.FullName, linkPath, false);
198+
txFileMgr.Copy(target.FullName, linkPath, false);
199199
}
200200
}
201201

Core/IO/ModuleInstaller.cs

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using ICSharpCode.SharpZipLib.Core;
88
using ICSharpCode.SharpZipLib.Zip;
99
using log4net;
10-
using ChinhDo.Transactions.FileManager;
10+
using ChinhDo.Transactions;
1111

1212
using CKAN.Extensions;
1313
using CKAN.Versioning;
@@ -32,12 +32,13 @@ public ModuleInstaller(GameInstance inst,
3232
IUser user,
3333
CancellationToken cancelToken = default)
3434
{
35-
User = user;
36-
this.cache = cache;
37-
this.config = config;
38-
instance = inst;
35+
log.DebugFormat("Creating ModuleInstaller for {0}", inst.GameDir);
36+
instance = inst;
37+
// Make a transaction file manager that uses a temp dir in the instance's CKAN dir
38+
this.cache = cache;
39+
this.config = config;
40+
User = user;
3941
this.cancelToken = cancelToken;
40-
log.DebugFormat("Creating ModuleInstaller for {0}", instance.GameDir);
4142
}
4243

4344
public IUser User { get; set; }
@@ -394,9 +395,9 @@ private List<string> InstallModule(CkanModule
394395
// Delete the manually installed DLL transaction-style because we believe we'll be replacing it
395396
var toDelete = instance.ToAbsoluteGameDir(dll);
396397
log.DebugFormat("Deleting manually installed DLL {0}", toDelete);
397-
TxFileManager file_transaction = new TxFileManager();
398-
file_transaction.Snapshot(toDelete);
399-
file_transaction.Delete(toDelete);
398+
var txFileMgr = new TxFileManager(instance.CkanDir);
399+
txFileMgr.Snapshot(toDelete);
400+
txFileMgr.Delete(toDelete);
400401
}
401402
}
402403

@@ -543,13 +544,13 @@ private static bool StreamsEqual(Stream s1, Stream s2)
543544
/// fails at a later stage.
544545
/// </summary>
545546
/// <param name="files">The files to overwrite</param>
546-
private static void DeleteConflictingFiles(IEnumerable<InstallableFile> files)
547+
private void DeleteConflictingFiles(IEnumerable<InstallableFile> files)
547548
{
548-
TxFileManager file_transaction = new TxFileManager();
549+
var txFileMgr = new TxFileManager(instance.CkanDir);
549550
foreach (InstallableFile file in files)
550551
{
551552
log.DebugFormat("Trying to delete {0}", file.destination);
552-
file_transaction.Delete(file.destination);
553+
txFileMgr.Delete(file.destination);
553554
}
554555
}
555556

@@ -695,6 +696,16 @@ public static List<InstallableFile> FindInstallableFiles(CkanModule module,
695696

696697
#endregion
697698

699+
private string? InstallFile(ZipFile zipfile,
700+
ZipEntry entry,
701+
string fullPath,
702+
bool makeDirs,
703+
string[] candidateDuplicates,
704+
IProgress<long>? progress)
705+
=> InstallFile(zipfile, entry, fullPath, makeDirs,
706+
new TxFileManager(instance.CkanDir),
707+
candidateDuplicates, progress);
708+
698709
/// <summary>
699710
/// Copy the entry from the opened zipfile to the path specified.
700711
/// </summary>
@@ -707,11 +718,10 @@ public static List<InstallableFile> FindInstallableFiles(CkanModule module,
707718
ZipEntry entry,
708719
string fullPath,
709720
bool makeDirs,
721+
IFileManager txFileMgr,
710722
string[] candidateDuplicates,
711723
IProgress<long>? progress)
712724
{
713-
var file_transaction = new TxFileManager();
714-
715725
if (entry.IsDirectory)
716726
{
717727
// Skip if we're not making directories for this install.
@@ -727,7 +737,7 @@ public static List<InstallableFile> FindInstallableFiles(CkanModule module,
727737
: fullPath;
728738

729739
log.DebugFormat("Making directory '{0}'", fullPath);
730-
file_transaction.CreateDirectory(fullPath);
740+
txFileMgr.CreateDirectory(fullPath);
731741
}
732742
else
733743
{
@@ -737,19 +747,19 @@ public static List<InstallableFile> FindInstallableFiles(CkanModule module,
737747
if (makeDirs && Path.GetDirectoryName(fullPath) is string d)
738748
{
739749
log.DebugFormat("Making parent directory '{0}'", d);
740-
file_transaction.CreateDirectory(d);
750+
txFileMgr.CreateDirectory(d);
741751
}
742752

743753
// We don't allow for the overwriting of files. See #208.
744-
if (file_transaction.FileExists(fullPath))
754+
if (txFileMgr.FileExists(fullPath))
745755
{
746756
throw new FileExistsKraken(fullPath);
747757
}
748758

749759
// Snapshot whatever was there before. If there's nothing, this will just
750760
// remove our file on rollback. We still need this even though we won't
751761
// overwite files, as it ensures deletion on rollback.
752-
file_transaction.Snapshot(fullPath);
762+
txFileMgr.Snapshot(fullPath);
753763

754764
// Try making hard links if already installed in another instance (faster, less space)
755765
foreach (var installedSource in candidateDuplicates)
@@ -918,7 +928,7 @@ private void Uninstall(string identifier,
918928
Registry registry,
919929
IProgress<long> progress)
920930
{
921-
var file_transaction = new TxFileManager();
931+
var txFileMgr = new TxFileManager(instance.CkanDir);
922932

923933
using (var transaction = CkanTransaction.CreateTransactionScope())
924934
{
@@ -972,7 +982,7 @@ private void Uninstall(string identifier,
972982
bytesDeleted += new FileInfo(absPath).Length;
973983
progress.Report(bytesDeleted);
974984
log.DebugFormat("Removing {0}", relPath);
975-
file_transaction.Delete(absPath);
985+
txFileMgr.Delete(absPath);
976986
}
977987
}
978988
catch (FileNotFoundException exc)
@@ -1044,7 +1054,7 @@ private void Uninstall(string identifier,
10441054
if (File.Exists(absPath))
10451055
{
10461056
log.DebugFormat("Attempting transaction deletion of file {0}", absPath);
1047-
file_transaction.Delete(absPath);
1057+
txFileMgr.Delete(absPath);
10481058
}
10491059
else if (Directory.Exists(absPath))
10501060
{
@@ -1063,7 +1073,7 @@ private void Uninstall(string identifier,
10631073

10641074
if (notRemovable.Length < 1)
10651075
{
1066-
// We *don't* use our file_transaction to delete files here, because
1076+
// We *don't* use our txFileMgr to delete files here, because
10671077
// it fails if the system's temp directory is on a different device
10681078
// to KSP. However we *can* safely delete it now we know it's empty,
10691079
// because the TxFileMgr *will* put it back if there's a file inside that

Core/Net/Net.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using System.Threading;
88

99
using Autofac;
10-
using ChinhDo.Transactions.FileManager;
10+
using ChinhDo.Transactions;
1111
using log4net;
1212

1313
using CKAN.Extensions;
@@ -66,10 +66,10 @@ public static string Download(Uri url,
6666
IUser? user = null)
6767
{
6868
user?.RaiseMessage(Properties.Resources.NetDownloading, url);
69-
var FileTransaction = new TxFileManager();
69+
var txFileMgr = new TxFileManager();
7070

7171
// Generate a temporary file if none is provided.
72-
filename ??= FileTransaction.GetTempFileName();
72+
filename ??= txFileMgr.CreateTempFileName();
7373

7474
log.DebugFormat("Downloading {0} to {1}", url, filename);
7575

@@ -118,7 +118,7 @@ public static string Download(Uri url,
118118
// Clean up our file, it's unlikely to be complete.
119119
// We do this even though we're using transactional files, as we may not be in a transaction.
120120
log.DebugFormat("Removing {0} after web error failure", filename);
121-
FileTransaction.Delete(filename);
121+
txFileMgr.Delete(filename);
122122
}
123123
catch
124124
{

0 commit comments

Comments
 (0)