aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Abbate <francesco.bbt@gmail.com>2022-01-10 16:26:39 +0100
committerFrancesco Abbate <francesco.bbt@gmail.com>2022-01-12 00:32:10 +0100
commitae1890d29a6aeb28be698fcafd3180e63a085de5 (patch)
tree47fb42c6fb8aa80094d7c6f70f03ecd2a88253f3
parent4cdd42de1a5aaa62d50a9b40c8f7af4142710f9d (diff)
downloadlite-xl-ae1890d29a6aeb28be698fcafd3180e63a085de5.tar.gz
lite-xl-ae1890d29a6aeb28be698fcafd3180e63a085de5.zip
Fix project files reading with symlinkfix-dir-monitor-symlinks
-rw-r--r--data/core/init.lua64
-rw-r--r--src/api/system.c8
2 files changed, 51 insertions, 21 deletions
diff --git a/data/core/init.lua b/data/core/init.lua
index 7a44f0ae..315f8c95 100644
--- a/data/core/init.lua
+++ b/data/core/init.lua
@@ -278,20 +278,6 @@ local function file_search(files, info)
end
-local function project_scan_add_entry(dir, fileinfo)
- assert(not dir.force_rescan, "should be used on when force_rescan is unset")
- local index, match = file_search(dir.files, fileinfo)
- if not match then
- table.insert(dir.files, index, fileinfo)
- if fileinfo.type == "dir" and not dir.files_limit then
- -- ASSUMPTION: dir.force_rescan is FALSE
- system.watch_dir_add(dir.watch_id, dir.name .. PATHSEP .. fileinfo.filename)
- end
- dir.is_dirty = true
- end
-end
-
-
local function files_info_equal(a, b)
return a.filename == b.filename and a.type == b.type
end
@@ -308,7 +294,7 @@ local function files_list_match(a, i1, n, b)
end
-- arguments like for files_list_match
-local function files_list_replace(as, i1, n, bs, insert_hook)
+local function files_list_replace(as, i1, n, bs, hook)
local m = #bs
local i, j = 1, 1
while i <= m or i <= n do
@@ -318,8 +304,9 @@ local function files_list_replace(as, i1, n, bs, insert_hook)
then
table.insert(as, i1 + i, b)
i, j, n = i + 1, j + 1, n + 1
- if insert_hook then insert_hook(b) end
+ if hook and hook.insert then hook.insert(b) end
elseif j > m or system.path_compare(a.filename, a.type, b.filename, b.type) then
+ if hook and hook.remove then hook.remove(as[i1 + i]) end
table.remove(as, i1 + i)
n = n - 1
else
@@ -328,6 +315,29 @@ local function files_list_replace(as, i1, n, bs, insert_hook)
end
end
+
+local function project_scan_add_entry(dir, fileinfo)
+ assert(not dir.force_rescan, "should be used only when force_rescan is false")
+ local index, match = file_search(dir.files, fileinfo)
+ if not match then
+ table.insert(dir.files, index, fileinfo)
+ if fileinfo.type == "dir" and not dir.files_limit then
+ -- ASSUMPTION: dir.force_rescan is FALSE
+ system.watch_dir_add(dir.watch_id, dir.name .. PATHSEP .. fileinfo.filename)
+ if fileinfo.symlink then
+ local new_files = get_directory_files(dir, dir.name, PATHSEP .. fileinfo.filename, {}, nil, 0, core.project_subdir_is_shown)
+ files_list_replace(dir.files, index, 0, new_files, {insert = function(info)
+ if info.type == "dir" then
+ system.watch_dir_add(dir.watch_id, dir.name .. PATHSEP .. info.filename)
+ end
+ end})
+ end
+ end
+ dir.is_dirty = true
+ end
+end
+
+
local function project_subdir_bounds(dir, filename)
local index, n = 0, #dir.files
for i, file in ipairs(dir.files) do
@@ -362,11 +372,11 @@ local function rescan_project_subdir(dir, filename_rooted)
-- we missed some directory creation event from the directory monitoring which
-- almost never happens. With inotify is at least theoretically possible.
local need_subdir_watches = not dir.files_limit and not dir.force_rescan
- files_list_replace(dir.files, index, n, new_files, need_subdir_watches and function(fileinfo)
+ files_list_replace(dir.files, index, n, new_files, need_subdir_watches and {insert = function(fileinfo)
if fileinfo.type == "dir" then
system.watch_dir_add(dir.watch_id, dir.name .. PATHSEP .. fileinfo.filename)
end
- end)
+ end})
dir.is_dirty = true
return true
end
@@ -624,10 +634,22 @@ local function project_scan_remove_file(dir, filepath)
fileinfo.type = filetype
local index, match = file_search(dir.files, fileinfo)
if match then
- table.remove(dir.files, index)
- if dir.files_limit and filetype == "dir" then
- dir.shown_subdir[filepath] = nil
+ if filetype == "dir" then
+ -- If the directory is a symlink it may get deleted and we will
+ -- never get dirmonitor events for the removal the files it contains.
+ -- We proceed to remove all the files that belong to the directory.
+ local _, n_subdir = project_subdir_bounds(dir, filepath)
+ files_list_replace(dir.files, index, n_subdir, {}, {
+ remove= function(fileinfo)
+ if fileinfo.type == "dir" then
+ system.watch_dir_rm(dir.watch_id, dir.name .. PATHSEP .. filepath)
+ end
+ end})
+ if dir.files_limit then
+ dir.shown_subdir[filepath] = nil
+ end
end
+ table.remove(dir.files, index)
dir.is_dirty = true
return
end
diff --git a/src/api/system.c b/src/api/system.c
index 4e134e91..10288eba 100644
--- a/src/api/system.c
+++ b/src/api/system.c
@@ -544,6 +544,14 @@ static int f_get_file_info(lua_State *L) {
}
lua_setfield(L, -2, "type");
+#if __linux__
+ if (S_ISDIR(s.st_mode)) {
+ if (lstat(path, &s) == 0) {
+ lua_pushboolean(L, S_ISLNK(s.st_mode));
+ lua_setfield(L, -2, "symlink");
+ }
+ }
+#endif
return 1;
}