mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-22 04:34:59 +00:00
refactor<*>: rewrite all with AvaloniaUI
This commit is contained in:
parent
0136904612
commit
2a62596999
521 changed files with 19780 additions and 23244 deletions
|
@ -1,268 +1,167 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Models {
|
||||
public interface IRepository {
|
||||
string FullPath { get; set; }
|
||||
string GitDir { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 文件系统更新监视
|
||||
/// </summary>
|
||||
public class Watcher {
|
||||
/// <summary>
|
||||
/// 打开仓库事件
|
||||
/// </summary>
|
||||
public static event Action<Repository> Opened;
|
||||
void RefreshBranches();
|
||||
void RefreshTags();
|
||||
void RefreshCommits();
|
||||
void RefreshSubmodules();
|
||||
void RefreshWorkingCopyChanges();
|
||||
void RefreshStashes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仓库的显示名变化了
|
||||
/// </summary>
|
||||
public static event Action<string, string> DisplayNameChanged;
|
||||
public class Watcher : IDisposable {
|
||||
public Watcher(IRepository repo) {
|
||||
_repo = repo;
|
||||
|
||||
/// <summary>
|
||||
/// 仓库的书签变化了
|
||||
/// </summary>
|
||||
public static event Action<string, int> BookmarkChanged;
|
||||
_wcWatcher = new FileSystemWatcher();
|
||||
_wcWatcher.Path = _repo.FullPath;
|
||||
_wcWatcher.Filter = "*";
|
||||
_wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
|
||||
_wcWatcher.IncludeSubdirectories = true;
|
||||
_wcWatcher.Created += OnWorkingCopyChanged;
|
||||
_wcWatcher.Renamed += OnWorkingCopyChanged;
|
||||
_wcWatcher.Changed += OnWorkingCopyChanged;
|
||||
_wcWatcher.Deleted += OnWorkingCopyChanged;
|
||||
_wcWatcher.EnableRaisingEvents = true;
|
||||
|
||||
/// <summary>
|
||||
/// 跳转到指定提交的事件
|
||||
/// </summary>
|
||||
public event Action<string> Navigate;
|
||||
/// <summary>
|
||||
/// 工作副本变更
|
||||
/// </summary>
|
||||
public event Action WorkingCopyChanged;
|
||||
/// <summary>
|
||||
/// 分支数据变更
|
||||
/// </summary>
|
||||
public event Action BranchChanged;
|
||||
/// <summary>
|
||||
/// 标签变更
|
||||
/// </summary>
|
||||
public event Action TagChanged;
|
||||
/// <summary>
|
||||
/// 贮藏变更
|
||||
/// </summary>
|
||||
public event Action StashChanged;
|
||||
/// <summary>
|
||||
/// 子模块变更
|
||||
/// </summary>
|
||||
public event Action SubmoduleChanged;
|
||||
/// <summary>
|
||||
/// 树更新
|
||||
/// </summary>
|
||||
public event Action SubTreeChanged;
|
||||
_repoWatcher = new FileSystemWatcher();
|
||||
_repoWatcher.Path = _repo.GitDir;
|
||||
_repoWatcher.Filter = "*";
|
||||
_repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
|
||||
_repoWatcher.IncludeSubdirectories = true;
|
||||
_repoWatcher.Created += OnRepositoryChanged;
|
||||
_repoWatcher.Renamed += OnRepositoryChanged;
|
||||
_repoWatcher.Changed += OnRepositoryChanged;
|
||||
_repoWatcher.Deleted += OnRepositoryChanged;
|
||||
_repoWatcher.EnableRaisingEvents = true;
|
||||
|
||||
/// <summary>
|
||||
/// 打开仓库事件
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
public static void Open(Repository repo) {
|
||||
if (all.ContainsKey(repo.Path)) {
|
||||
Opened?.Invoke(repo);
|
||||
return;
|
||||
_timer = new Timer(Tick, null, 100, 100);
|
||||
}
|
||||
|
||||
public void SetEnabled(bool enabled) {
|
||||
if (enabled) {
|
||||
if (_lockCount > 0) _lockCount--;
|
||||
} else {
|
||||
_lockCount++;
|
||||
}
|
||||
|
||||
var watcher = new Watcher();
|
||||
watcher.Start(repo.Path, repo.GitDir);
|
||||
all.Add(repo.Path, watcher);
|
||||
repo.LastOpenTime = DateTime.Now.ToFileTime();
|
||||
|
||||
Opened?.Invoke(repo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止指定的监视器
|
||||
/// </summary>
|
||||
/// <param name="repoPath"></param>
|
||||
public static void Close(string repoPath) {
|
||||
if (!all.ContainsKey(repoPath)) return;
|
||||
all[repoPath].Stop();
|
||||
all.Remove(repoPath);
|
||||
public void MarkWorkingCopyRefreshed() {
|
||||
_updateWC = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取得一个仓库的监视器
|
||||
/// </summary>
|
||||
/// <param name="repoPath"></param>
|
||||
/// <returns></returns>
|
||||
public static Watcher Get(string repoPath) {
|
||||
if (all.ContainsKey(repoPath)) return all[repoPath];
|
||||
return null;
|
||||
public void Dispose() {
|
||||
_repoWatcher.EnableRaisingEvents = false;
|
||||
_repoWatcher.Created -= OnRepositoryChanged;
|
||||
_repoWatcher.Renamed -= OnRepositoryChanged;
|
||||
_repoWatcher.Changed -= OnRepositoryChanged;
|
||||
_repoWatcher.Deleted -= OnRepositoryChanged;
|
||||
_repoWatcher.Dispose();
|
||||
_repoWatcher = null;
|
||||
|
||||
_wcWatcher.EnableRaisingEvents = false;
|
||||
_wcWatcher.Created -= OnWorkingCopyChanged;
|
||||
_wcWatcher.Renamed -= OnWorkingCopyChanged;
|
||||
_wcWatcher.Changed -= OnWorkingCopyChanged;
|
||||
_wcWatcher.Deleted -= OnWorkingCopyChanged;
|
||||
_wcWatcher.Dispose();
|
||||
_wcWatcher = null;
|
||||
|
||||
_timer.Dispose();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停或启用监听
|
||||
/// </summary>
|
||||
/// <param name="repoPath"></param>
|
||||
/// <param name="enabled"></param>
|
||||
public static void SetEnabled(string repoPath, bool enabled) {
|
||||
if (all.ContainsKey(repoPath)) {
|
||||
var watcher = all[repoPath];
|
||||
if (enabled) {
|
||||
if (watcher.lockCount > 0) watcher.lockCount--;
|
||||
private void Tick(object sender) {
|
||||
if (_lockCount > 0) return;
|
||||
|
||||
var now = DateTime.Now.ToFileTime();
|
||||
if (_updateBranch > 0 && now > _updateBranch) {
|
||||
_updateBranch = 0;
|
||||
_updateWC = 0;
|
||||
|
||||
if (_updateTags > 0) {
|
||||
_updateTags = 0;
|
||||
Task.Run(() => {
|
||||
_repo.RefreshTags();
|
||||
_repo.RefreshBranches();
|
||||
_repo.RefreshCommits();
|
||||
});
|
||||
} else {
|
||||
watcher.lockCount++;
|
||||
Task.Run(() => {
|
||||
_repo.RefreshBranches();
|
||||
_repo.RefreshCommits();
|
||||
});
|
||||
}
|
||||
|
||||
Task.Run(_repo.RefreshWorkingCopyChanges);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通知仓库显示名变化
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
public static void NotifyDisplayNameChanged(Repository repo) {
|
||||
DisplayNameChanged?.Invoke(repo.Path, repo.Name);
|
||||
}
|
||||
if (_updateWC > 0 && now > _updateWC) {
|
||||
_updateWC = 0;
|
||||
Task.Run(_repo.RefreshWorkingCopyChanges);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通知仓库标签变化
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
public static void NotifyBookmarkChanged(Repository repo) {
|
||||
BookmarkChanged?.Invoke(repo.Path, repo.Bookmark);
|
||||
}
|
||||
if (_updateSubmodules > 0 && now > _updateSubmodules) {
|
||||
_updateSubmodules = 0;
|
||||
_repo.RefreshSubmodules();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跳转到指定的提交
|
||||
/// </summary>
|
||||
/// <param name="commit"></param>
|
||||
public void NavigateTo(string commit) {
|
||||
Navigate?.Invoke(commit);
|
||||
}
|
||||
if (_updateStashes > 0 && now > _updateStashes) {
|
||||
_updateStashes = 0;
|
||||
_repo.RefreshStashes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅强制更新本地变化
|
||||
/// </summary>
|
||||
public void RefreshWC() {
|
||||
updateWC = 0;
|
||||
WorkingCopyChanged?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通知更新子树列表
|
||||
/// </summary>
|
||||
public void RefreshSubTrees() {
|
||||
SubTreeChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void Start(string repo, string gitDir) {
|
||||
wcWatcher = new FileSystemWatcher();
|
||||
wcWatcher.Path = repo;
|
||||
wcWatcher.Filter = "*";
|
||||
wcWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.CreationTime;
|
||||
wcWatcher.IncludeSubdirectories = true;
|
||||
wcWatcher.Created += OnWorkingCopyChanged;
|
||||
wcWatcher.Renamed += OnWorkingCopyChanged;
|
||||
wcWatcher.Changed += OnWorkingCopyChanged;
|
||||
wcWatcher.Deleted += OnWorkingCopyChanged;
|
||||
wcWatcher.EnableRaisingEvents = true;
|
||||
|
||||
repoWatcher = new FileSystemWatcher();
|
||||
repoWatcher.Path = gitDir;
|
||||
repoWatcher.Filter = "*";
|
||||
repoWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
|
||||
repoWatcher.IncludeSubdirectories = true;
|
||||
repoWatcher.Created += OnRepositoryChanged;
|
||||
repoWatcher.Renamed += OnRepositoryChanged;
|
||||
repoWatcher.Changed += OnRepositoryChanged;
|
||||
repoWatcher.Deleted += OnRepositoryChanged;
|
||||
repoWatcher.EnableRaisingEvents = true;
|
||||
|
||||
timer = new Timer(Tick, null, 100, 100);
|
||||
}
|
||||
|
||||
private void Stop() {
|
||||
repoWatcher.EnableRaisingEvents = false;
|
||||
repoWatcher.Dispose();
|
||||
repoWatcher = null;
|
||||
|
||||
wcWatcher.EnableRaisingEvents = false;
|
||||
wcWatcher.Dispose();
|
||||
wcWatcher = null;
|
||||
|
||||
timer.Dispose();
|
||||
timer = null;
|
||||
|
||||
Navigate = null;
|
||||
WorkingCopyChanged = null;
|
||||
BranchChanged = null;
|
||||
TagChanged = null;
|
||||
StashChanged = null;
|
||||
SubmoduleChanged = null;
|
||||
SubTreeChanged = null;
|
||||
if (_updateTags > 0 && now > _updateTags) {
|
||||
_updateTags = 0;
|
||||
_repo.RefreshTags();
|
||||
_repo.RefreshCommits();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRepositoryChanged(object o, FileSystemEventArgs e) {
|
||||
if (string.IsNullOrEmpty(e.Name)) return;
|
||||
|
||||
if (e.Name.StartsWith("modules", StringComparison.Ordinal)) {
|
||||
updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
|
||||
} else if (e.Name.StartsWith("refs\\tags", StringComparison.Ordinal)) {
|
||||
updateTags = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (e.Name.StartsWith("refs\\stash", StringComparison.Ordinal)) {
|
||||
updateStashes = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (e.Name.Equals("HEAD", StringComparison.Ordinal) ||
|
||||
e.Name.StartsWith("refs\\heads\\", StringComparison.Ordinal) ||
|
||||
e.Name.StartsWith("refs\\remotes\\", StringComparison.Ordinal) ||
|
||||
e.Name.StartsWith("worktrees\\")) {
|
||||
updateBranch = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (e.Name.StartsWith("objects\\", StringComparison.Ordinal) || e.Name.Equals("index", StringComparison.Ordinal)) {
|
||||
updateWC = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
var name = e.Name.Replace("\\", "/");
|
||||
if (name.StartsWith("modules", StringComparison.Ordinal)) {
|
||||
_updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime();
|
||||
} else if (name.StartsWith("refs/tags", StringComparison.Ordinal)) {
|
||||
_updateTags = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (name.StartsWith("refs/stash", StringComparison.Ordinal)) {
|
||||
_updateStashes = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (name.Equals("HEAD", StringComparison.Ordinal) ||
|
||||
name.StartsWith("refs/heads/", StringComparison.Ordinal) ||
|
||||
name.StartsWith("refs/remotes/", StringComparison.Ordinal) ||
|
||||
name.StartsWith("worktrees/")) {
|
||||
_updateBranch = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (name.StartsWith("objects/", StringComparison.Ordinal) || name.Equals("index", StringComparison.Ordinal)) {
|
||||
_updateWC = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWorkingCopyChanged(object o, FileSystemEventArgs e) {
|
||||
if (string.IsNullOrEmpty(e.Name)) return;
|
||||
if (e.Name == ".git" || e.Name.StartsWith(".git\\", StringComparison.Ordinal)) return;
|
||||
|
||||
updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
|
||||
var name = e.Name.Replace("\\", "/");
|
||||
if (name == ".git" || name.StartsWith(".git/", StringComparison.Ordinal)) return;
|
||||
if (_updateWC == 0) _updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
|
||||
}
|
||||
|
||||
private void Tick(object sender) {
|
||||
if (lockCount > 0) return;
|
||||
|
||||
var now = DateTime.Now.ToFileTime();
|
||||
if (updateBranch > 0 && now > updateBranch) {
|
||||
BranchChanged?.Invoke();
|
||||
WorkingCopyChanged?.Invoke();
|
||||
updateBranch = 0;
|
||||
updateWC = 0;
|
||||
}
|
||||
|
||||
if (updateWC > 0 && now > updateWC) {
|
||||
WorkingCopyChanged?.Invoke();
|
||||
updateWC = 0;
|
||||
}
|
||||
|
||||
if (updateSubmodules > 0 && now > updateSubmodules) {
|
||||
SubmoduleChanged?.Invoke();
|
||||
updateSubmodules = 0;
|
||||
}
|
||||
|
||||
if (updateStashes > 0 && now > updateStashes) {
|
||||
StashChanged?.Invoke();
|
||||
updateStashes = 0;
|
||||
}
|
||||
|
||||
if (updateTags > 0 && now > updateTags) {
|
||||
TagChanged?.Invoke();
|
||||
updateTags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#region PRIVATES
|
||||
private static Dictionary<string, Watcher> all = new Dictionary<string, Watcher>();
|
||||
|
||||
private FileSystemWatcher repoWatcher = null;
|
||||
private FileSystemWatcher wcWatcher = null;
|
||||
private Timer timer = null;
|
||||
private int lockCount = 0;
|
||||
private long updateWC = 0;
|
||||
private long updateBranch = 0;
|
||||
private long updateSubmodules = 0;
|
||||
private long updateStashes = 0;
|
||||
private long updateTags = 0;
|
||||
#endregion
|
||||
private IRepository _repo = null;
|
||||
private FileSystemWatcher _repoWatcher = null;
|
||||
private FileSystemWatcher _wcWatcher = null;
|
||||
private Timer _timer = null;
|
||||
private int _lockCount = 0;
|
||||
private long _updateWC = 0;
|
||||
private long _updateBranch = 0;
|
||||
private long _updateSubmodules = 0;
|
||||
private long _updateStashes = 0;
|
||||
private long _updateTags = 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue