Fix several problem with directory update

When scanning a subdirectory on-demand ensure files aready present
are not added twice. Files or directory can be already present due
to dir monitoring create message.

Fix check for ignore files when adding a file to respond to a dir monitor
event to use each part of the file's path.

Fix C function to compare files for treeview placement.
This commit is contained in:
Francesco Abbate 2021-07-15 18:49:18 +02:00
parent ad7bdeb129
commit aa37f2b149
3 changed files with 57 additions and 34 deletions

View File

@ -187,6 +187,36 @@ function core.add_project_directory(path)
end end
local function file_search(files, info)
local filename, type = info.filename, info.type
local inf, sup = 1, #files
while sup - inf > 8 do
local curr = math.floor((inf + sup) / 2)
if system.path_compare(filename, type, files[curr].filename, files[curr].type) then
sup = curr - 1
else
inf = curr
end
end
repeat
if files[inf].filename == filename then
return inf, true
end
inf = inf + 1
until inf > sup or system.path_compare(filename, type, files[inf].filename, files[inf].type)
return inf, false
end
local function project_scan_add_entry(dir, fileinfo)
local index, match = file_search(dir.files, fileinfo)
if not match then
table.insert(dir.files, index, fileinfo)
dir.is_dirty = true
end
end
function core.scan_project_subdir(dirname, filename) function core.scan_project_subdir(dirname, filename)
for _, dir in ipairs(core.project_directories) do for _, dir in ipairs(core.project_directories) do
if dir.name == dirname then if dir.name == dirname then
@ -195,8 +225,8 @@ function core.scan_project_subdir(dirname, filename)
if file.filename == filename then if file.filename == filename then
if file.scanned then return end if file.scanned then return end
local new_files = get_directory_files(dirname, PATHSEP .. filename, {}) local new_files = get_directory_files(dirname, PATHSEP .. filename, {})
for j, new_file in ipairs(new_files) do for _, new_file in ipairs(new_files) do
table.insert(dir.files, i + j, new_file) project_scan_add_entry(dir, new_file)
end end
file.scanned = true file.scanned = true
return true return true
@ -282,27 +312,6 @@ function core.project_files_number()
end end
local function file_search(files, info)
local filename, type = info.filename, info.type
local inf, sup = 1, #files
while sup - inf > 8 do
local curr = math.floor((inf + sup) / 2)
if system.path_compare(filename, type, files[curr].filename, files[curr].type) then
sup = curr - 1
else
inf = curr
end
end
repeat
if files[inf].filename == filename then
return inf, true
end
inf = inf + 1
until inf > sup or system.path_compare(filename, type, files[inf].filename, files[inf].type)
return inf, false
end
local function project_scan_remove_file(watch_id, filepath) local function project_scan_remove_file(watch_id, filepath)
local project_dir_entry local project_dir_entry
for i = 1, #core.project_directories do for i = 1, #core.project_directories do
@ -333,14 +342,16 @@ local function project_scan_add_file(watch_id, filepath)
project_dir_entry = core.project_directories[i] project_dir_entry = core.project_directories[i]
end end
end end
if not project_dir_entry or common.match_pattern(filepath, config.ignore_files) then return end if not project_dir_entry then return end
for fragment in string.gmatch(filepath, "([^/\\]+)") do
if common.match_pattern(fragment, config.ignore_files) then
return
end
end
local size_limit = config.file_size_limit * 10e5 local size_limit = config.file_size_limit * 10e5
local fileinfo = get_project_file_info(project_dir_entry.name, PATHSEP .. filepath, size_limit) local fileinfo = get_project_file_info(project_dir_entry.name, PATHSEP .. filepath, size_limit)
local index, match = file_search(project_dir_entry.files, fileinfo) if fileinfo then
if not match then project_scan_add_entry(project_dir_entry, fileinfo)
table.insert(project_dir_entry.files, index, fileinfo)
project_dir_entry.is_dirty = true
return
end end
end end

View File

@ -104,9 +104,9 @@ end
function TreeView:check_cache() function TreeView:check_cache()
-- invalidate cache's skip values if project_files has changed
for i = 1, #core.project_directories do for i = 1, #core.project_directories do
local dir = core.project_directories[i] local dir = core.project_directories[i]
-- invalidate cache's skip values if directory is declared dirty
if dir.is_dirty and self.cache[dir.name] then if dir.is_dirty and self.cache[dir.name] then
self:invalidate_cache(dir.name) self:invalidate_cache(dir.name)
end end
@ -219,9 +219,7 @@ function TreeView:on_mouse_pressed(button, x, y, clicks)
else else
if hovered_item.dir.files_limit and not hovered_item.expanded then if hovered_item.dir.files_limit and not hovered_item.expanded then
local dirname = hovered_item.dir.name local dirname = hovered_item.dir.name
if core.scan_project_subdir(dirname, hovered_item.filename) then core.scan_project_subdir(dirname, hovered_item.filename)
self:invalidate_cache(dirname)
end
end end
hovered_item.expanded = not hovered_item.expanded hovered_item.expanded = not hovered_item.expanded
end end

View File

@ -689,7 +689,21 @@ static int f_path_compare(lua_State *L) {
return 1; return 1;
} }
/* If types are the same compare the files' path alphabetically. */ /* If types are the same compare the files' path alphabetically. */
lua_pushboolean(L, strcmp(path1 + i, path2 + i) < 0); int cfr = 0;
int len_min = (len1 < len2 ? len1 : len2);
for (int j = i; j <= len_min; j++) {
if (path1[j] == path2[j]) continue;
if (path1[j] == 0 || path2[j] == 0) {
cfr = (path1[j] == 0);
} else if (path1[j] == PATHSEP || path2[j] == PATHSEP) {
/* For comparison we treat PATHSEP as if it was the string terminator. */
cfr = (path1[j] == PATHSEP);
} else {
cfr = (path1[j] < path2[j]);
}
break;
}
lua_pushboolean(L, cfr);
return 1; return 1;
} }