mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-22 04:34:59 +00:00
refactor<*>: rewrite all codes...
This commit is contained in:
parent
89ff8aa744
commit
30ab8ae954
342 changed files with 17208 additions and 19633 deletions
237
src/Models/Watcher.cs
Normal file
237
src/Models/Watcher.cs
Normal file
|
@ -0,0 +1,237 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace SourceGit.Models {
|
||||
|
||||
/// <summary>
|
||||
/// 文件系统更新监视
|
||||
/// </summary>
|
||||
public class Watcher {
|
||||
/// <summary>
|
||||
/// 打开仓库事件
|
||||
/// </summary>
|
||||
public static event Action<Repository> Opened;
|
||||
|
||||
/// <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>
|
||||
/// <param name="repo"></param>
|
||||
public static void Open(Repository repo) {
|
||||
if (all.ContainsKey(repo.Path)) return;
|
||||
|
||||
var watcher = new Watcher();
|
||||
watcher.Start(repo.Path, repo.GitDir);
|
||||
all.Add(repo.Path, watcher);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取得一个仓库的监视器
|
||||
/// </summary>
|
||||
/// <param name="repoPath"></param>
|
||||
/// <returns></returns>
|
||||
public static Watcher Get(string repoPath) {
|
||||
if (all.ContainsKey(repoPath)) return all[repoPath];
|
||||
return 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--;
|
||||
} else {
|
||||
watcher.lockCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 跳转到指定的提交
|
||||
/// </summary>
|
||||
/// <param name="commit"></param>
|
||||
public void NavigateTo(string commit) {
|
||||
Navigate?.Invoke(commit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制刷新
|
||||
/// </summary>
|
||||
public void Refresh() {
|
||||
updateWC = 1;
|
||||
updateBranch = 1;
|
||||
updateSubmodules = 1;
|
||||
updateStashes = 1;
|
||||
updateTags = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仅强制更新本地变化
|
||||
/// </summary>
|
||||
public void RefreshWC() {
|
||||
updateWC = 0;
|
||||
WorkingCopyChanged?.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;
|
||||
}
|
||||
|
||||
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.EndsWith("_HEAD", StringComparison.Ordinal) ||
|
||||
e.Name.StartsWith("refs\\heads\\", StringComparison.Ordinal) ||
|
||||
e.Name.StartsWith("refs\\remotes\\", StringComparison.Ordinal)) {
|
||||
updateBranch = DateTime.Now.AddSeconds(.5).ToFileTime();
|
||||
} else if (e.Name.StartsWith("objects\\") || e.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();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue