fix: 修复无法计算文件大小的问题
This commit is contained in:
parent
8a2a7d15e2
commit
d9fec8e595
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -955,6 +955,9 @@ namespace Flawless.Client.Remote
|
||||
|
||||
[JsonPropertyName("workPath")]
|
||||
public string WorkPath { get; set; }
|
||||
|
||||
[JsonPropertyName("size")]
|
||||
public long Size { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -32,6 +32,8 @@ public partial class LocalChangesNode : ReactiveModel
|
||||
[Reactive] private DateTime? _modifiedTime;
|
||||
|
||||
[Reactive] private LocalChangesNode? _parent;
|
||||
|
||||
[Reactive] private long _size;
|
||||
|
||||
public bool Included
|
||||
{
|
||||
@ -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),
|
||||
@ -232,13 +236,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);
|
||||
|
||||
@ -76,6 +76,14 @@ public partial class SettingViewModel : RoutableViewModelBase
|
||||
{
|
||||
UIHelper.NotifyError(ex);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UIHelper.NotifyError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadClientSettings()
|
||||
|
||||
@ -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}"/>
|
||||
|
||||
@ -6,11 +6,14 @@ public struct WorkspaceFile : IEquatable<WorkspaceFile>
|
||||
public DateTime ModifyTime { get; set; }
|
||||
|
||||
public string WorkPath { get; set; }
|
||||
|
||||
public ulong Size { get; set; }
|
||||
|
||||
public WorkspaceFile(DateTime modifyTime, string workPath)
|
||||
public WorkspaceFile(DateTime modifyTime, string workPath, long size)
|
||||
{
|
||||
ModifyTime = modifyTime;
|
||||
WorkPath = workPath;
|
||||
Size = (ulong) size;
|
||||
}
|
||||
|
||||
public bool Equals(WorkspaceFile other)
|
||||
|
||||
@ -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)
|
||||
@ -510,6 +510,14 @@ public class RepositoryInnieController(
|
||||
depotLabels.AddRange(mainDepot.Dependencies.Select(d => new DepotLabel(d.DepotId, d.Length)));
|
||||
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user