1
0

fix: 修复无法计算文件大小的问题

This commit is contained in:
Ca2didi 2025-05-19 01:16:56 +08:00
parent 8a2a7d15e2
commit d9fec8e595
10 changed files with 82 additions and 44 deletions

View File

@ -21,8 +21,9 @@ public static class PathUtility
=> Path.Combine(SettingService.C.AppSetting.RepositoryPath, login, owner, repo,
AppDefaultValues.RepoLocalStorageManagerFolder, AppDefaultValues.RepoLocalStorageDepotFolder);
public static string ConvertBytesToBestDisplay(ulong bytes)
public static string ConvertBytesToBestDisplay(long bytes)
{
if (bytes < 0) return string.Empty;
string[] units = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
int unitIndex = 0;
double size = bytes;

View File

@ -124,14 +124,16 @@ public class LocalFileTreeAccessor
if (!WorkPath.IsPathValid(workPath) || IgnoredDirectories.Any(d => workPath.StartsWith(d)))
continue;
var modifyTime = File.GetLastWriteTimeUtc(f);
_currentFiles.Add(workPath, new WorkspaceFile { WorkPath = workPath, ModifyTime = modifyTime });
var inf = new FileInfo(f);
_currentFiles.Add(workPath, new WorkspaceFile(inf.LastWriteTimeUtc, workPath, inf.Length));
}
LastScanTimeUtc = DateTime.UtcNow;
// Find those are changed
var changes = _currentFiles.Values.Where(v => _baseline.TryGetValue(v.WorkPath, out var fi) && fi.ModifyTime != v.ModifyTime);
var changes = _currentFiles.Values.Where(v =>
_baseline.TryGetValue(v.WorkPath, out var fi) &&
(fi.ModifyTime != v.ModifyTime || fi.Size != v.Size));
var news = _currentFiles.Values.Where(v => !_baseline.ContainsKey(v.WorkPath));
var removed = _baseline.Values.Where(v => !_currentFiles.ContainsKey(v.WorkPath));

View File

@ -956,6 +956,9 @@ namespace Flawless.Client.Remote
[JsonPropertyName("workPath")]
public string WorkPath { get; set; }
[JsonPropertyName("size")]
public long Size { get; set; }
}
[System.CodeDom.Compiler.GeneratedCode("NSwag", "14.3.0.0 (NJsonSchema v11.2.0.0 (Newtonsoft.Json v13.0.0.0))")]

View File

@ -156,7 +156,7 @@ public class RepositoryFileTreeAccessor : IDisposable, IAsyncDisposable, IEnumer
public IEnumerator<WorkspaceFile> GetEnumerator()
{
return _cached.Values
.Select(cv => new WorkspaceFile(cv.FileInfo.ModifyTime, cv.FileInfo.Path)).GetEnumerator();
.Select(cv => new WorkspaceFile(cv.FileInfo.ModifyTime, cv.FileInfo.Path, (long)cv.FileInfo.Size)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()

View File

@ -1177,7 +1177,7 @@ public class RepositoryService : BaseService<RepositoryService>
return new(
rsp.ManifestId,
rsp.Depot.Select(x => new DepotLabel(x.Id, x.Length)).ToArray(),
rsp.FilePaths.Select(x => new WorkspaceFile(x.ModifyTime.UtcDateTime, x.WorkPath)).ToArray());
rsp.FilePaths.Select(x => new WorkspaceFile(x.ModifyTime.UtcDateTime, x.WorkPath, x.Size)).ToArray());
}
catch (Exception e)
{
@ -1205,8 +1205,8 @@ public class RepositoryService : BaseService<RepositoryService>
return true;
}
public async ValueTask<CommitManifest?> CommitWorkspaceAsBaselineAsync
(RepositoryModel repo, IEnumerable<ChangeInfo> changes, string message)
public async ValueTask<CommitManifest?> CommitWorkspaceAsync
(RepositoryModel repo, IEnumerable<ChangeInfo> changes, string message, bool forceBaseline = false)
{
// Check if current version is the latest
var api = Api.C;
@ -1233,6 +1233,12 @@ public class RepositoryService : BaseService<RepositoryService>
return null;
}
// Decide create new depot, create full depot or create addon depot.
var changesSize = localDb.LocalAccessor.Changes.Values.Sum(x => (long) x.File.Size);
var hasAddOrModify = localDb.LocalAccessor.Changes.Any(x =>
x.Value.Type == ChangeInfoType.Add || x.Value.Type == ChangeInfoType.Modify);
// Generate depot
var tempDepotPath = await CreateDepotIntoTempFileAsync(repo, manifestList);
if (tempDepotPath == null) return null;

View File

@ -33,6 +33,8 @@ public partial class LocalChangesNode : ReactiveModel
[Reactive] private LocalChangesNode? _parent;
[Reactive] private long _size;
public bool Included
{
get
@ -59,7 +61,8 @@ public partial class LocalChangesNode : ReactiveModel
Type = "Folder",
FullPath = folderPath,
Contents = new(),
Parent = parent
Parent = parent,
Size = -1
};
}
@ -70,7 +73,8 @@ public partial class LocalChangesNode : ReactiveModel
Type = file.Type.ToString(),
FullPath = file.File.WorkPath,
ModifiedTime = file.File.ModifyTime,
Parent = parent
Parent = parent,
Size = (long) file.File.Size
};
}
}
@ -179,7 +183,7 @@ public partial class RepositoryViewModel : RoutableViewModelBase
new TextColumn<LocalChangesNode, string>(
"Size",
n => PathUtility.ConvertBytesToBestDisplay(GetFileSize(n))),
n => PathUtility.ConvertBytesToBestDisplay(n.Size)),
new TextColumn<LocalChangesNode, DateTime?>(
"ModifiedTime", n => n.ModifiedTime.HasValue ? n.ModifiedTime.Value.ToLocalTime() : null),
@ -221,9 +225,9 @@ public partial class RepositoryViewModel : RoutableViewModelBase
"File Type",
n => n.Contents != null ? "Folder" : Path.GetExtension(n.FullPath)),
new TextColumn<LocalChangesNode, ulong>(
new TextColumn<LocalChangesNode, string>(
"Size",
n => 0),
n => PathUtility.ConvertBytesToBestDisplay(n.Size)),
new TextColumn<LocalChangesNode, DateTime?>(
"ModifiedTime", n => n.ModifiedTime.HasValue ? n.ModifiedTime.Value.ToLocalTime() : null),
@ -233,13 +237,6 @@ public partial class RepositoryViewModel : RoutableViewModelBase
_ = StartupTasksAsync();
}
private ulong GetFileSize(LocalChangesNode node)
{
if (!File.Exists(node.FullPath)) return 0;
var path = Path.Combine(_wsRoot, node.FullPath);
return (ulong)new FileInfo(path).Length;
}
private async Task StartupTasksAsync()
{
@ -552,7 +549,7 @@ public partial class RepositoryViewModel : RoutableViewModelBase
}
using var l = UIHelper.MakeLoading("Committing changes...");
var manifest = await RepositoryService.C.CommitWorkspaceAsBaselineAsync(Repository, changes, LocalDatabase.CommitMessage!);
var manifest = await RepositoryService.C.CommitWorkspaceAsync(Repository, changes, LocalDatabase.CommitMessage!);
if (manifest == null) return;
LocalDatabase.LocalAccessor.SetBaseline(manifest.Value.FilePaths);

View File

@ -76,6 +76,14 @@ public partial class SettingViewModel : RoutableViewModelBase
{
UIHelper.NotifyError(ex);
}
try
{
}
catch (Exception ex)
{
UIHelper.NotifyError(ex);
}
}
private async Task LoadClientSettings()

View File

@ -42,16 +42,16 @@
<u:FormItem Label="Default Storage Location">
<u:PathPicker/>
</u:FormItem>
<u:FormGroup Header="Workspace Refresh">
<StackPanel Spacing="4">
<CheckBox Theme="{StaticResource CardCheckBox}" Content="Open Workspace"
IsChecked="{Binding SettingModel.RefreshWorkspaceOnOpen}"/>
<CheckBox Theme="{StaticResource CardCheckBox}" Content="Filesystem Changed"
IsChecked="{Binding SettingModel.RefreshWorkspaceOnFilesystemChanges}"/>
</StackPanel>
</u:FormGroup>
<!-- <u:FormGroup Header="Workspace Refresh"> -->
<!-- <StackPanel Spacing="4"> -->
<!-- <CheckBox Theme="{StaticResource CardCheckBox}" Content="Open Workspace" -->
<!-- IsChecked="{Binding SettingModel.RefreshWorkspaceOnOpen}"/> -->
<!-- <CheckBox Theme="{StaticResource CardCheckBox}" Content="Filesystem Changed" -->
<!-- IsChecked="{Binding SettingModel.RefreshWorkspaceOnFilesystemChanges}"/> -->
<!-- </StackPanel> -->
<!-- </u:FormGroup> -->
<u:FormGroup Header="Extern Tools">
<u:PathPicker u:FormItem.Label="Open Folder"/>
<!-- <u:PathPicker u:FormItem.Label="Open Folder"/> -->
<u:PathPicker u:FormItem.Label="Diff Tool"/>
</u:FormGroup>
<StackPanel Orientation="Horizontal" Spacing="4">
@ -84,11 +84,11 @@
<Grid RowDefinitions="Auto, *" Margin="10">
<StackPanel Orientation="Horizontal">
<Button Content="Refresh Users"
<Button Content="Refresh"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Command="{Binding CreateUserCommand}"/>
<Button Content="Add Users"
<Button Content="Add"
VerticalAlignment="Bottom"
HorizontalAlignment="Right"
Command="{Binding CreateUserCommand}"/>

View File

@ -7,10 +7,13 @@ public struct WorkspaceFile : IEquatable<WorkspaceFile>
public string WorkPath { get; set; }
public WorkspaceFile(DateTime modifyTime, string workPath)
public ulong Size { get; set; }
public WorkspaceFile(DateTime modifyTime, string workPath, long size)
{
ModifyTime = modifyTime;
WorkPath = workPath;
Size = (ulong) size;
}
public bool Equals(WorkspaceFile other)

View File

@ -410,11 +410,11 @@ public class RepositoryInnieController(
var dateTimeStr = s.Substring(0, idx);
var pathStr = s.Substring(idx + 1);
return new WorkspaceFile(DateTime.FromBinary(long.Parse(dateTimeStr)), pathStr);
return new WorkspaceFile(DateTime.FromBinary(long.Parse(dateTimeStr)), pathStr, 0);
}).ToArray();
var sizeMap = new Dictionary<WorkspaceFile, long>();
var test = new HashSet<WorkspaceFile>(actualFs);
var createNewDepot = false;
RepositoryDepot mainDepot;
List<DepotLabel> depotLabels = new();
@ -423,7 +423,7 @@ public class RepositoryInnieController(
{
// Use existed depots
var mainDepotId = Guid.Parse(req.MainDepotId!);
var preDepot = await StencilWorkspaceSnapshotViaDatabaseAsync(rp.Id, mainDepotId, test);
var preDepot = await StencilWorkspaceSnapshotViaDatabaseAsync(rp.Id, mainDepotId, test, sizeMap);
if (preDepot == null)
return BadRequest(new FailedResponse("Not a valid main depot!", "NoMainDepot"));
@ -448,7 +448,7 @@ public class RepositoryInnieController(
await req.Depot.CopyToAsync(cacheStream, HttpContext.RequestAborted);
// Look if main depot can do this...
await StencilWorkspaceSnapshotAsync(cacheStream, test);
await StencilWorkspaceSnapshotAsync(cacheStream, test, sizeMap);
// Oh no, will we need to load their parents?
var unresolvedCount = test.Count;
@ -457,7 +457,7 @@ public class RepositoryInnieController(
// Yes
foreach (var subDepot in req.RequiredDepots?.Select(Guid.Parse) ?? [])
{
await StencilWorkspaceSnapshotViaDatabaseAsync(rp.Id, subDepot, test);
await StencilWorkspaceSnapshotViaDatabaseAsync(rp.Id, subDepot, test, sizeMap);
var rest = test.Count;
if (rest == 0)
@ -511,6 +511,14 @@ public class RepositoryInnieController(
}
// Update size info of FilePaths
for (var i = 0; i < actualFs.Length; i++)
{
var ws = actualFs[i];
ws.Size = (ulong)sizeMap.GetValueOrDefault(ws, 0);
actualFs[i] = ws;
}
// Create commit info
var commit = new RepositoryCommit
{
@ -549,7 +557,8 @@ public class RepositoryInnieController(
return Ok(new CommitSuccessResponse(commit.CommittedOn, commit.Id, mainDepot.DepotId));
}
private static async ValueTask StencilWorkspaceSnapshotAsync(Stream depotStream, HashSet<WorkspaceFile> unresolved)
private static async ValueTask StencilWorkspaceSnapshotAsync(Stream depotStream,
HashSet<WorkspaceFile> unresolved, Dictionary<WorkspaceFile, long> sizeMap)
{
// Get version
depotStream.Seek(0, SeekOrigin.Begin); // Fix: Get an invalid version code due to offset is bad.
@ -568,14 +577,20 @@ public class RepositoryInnieController(
{
ModifyTime = inf.ModifyTime,
WorkPath = inf.Path,
Size = 0
};
if (!sizeMap.TryAdd(test, (long)inf.Size)) sizeMap[test] = (long)inf.Size;
unresolved.Remove(test);
if (unresolved.Count == 0) break; // Early quit to avoid extra performance loss.
}
}
private async Task<RepositoryDepot?> StencilWorkspaceSnapshotViaDatabaseAsync(Guid rpId, Guid depotId, HashSet<WorkspaceFile> unresolved)
private async Task<RepositoryDepot?> StencilWorkspaceSnapshotViaDatabaseAsync(
Guid rpId, Guid depotId,
HashSet<WorkspaceFile> unresolved,
Dictionary<WorkspaceFile, long> sizeMap)
{
var depot = await dbContext.Repositories
.SelectMany(r => r.Depots)
@ -583,20 +598,23 @@ public class RepositoryInnieController(
.ThenInclude(repositoryDepot => repositoryDepot.Dependencies)
.FirstOrDefaultAsync(r => r.DepotId == depotId);
await RecurringAsync(transformer, rpId, depot, unresolved);
await RecurringAsync(transformer, rpId, depot, unresolved, sizeMap);
return depot;
static async ValueTask RecurringAsync(PathTransformer transformer, Guid rpId, RepositoryDepot? depot, HashSet<WorkspaceFile> unresolved)
static async ValueTask RecurringAsync(
PathTransformer transformer, Guid rpId,
RepositoryDepot? depot, HashSet<WorkspaceFile> unresolved,
Dictionary<WorkspaceFile, long> sizeMap)
{
if (depot == null) return;
var path = transformer.GetDepotPath(rpId, depot.DepotId);
// require do not extend lifetime scope.
await using (var fs = new BufferedStream(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)))
await StencilWorkspaceSnapshotAsync(fs, unresolved);
await StencilWorkspaceSnapshotAsync(fs, unresolved, sizeMap);
for (var i = 0; i < depot.Dependencies.Count && unresolved.Count > 0; i++)
await RecurringAsync(transformer, rpId, depot.Dependencies[i], unresolved);
await RecurringAsync(transformer, rpId, depot.Dependencies[i], unresolved, sizeMap);
}
}