using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace SourceGit.Commands { public class Fetch : Command { public Fetch(string repo, string remote, bool prune, Action outputHandler) { _outputHandler = outputHandler; WorkingDirectory = repo; Context = repo; TraitErrorAsOutput = true; var sshKey = new Config(repo).Get($"remote.{remote}.sshkey"); if (!string.IsNullOrEmpty(sshKey)) { Args = $"-c core.sshCommand=\"ssh -i '{sshKey}'\" "; } else { Args = "-c credential.helper=manager "; } Args += "fetch --force --progress --verbose "; if (prune) Args += "--prune "; Args += remote; AutoFetch.MarkFetched(repo); } public Fetch(string repo, string remote, string localBranch, string remoteBranch, Action outputHandler) { _outputHandler = outputHandler; WorkingDirectory = repo; Context = repo; TraitErrorAsOutput = true; var sshKey = new Config(repo).Get($"remote.{remote}.sshkey"); if (!string.IsNullOrEmpty(sshKey)) { Args = $"-c core.sshCommand=\"ssh -i '{sshKey}'\" "; } else { Args = "-c credential.helper=manager "; } Args += $"fetch --progress --verbose {remote} {remoteBranch}:{localBranch}"; } protected override void OnReadline(string line) { _outputHandler?.Invoke(line); } private readonly Action _outputHandler; } public class AutoFetch { private const double INTERVAL = 10 * 60; public static bool IsEnabled { get; set; } = false; class Job { public Fetch Cmd = null; public DateTime NextRunTimepoint = DateTime.MinValue; } static AutoFetch() { Task.Run(() => { while (true) { if (!IsEnabled) { Thread.Sleep(10000); continue; } var now = DateTime.Now; var uptodate = new List(); lock (_lock) { foreach (var job in _jobs) { if (job.Value.NextRunTimepoint.Subtract(now).TotalSeconds <= 0) { uptodate.Add(job.Value); } } } foreach (var job in uptodate) { job.Cmd.Exec(); job.NextRunTimepoint = DateTime.Now.AddSeconds(INTERVAL); } Thread.Sleep(2000); } }); } public static void AddRepository(string repo) { var job = new Job { Cmd = new Fetch(repo, "--all", true, null) { RaiseError = false }, NextRunTimepoint = DateTime.Now.AddSeconds(INTERVAL), }; lock (_lock) { if (_jobs.ContainsKey(repo)) { _jobs[repo] = job; } else { _jobs.Add(repo, job); } } } public static void RemoveRepository(string repo) { lock (_lock) { _jobs.Remove(repo); } } public static void MarkFetched(string repo) { lock (_lock) { if (_jobs.TryGetValue(repo, out var value)) { value.NextRunTimepoint = DateTime.Now.AddSeconds(INTERVAL); } } } private static readonly Dictionary _jobs = new Dictionary(); private static readonly object _lock = new object(); } }