115 lines
3.4 KiB
C#
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));
|
|
}
|
|
} |