Switch to using winutil for auto-reload on windows

This commit is contained in:
Kovid Goyal 2020-10-08 16:44:22 +05:30
parent 1754c87256
commit d4ea5f726d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -5,10 +5,17 @@
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
import os, sys, subprocess, signal, time, errno, socket, ssl import errno
from threading import Thread, Lock import os
import signal
import socket
import ssl
import subprocess
import sys
import time
from threading import Lock, Thread
from calibre.constants import islinux, iswindows, ismacos from calibre.constants import islinux, ismacos, iswindows, plugins
from calibre.srv.http_response import create_http_handler from calibre.srv.http_response import create_http_handler
from calibre.srv.loop import ServerLoop from calibre.srv.loop import ServerLoop
from calibre.srv.opts import Options from calibre.srv.opts import Options
@ -16,8 +23,8 @@ from calibre.srv.standalone import create_option_parser
from calibre.srv.utils import create_sock_pair from calibre.srv.utils import create_sock_pair
from calibre.srv.web_socket import DummyHandler from calibre.srv.web_socket import DummyHandler
from calibre.utils.monotonic import monotonic from calibre.utils.monotonic import monotonic
from polyglot.builtins import itervalues, error_message, native_string_type from polyglot.builtins import error_message, itervalues, native_string_type
from polyglot.queue import Queue, Empty from polyglot.queue import Empty, Queue
MAX_RETRIES = 10 MAX_RETRIES = 10
@ -61,6 +68,7 @@ class WatcherBase(object):
if islinux: if islinux:
import select import select
from calibre.utils.inotify import INotifyTreeWatcher from calibre.utils.inotify import INotifyTreeWatcher
class Watcher(WatcherBase): class Watcher(WatcherBase):
@ -93,48 +101,49 @@ if islinux:
self.client_sock.sendall(b'w') self.client_sock.sendall(b'w')
elif iswindows: elif iswindows:
import win32file, win32con
FILE_LIST_DIRECTORY = 0x0001
from calibre.srv.utils import HandleInterrupt from calibre.srv.utils import HandleInterrupt
class TreeWatcher(Thread): class TreeWatcher(Thread):
daemon = True
def __init__(self, path_to_watch, modified_queue): def __init__(self, path_to_watch, modified_queue):
Thread.__init__(self, name='TreeWatcher') Thread.__init__(self, name='TreeWatcher', daemon=True)
self.modified_queue = modified_queue self.modified_queue = modified_queue
self.path_to_watch = path_to_watch self.path_to_watch = path_to_watch
self.dir_handle = win32file.CreateFileW(
path_to_watch,
FILE_LIST_DIRECTORY,
win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS,
None
)
def run(self): def run(self):
winutil = plugins['winutil'][0]
dir_handle = winutil.create_file(
self.path_to_watch,
winutil.FILE_LIST_DIRECTORY,
winutil.FILE_SHARE_READ,
winutil.OPEN_EXISTING,
winutil.FILE_FLAG_BACKUP_SEMANTICS,
)
try: try:
buffer = b'0' * 8192
while True: while True:
results = win32file.ReadDirectoryChangesW( try:
self.dir_handle, results = winutil.read_directory_changes(
8192, # Buffer size for storing events dir_handle, buffer,
True, # Watch sub-directories as well True, # Watch sub-directories as well
win32con.FILE_NOTIFY_CHANGE_FILE_NAME | winutil.FILE_NOTIFY_CHANGE_FILE_NAME |
win32con.FILE_NOTIFY_CHANGE_DIR_NAME | winutil.FILE_NOTIFY_CHANGE_DIR_NAME |
win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES | winutil.FILE_NOTIFY_CHANGE_ATTRIBUTES |
win32con.FILE_NOTIFY_CHANGE_SIZE | winutil.FILE_NOTIFY_CHANGE_SIZE |
win32con.FILE_NOTIFY_CHANGE_LAST_WRITE | winutil.FILE_NOTIFY_CHANGE_LAST_WRITE |
win32con.FILE_NOTIFY_CHANGE_SECURITY, winutil.FILE_NOTIFY_CHANGE_SECURITY,
None, None
) )
for action, filename in results: for action, filename in results:
if self.file_is_watched(filename): if self.file_is_watched(filename):
self.modified_queue.put(os.path.join(self.path_to_watch, filename)) self.modified_queue.put(os.path.join(self.path_to_watch, filename))
except OverflowError:
pass # the buffer overflowed, there are unknown changes
except Exception: except Exception:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
finally:
winutil.close_handle(dir_handle)
class Watcher(WatcherBase): class Watcher(WatcherBase):
@ -282,7 +291,7 @@ class Worker(object):
self.p = None self.p = None
def restart(self, forced=False): def restart(self, forced=False):
from calibre.utils.rapydscript import compile_srv, CompileFailure from calibre.utils.rapydscript import CompileFailure, compile_srv
self.clean_kill() self.clean_kill()
if forced: if forced:
self.retry_count += 1 self.retry_count += 1