Commit 4a4337d1 authored by asseldonk's avatar asseldonk
Browse files

filesystem: bug in last commit

parent f3b387c0
......@@ -21,7 +21,6 @@ import vispa
try:
import Image
import ImageFilter
HAVE_PIL = True
except:
HAVE_PIL = False
......@@ -35,7 +34,6 @@ if not HAVE_PIL:
logger = logging.getLogger(__name__)
def get_file_info(base, name):
root, ext = os.path.splitext(name)
info = {
......@@ -47,7 +45,7 @@ def get_file_info(base, name):
try:
fullpath = os.path.join(base, name)
stats = os.lstat(fullpath)
if stat.S_ISLNK(stats.st_mode):
realfullpath = os.path.realpath(fullpath)
info.update({
......@@ -67,8 +65,8 @@ def get_file_info(base, name):
return info
class FileSystem(object):
FILE_EXTENSIONS = ["png", "jpg", "jpeg", "bmp", "ps", "eps", "pdf",
"txt", "xml", "py", "c", "cpp", "root", "pxlio"]
BROWSER_EXTENSIONS = ["png", "jpg", "jpeg", "bmp"]
......@@ -85,7 +83,7 @@ class FileSystem(object):
self.watchservice = WatchService()
self._userid = userid
self._workspaceid = workspaceid
def __del__(self):
self.close()
......@@ -105,7 +103,7 @@ class FileSystem(object):
def close(self):
if self.watchservice:
self.watchservice.stop()
def get_mime_type(self, filepath):
filepath = self.expand(filepath)
mime, encoding = guess_type(filepath)
......@@ -151,13 +149,7 @@ class FileSystem(object):
# actual function
path = self.expand(path)
if os.path.exists(path):
# import pydevd
# pydevd.settrace('localhost', port=44847, stdoutToServer=False, stderrToServer=False)
# check if reading the file is allowed
if not self.checkPermissions(path, os.R_OK):
return -2
length = len(os.listdir(path))
return length
return len(os.listdir(path))
else:
return -1
......@@ -173,11 +165,11 @@ class FileSystem(object):
# actual function
filter = re.compile(filter) if filter else None
base = self.expand(path)
filelist = [get_file_info(base, name) for name in os.listdir(base) if
not (hide_hidden and name.startswith('.')) and
(not filter or bool(filter.search(name)) == reverse)]
filelist = [i for i in filelist if 'size' in i] # ignore failed file info (e.g. access error)
not (hide_hidden and name.startswith('.')) and
(not filter or bool(filter.search(name)) == reverse)]
filelist = [i for i in filelist if 'size' in i] # ignore failed file info (e.g. access error)
# Determine the parent
parentpath = os.path.dirname(base)
......@@ -190,7 +182,7 @@ class FileSystem(object):
return json.dumps(data)
else:
return data
def get_suggestions(
self, path, length=1, append_hidden=True, encode_json=True):
suggestions = []
......@@ -331,7 +323,7 @@ class FileSystem(object):
paths.append(fullp)
else:
ap = fullp[
len(path):] if fullp.startswith(path) else fullp
len(path):] if fullp.startswith(path) else fullp
logger.debug(fullp)
archive.write(fullp, ap)
else:
......@@ -349,6 +341,7 @@ class FileSystem(object):
return True
# fulltarget = os.path.join(path, fullsrc.split(os.sep)[-1])
logger.error("")
target = self.handle_file_name_collision(
fullsrc.split(os.sep)[-1], path)
fulltarget = os.path.join(path, target)
......@@ -363,7 +356,7 @@ class FileSystem(object):
os.remove(fullsrc)
def save_file(self, path, content, force=True, binary=False,
utf8=False, window_id=None, view_id=None, watch_id=None):
utf8=False, window_id=None, view_id=None, watch_id=None):
path = self.expand(path)
# check if file already exists
if os.path.exists(path) and not force:
......@@ -379,29 +372,29 @@ class FileSystem(object):
f.write(content)
mtime = os.path.getmtime(path)
except Exception as e:
mtime = 0
mtime = 0
# inline watch
if window_id and view_id and watch_id:
watch_error = self.watch(path, window_id, view_id, watch_id)
else:
watch_error = ""
return json.dumps({
"mtime": os.path.getmtime(path),
"success": mtime > 0 and self.checkPermissions(path), # save is not successful, if file not writable
"watch_error": watch_error,
"success": mtime > 0 and self.checkPermissions(path), #save is not successful, if file not writable
"watch_error": watch_error,
"path": path
})
def get_file(self, path, binary=False,
utf8=False, window_id=None, view_id=None, watch_id=None):
utf8=False, window_id=None, view_id=None, watch_id=None):
# inline watch
if window_id and view_id and watch_id:
watch_error = self.watch(path, window_id, view_id, watch_id)
else:
watch_error = ""
# actual function
path = self.expand(path)
try:
......@@ -409,34 +402,34 @@ class FileSystem(object):
content = f.read()
if utf8:
content = content.decode('utf8')
# new: check for writing rights
#new: check for writing rights
writable = self.checkPermissions(path)
error = None
mtime = os.path.getmtime(path)
except Exception as e:
mtime = 0
mtime = 0
content = ""
writable = None
error = str(e)
return json.dumps({
"content": content,
"mtime": mtime,
"success": mtime > 0,
"watch_error": watch_error,
"writable": writable,
"writable": writable,
"error": error
})
def checkPermissions(self, path, permission=os.W_OK):
return os.access(path, permission)
def checkPermissions(self, path):
return os.access(path, os.W_OK)
def save_file_content(self, filename, content,
path=None, force=True, append=False):
# check write permissions
# if not self.checkPermission(username, vPath, 'w'):
# return False, "Permission denied!"
# return False, "Permission denied!"
if path:
filename = os.path.join(path, filename)
......@@ -540,14 +533,10 @@ class FileSystem(object):
path = self.expand(path)
if not os.path.exists(path):
return "The file does not exist"
# check if reading the file is allowed
if not self.checkPermissions(path, os.R_OK):
return "Reading the file is not allowed"
self.watchservice.subscribe((window_id, view_id, watch_id), path, pattern, reverse, hide_hidden)
return ""
def unwatch(self, window_id, view_id, watch_id=None):
self.watchservice.unsubscribe((window_id, view_id, watch_id))
return ""
......@@ -557,10 +546,10 @@ class FileSystem(object):
request_dict = json.loads(request)
config = ConfigParser.ConfigParser()
config.read([FileSystem.GLOBAL_WORKSPACE_CONF,
self.expand(FileSystem.PRIVATE_WORKSPACE_CONF)])
self.expand(FileSystem.PRIVATE_WORKSPACE_CONF)])
if self.exists(FileSystem.PRIVATE_WORKSPACE_CONF):
mtime = self.get_mtime(FileSystem.PRIVATE_WORKSPACE_CONF)
self._watch_workspaceini()
self._watch_workspaceini()
else:
mtime = -1
if not isinstance(request_dict, dict):
......@@ -578,21 +567,20 @@ class FileSystem(object):
if config.has_option(section, name):
data[section][name] = config.get(section, name)
elif fail_on_missing:
raise Exception(
'workspace.ini is missing the option "%s" in section [%s] ' % (name, section))
raise Exception('workspace.ini is missing the option "%s" in section [%s] ' % (name, section))
elif fail_on_missing:
raise Exception('workspace.ini is missing the section [%s]' % section)
return json.dumps({
"content": data,
"success": True,
"mtime": mtime
})
})
except Exception as e:
return json.dumps({
"content": "",
"success": False,
"error": str(e)
})
})
def set_workspaceini(self, request):
try:
......@@ -619,7 +607,6 @@ class FileSystem(object):
if self.exists(FileSystem.PRIVATE_WORKSPACE_CONF, 'f'):
self.watchservice.subscribe((self._userid, self._workspaceid), FileSystem.PRIVATE_WORKSPACE_CONF)
class WatchService(object):
def __init__(self):
self.subscriber_buffer = []
......@@ -630,42 +617,42 @@ class WatchService(object):
self.run = True
self.thread = Thread(target=self._worker)
self.thread.start()
def subscribe(self, id, path, pattern=None, reverse=False, hide_hidden=True):
if not path:
return self.unsubscribe(id)
path = os.path.expanduser(os.path.expandvars(path)).encode('utf8')
with self.lock:
if id not in self.subscribers:
WatchSubscriber(self, id)
self.subscribers[id].update(path, pattern, reverse, hide_hidden)
def unsubscribe(self, id):
with self.lock:
if hasattr(id, '__contains__') and None in id:
for subscriber in self.subscribers.values():
if False not in map(lambda e, c: c is None or e == c, subscriber.id, id):
if False not in map(lambda e,c: c is None or e == c, subscriber.id, id):
subscriber.destroy()
elif id in self.subscribers:
self.subscribers[id].destroy()
def stop(self):
self.run = False
def _worker(self):
while self.run:
events = self.monitor.read_events(0.05)
if events:
with self.lock:
for event in events:
if event.action_name in ['delete self', 'move self']:
if event.action_name in ['delete self','move self']:
kind = 'vanish'
elif event.action_name == 'modify':
kind = 'modify'
elif event.watch.isdir and event.action_name in ['create', 'delete', 'move from', 'move to']:
elif event.watch.isdir and event.action_name in ['create','delete','move from','move to']:
kind = 'change'
else:
kind = None
......@@ -677,32 +664,31 @@ class WatchService(object):
event.watch.mtime = -1
for subscriber in event.watch.subscribers[:]:
subscriber.process(kind, event.name)
if self.subscriber_buffer:
with self.lock:
for subscriber in self.subscriber_buffer[:]:
subscriber.flush(False)
for subscriber in self.subscribers.items():
subscriber.destroy()
self.monitor.remove_all_watches()
self.monitor.close()
class WatchSubscriber(object): # this should never be instanced manually
class WatchSubscriber(object): # this should never be instanced manually
EVENT_DELAYS = {
'change': [1.0, 0.1],
'modify': [1.0, 0.2]
'change': [1.0,0.1],
'modify': [1.0,0.2]
}
MAX_INLINE_SUBJECTS = 10
MAX_SUBJECT_NAMES = 25
def __init__(self, service, id):
if not isinstance(service, WatchService):
raise TypeError("No valid WatchService instance was provided")
if id in service.subscribers:
raise RuntimeError("There is already a subscriber with this id: " + str(id))
raise RuntimeError("There is already a subscriber with this id: "+str(id))
self.id = id
self.service = service
self.service.subscribers[self.id] = self
......@@ -712,7 +698,7 @@ class WatchSubscriber(object): # this should never be instanced manually
self.hide_hidden = None
self.event_buffer = {}
self.subject_buffer = {}
def destroy(self):
self.unbind()
if self in self.service.subscriber_buffer:
......@@ -722,31 +708,30 @@ class WatchSubscriber(object): # this should never be instanced manually
del self.watch
del self.event_buffer
del self.subject_buffer
def process(self, event, subject=""):
if self.watch.isdir and subject:
if self.hide_hidden and subject.startswith('.'):
return
if self.pattern and bool(self.pattern.search(subject)) != self.reverse:
return
if event not in self.subject_buffer:
self.subject_buffer[event] = []
if subject not in self.subject_buffer[event]:
self.subject_buffer[event].append(subject)
if event in WatchSubscriber.EVENT_DELAYS:
now = time()
if event in self.event_buffer:
self.event_buffer[event][1] = now + WatchSubscriber.EVENT_DELAYS[event][1]
else:
self.event_buffer[event] = [now + delay for delay in
WatchSubscriber.EVENT_DELAYS[event]] # first & last event
self.event_buffer[event] = [now + delay for delay in WatchSubscriber.EVENT_DELAYS[event]] #first & last event
if self not in self.service.subscriber_buffer:
self.service.subscriber_buffer.append(self)
else:
self.emit(event)
def flush(self, force=False):
now = time()
for event, delays in self.event_buffer.items():
......@@ -757,7 +742,7 @@ class WatchSubscriber(object): # this should never be instanced manually
self.service.subscriber_buffer.remove(self)
def emit(self, event):
if len(self.id) == 3: # window_id, view_id, watch_id
if len(self.id) == 3: # window_id, view_id, watch_id
data = {
'event': event,
'path': self.watch.path,
......@@ -768,43 +753,42 @@ class WatchSubscriber(object): # this should never be instanced manually
subject_count = len(self.subject_buffer[event])
data['subject_count'] = subject_count
if subject_count <= WatchSubscriber.MAX_INLINE_SUBJECTS:
data['subject_infos'] = [get_file_info(self.watch.path, subject) for subject in
self.subject_buffer[event]]
data['subject_infos'] = [get_file_info(self.watch.path, subject) for subject in self.subject_buffer[event]]
elif subject_count <= WatchSubscriber.MAX_SUBJECT_NAMES:
data['subject_names'] = self.subject_buffer[event]
self.subject_buffer[event] = []
else:
data['mtime'] = self.watch.mtime
vispa.remote.send_topic("extension.%s.socket.watch" % self.id[1], window_id=self.id[0], data=data)
elif len(self.id) == 2: # userid, workspaceid
elif len(self.id) == 2: # userid, workspaceid
vispa.remote.send_topic('workspace.ini_modified', user_id=self.id[0], data={
"workspaceId": self.id[1],
"mtime": self.watch.mtime
})
elif hasattr(self.id, '__call__'):
self.id(event, self)
def update(self, path, pattern="", reverse=False, hide_hidden=True):
self.bind(path)
if self.watch.isdir and pattern:
if not self.pattern or self.pattern.pattern != pattern:
self.pattern = re.compile(pattern)
self.reverse = reverse
self.subject_buffer = {event: [
subject for subject in subjects if bool(self.pattern.search(subject)) == self.reverse
] for event, subjects in self.subject_buffer.items()}
self.subject_buffer = {event:[
subject for subject in subjects if bool(self.pattern.search(subject)) == self.reverse
] for event, subjects in self.subject_buffer.items()}
else:
self.pattern = None
self.reverse = None
self.hide_hidden = hide_hidden
def bind(self, path):
if self.watch:
if self.watch.path == path:
return
else:
self.unbind()
if path not in self.service.watches:
if not os.path.exists(path):
raise IOError("File to be watched does not exist: %s" % path)
......@@ -821,25 +805,24 @@ class WatchSubscriber(object): # this should never be instanced manually
self.service.watches[path] = watch
else:
watch = self.service.watches[path]
self.watch = watch
if self not in watch.subscribers:
watch.subscribers.append(self)
self.subject_buffer = {}
def unbind(self):
if not self.watch:
return
self.watch.subscribers.remove(self)
if len(self.watch.subscribers) == 0:
del self.service.watches[self.watch.path]
self.service.monitor.remove_watch(self.watch)
self.watch = None
def string_compare(a, b):
if a == b:
return 0
......@@ -848,7 +831,6 @@ def string_compare(a, b):
else:
return -1
def file_compare(a, b):
if not a.startswith('.') and not b.startswith('.'):
return string_compare(a, b)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment