1
0

115 lines
3.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using Flawless.Abstraction;
using Flawless.Client.Models;
using Flawless.Core.Modal;
namespace Flawless.Client.Service;
public class LocalFileTreeAccessor
{
public enum ChangeType
{
Folder = 0,
Add,
Remove,
Modify
}
public struct ChangeRecord
{
public ChangeType Type { get; }
public WorkspaceFile File { get; }
public ChangeRecord(ChangeType type, WorkspaceFile file)
{
Type = type;
File = file;
}
}
private static readonly string[] IgnoredDirectories =
{
AppDefaultValues.RepoLocalStorageManagerFolder
};
private readonly RepositoryModel _repo;
private readonly string _rootDirectory;
private IReadOnlyDictionary<string, WorkspaceFile> _baseline;
private Dictionary<string, ChangeRecord> _changes = new();
private Dictionary<string, WorkspaceFile> _currentFiles = new();
private object _optLock = new();
public DateTime LastScanTimeUtc { get; private set; }
public string WorkingDirectory => _rootDirectory;
public IReadOnlyDictionary<string, WorkspaceFile> BaselineFiles => _baseline;
public IReadOnlyDictionary<string, ChangeRecord> Changes => _changes;
public IReadOnlyDictionary<string, WorkspaceFile> CurrentFiles => _currentFiles;
public LocalFileTreeAccessor(RepositoryModel repo, IEnumerable<WorkspaceFile> baselines)
{
_repo = repo;
_baseline = baselines.ToImmutableDictionary(b => b.WorkPath);
_rootDirectory = PathUtility.GetWorkspacePath(repo.OwnerName, repo.Name);
}
public void SetBaseline(IEnumerable<WorkspaceFile> baselines)
{
lock (_optLock)
{
_baseline = baselines.ToImmutableDictionary(b => b.WorkPath);
_changes.Clear();
RefreshInternal();
}
}
public void Refresh()
{
lock (_optLock)
{
_changes.Clear();
RefreshInternal();
}
}
private void RefreshInternal()
{
_currentFiles.Clear();
foreach (var f in Directory.GetFiles(_rootDirectory, "*", SearchOption.AllDirectories))
{
var workPath = WorkPath.FromPlatformPath(f, _rootDirectory);
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 });
}
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 news = _currentFiles.Values.Where(v => !_baseline.ContainsKey(v.WorkPath));
var removed = _baseline.Values.Where(v => !_currentFiles.ContainsKey(v.WorkPath));
foreach (var f in changes) _changes.Add(f.WorkPath, new ChangeRecord(ChangeType.Modify, f));
foreach (var f in news) _changes.Add(f.WorkPath, new ChangeRecord(ChangeType.Add, f));
foreach (var f in removed) _changes.Add(f.WorkPath, new ChangeRecord(ChangeType.Remove, f));
}
}