76 lines
2.7 KiB
JavaScript
76 lines
2.7 KiB
JavaScript
'use strict';
|
|
|
|
class RepositoryMonitor {
|
|
constructor({ store, git, onChange, diagnostics = null }) {
|
|
this.store = store;
|
|
this.git = git;
|
|
this.onChange = onChange;
|
|
this.diagnostics = diagnostics;
|
|
this.paths = [];
|
|
this.fingerprints = new Map();
|
|
this.timer = null;
|
|
this.running = false;
|
|
this.paused = new Set();
|
|
}
|
|
|
|
setPaths(paths) {
|
|
this.paths = [...new Set((paths || []).filter(Boolean))];
|
|
for (const existing of [...this.fingerprints.keys()]) {
|
|
if (!this.paths.includes(existing)) this.fingerprints.delete(existing);
|
|
}
|
|
}
|
|
|
|
pause(localPath) { if (localPath) this.paused.add(localPath); }
|
|
resume(localPath) { if (localPath) this.paused.delete(localPath); }
|
|
|
|
restart() {
|
|
this.stop();
|
|
if (!this.store.data.preferences.autoRefresh) return;
|
|
const seconds = Math.min(Math.max(Number(this.store.data.preferences.repositoryPollSeconds) || 4, 2), 60);
|
|
this.timer = setInterval(() => this.tick().catch((error) => this.diagnostics?.warning('repository-monitor.tick.failed', error)), seconds * 1000);
|
|
this.timer.unref?.();
|
|
}
|
|
|
|
stop() {
|
|
if (this.timer) clearInterval(this.timer);
|
|
this.timer = null;
|
|
}
|
|
|
|
async tick() {
|
|
if (this.running || !this.paths.length) return;
|
|
this.running = true;
|
|
try {
|
|
const queue = [...this.paths];
|
|
const workers = Array.from({ length: Math.min(4, queue.length) }, async () => {
|
|
while (queue.length) {
|
|
const localPath = queue.shift();
|
|
if (this.paused.has(localPath)) continue;
|
|
try {
|
|
const status = await this.git.status(localPath);
|
|
const next = this.git.statusFingerprint(status);
|
|
const previous = this.fingerprints.get(localPath);
|
|
this.fingerprints.set(localPath, next);
|
|
if (previous && previous !== next) {
|
|
await this.diagnostics?.debug('repository-monitor.changed', { localPath, head: status.head, branch: status.branch?.head, counts: status.counts });
|
|
this.onChange?.({ localPath, status, reason: 'working-tree-changed' });
|
|
}
|
|
} catch (error) {
|
|
const next = `error:${error.message}`;
|
|
const previous = this.fingerprints.get(localPath);
|
|
this.fingerprints.set(localPath, next);
|
|
if (previous && previous !== next) {
|
|
await this.diagnostics?.warning('repository-monitor.unavailable', { localPath, message: error.message });
|
|
this.onChange?.({ localPath, error: error.message, reason: 'repository-unavailable' });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
await Promise.all(workers);
|
|
} finally {
|
|
this.running = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = { RepositoryMonitor };
|