Ignore watcher event if mtime doesn't changed (#3057)

This commit is contained in:
Felix Häusler 2022-02-22 21:44:56 +01:00 committed by GitHub
parent 6b394b4a9b
commit d95506751b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 38 additions and 20 deletions

View File

@ -39,5 +39,5 @@ You can report bugs and problems via our [GitHub issue tracker](https://github.c
Normally, you should never get this error but if you disabled user namespaces, this error message may appears in the command output when launching MarkText. To solve the issue, that Chromium cannot start the sandbox (process), you can choose one of the following steps:
- Enable Linux kernel user namespaces to use the preferred sandbox: `sudo sysctl kernel.unprivileged_userns_clone=1`.
- Set correct SUID sandbox helper binary permissions: `sudo chown root <path_to_marktext_dir>/chrome-sandbox && sudo chmod 4755 <path_to_marktext_dir>/chrome-sandbox`. This is prefered if you don't want to enable user namespaces.
- Set correct SUID sandbox helper binary permissions: `sudo chown root <path_to_marktext_dir>/chrome-sandbox && sudo chmod 4755 <path_to_marktext_dir>/chrome-sandbox`. This is preferred if you don't want to enable user namespaces.
- Launch MarkText with `--no-sandbox` argument.

View File

@ -29,7 +29,7 @@ On Red Hat-based Linux: `sudo dnf install libX11-devel libxkbfile-devel libsecre
**Additional development dependencies on Windows:**
- Windows 10 SDK (only needed before Windows 10)
- Visual Studio 2019 (prefered)
- Visual Studio 2019 (preferred)
### Let's build

View File

@ -71,12 +71,12 @@ export const writeMarkdownFile = (pathname, content, options) => {
* Reads the contents of a markdown file.
*
* @param {string} pathname The path to the markdown file.
* @param {string} preferedEol The prefered EOL.
* @param {string} preferredEol The preferred EOL.
* @param {boolean} autoGuessEncoding Whether we should try to auto guess encoding.
* @param {*} trimTrailingNewline The trim trailing newline option.
* @returns {IMarkdownDocumentRaw} Returns a raw markdown document.
*/
export const loadMarkdownFile = async (pathname, preferedEol, autoGuessEncoding = true, trimTrailingNewline = 2) => {
export const loadMarkdownFile = async (pathname, preferredEol, autoGuessEncoding = true, trimTrailingNewline = 2) => {
// TODO: Use streams to not buffer the file multiple times and only guess
// encoding on the first 256/512 bytes.
@ -95,7 +95,7 @@ export const loadMarkdownFile = async (pathname, preferedEol, autoGuessEncoding
const isCrlf = CRLF_LINE_ENDING_REG.test(markdown)
const isMixedLineEndings = isLf && isCrlf
const isUnknownEnding = !isLf && !isCrlf
let lineEnding = preferedEol
let lineEnding = preferredEol
if (isLf && !isCrlf) {
lineEnding = 'lf'
} else if (isCrlf && !isLf) {

View File

@ -186,18 +186,18 @@ class Watcher {
let renameTimer = null
watcher
.on('add', pathname => {
if (!this._shouldIgnoreEvent(win.id, pathname, type)) {
.on('add', async pathname => {
if (!await this._shouldIgnoreEvent(win.id, pathname, type, usePolling)) {
const { _preferences } = this
const eol = _preferences.getPreferedEol()
const eol = _preferences.getPreferredEol()
const { autoGuessEncoding, trimTrailingNewline } = _preferences.getAll()
add(win, pathname, type, eol, autoGuessEncoding, trimTrailingNewline)
}
})
.on('change', pathname => {
if (!this._shouldIgnoreEvent(win.id, pathname, type)) {
.on('change', async pathname => {
if (!await this._shouldIgnoreEvent(win.id, pathname, type, usePolling)) {
const { _preferences } = this
const eol = _preferences.getPreferedEol()
const eol = _preferences.getPreferredEol()
const { autoGuessEncoding, trimTrailingNewline } = _preferences.getAll()
change(win, pathname, type, eol, autoGuessEncoding, trimTrailingNewline)
}
@ -323,7 +323,7 @@ class Watcher {
* @param {string} pathname The path to ignore.
* @param {number} [duration] The duration in ms to ignore the changed event.
*/
ignoreChangedEvent (windowId, pathname, duration = WATCHER_STABILITY_THRESHOLD + WATCHER_STABILITY_POLL_INTERVAL + 1000) {
ignoreChangedEvent (windowId, pathname, duration = WATCHER_STABILITY_THRESHOLD + (WATCHER_STABILITY_POLL_INTERVAL * 2)) {
this._ignoreChangeEvents.push({ windowId, pathname, duration, start: new Date() })
}
@ -333,8 +333,9 @@ class Watcher {
* @param {number} winId
* @param {string} pathname
* @param {string} type
* @param {boolean} usePolling
*/
_shouldIgnoreEvent (winId, pathname, type) {
async _shouldIgnoreEvent (winId, pathname, type, usePolling) {
if (type === 'file') {
const { _ignoreChangeEvents } = this
const currentTime = new Date()
@ -343,9 +344,26 @@ class Watcher {
if (windowId === winId && pathToIgnore === pathname) {
_ignoreChangeEvents.splice(i, 1)
--i
// Modification origin is the editor and we should ignore the event.
if (currentTime - start < duration) {
return true
}
// Try to catch cloud drives that emit the change event not immediately or re-sync the change (GH#3044).
if (!usePolling) {
try {
const fileInfo = await fsPromises.stat(pathname)
if (fileInfo.mtime - start < duration) {
if (global.MARKTEXT_DEBUG_VERBOSE >= 3) {
console.log(`Ignoring file event after "stat": current="${currentTime}", start="${start}", file="${fileInfo.mtime}".`)
}
return true
}
} catch (error) {
console.error('Failed to "stat" file to determine modification time:', error)
}
}
}
}
}

View File

@ -148,7 +148,7 @@ class AppMenu {
const { menu, shortcutMap } = windowMenus.get(window.id)
// Set source-code editor if prefered.
// Set source-code editor if preferred.
const sourceCodeModeMenuItem = menu.getMenuItemById('sourceCodeModeMenuItem')
sourceCodeModeMenuItem.checked = isSourceMode

View File

@ -121,7 +121,7 @@ class Preference extends EventEmitter {
})
}
getPreferedEol () {
getPreferredEol () {
const endOfLine = this.getItem('endOfLine')
if (endOfLine === 'lf') {
return 'lf'

View File

@ -82,7 +82,7 @@ class EditorWindow extends BaseWindow {
// Restore and focus window
this.bringToFront()
const lineEnding = preferences.getPreferedEol()
const lineEnding = preferences.getPreferredEol()
appMenu.updateLineEndingMenu(this.id, lineEnding)
win.webContents.send('mt::bootstrap-editor', {
@ -235,7 +235,7 @@ class EditorWindow extends BaseWindow {
const { browserWindow } = this
const { preferences } = this._accessor
const eol = preferences.getPreferedEol()
const eol = preferences.getPreferredEol()
const { autoGuessEncoding, trimTrailingNewline } = preferences.getAll()
for (const { filePath, options, selected } of fileList) {
@ -393,7 +393,7 @@ class EditorWindow extends BaseWindow {
this.lifecycle = WindowLifecycle.READY
const { preferences } = this._accessor
const { sideBarVisibility, tabBarVisibility, sourceCodeModeEnabled } = preferences.getAll()
const lineEnding = preferences.getPreferedEol()
const lineEnding = preferences.getPreferredEol()
browserWindow.webContents.send('mt::bootstrap-editor', {
addBlankTab: true,
markdownList: [],

View File

@ -614,7 +614,7 @@ export default {
const { container } = this.editor = new Muya(ele, options)
// Create spell check wrapper and enable spell checking if prefered.
// Create spell check wrapper and enable spell checking if preferred.
this.spellchecker = new SpellChecker(spellcheckerEnabled)
if (spellcheckerEnabled) {
this.initSpellchecker()

View File

@ -123,7 +123,7 @@ export class SpellChecker {
* @param {boolean} enabled Whether spell checking is enabled.
*/
constructor (enabled = true) {
// Hunspell is used on Linux and Windows but macOS can use Hunspell if prefered.
// Hunspell is used on Linux and Windows but macOS can use Hunspell if preferred.
this.isHunspell = !isOsSpellcheckerSupported() || !!process.env['SPELLCHECKER_PREFER_HUNSPELL'] // eslint-disable-line dot-notation
// Initialize spell check provider. If spell check is not enabled don't