Directory list grows when the content of a file is replaced
Steps to reproduce
- Create a directory list and make it listen a directory.
- Replace the content of a file that belongs to the directory, using
g_file_replace_contents
.
Current behavior
The number of list items increases.
Expected outcome
The number of list items should keep unchanged.
Version information
GTK 4.0.3.
Additional information
#!/usr/bin/gjs
imports.gi.versions.Gtk = '4.0';
const { Gio, GLib, Gtk } = imports.gi;
const directory = Gio.File.new_for_path(GLib.dir_make_tmp(null));
// Log monitor events.
const monitor = directory.monitor_directory(0, null);
monitor.connect('changed', (monitor_, file, otherFile, eventType) => {
log('monitor-changed: ' + [
file && file.get_basename(),
otherFile && otherFile.get_basename(),
Object.keys(Gio.FileMonitorEvent)[eventType],
]);
});
// Log directory list events.
const directoryList = new Gtk.DirectoryList({ file: directory, attributes: '' });
directoryList.connect('items-changed', (list, position, removed, added) => {
log('list-items-changed: ' + [position, removed, added] + ' => ' + list.get_n_items() + ' items');
});
log(`GTK ${Gtk.MAJOR_VERSION}.${Gtk.MINOR_VERSION}.${Gtk.MICRO_VERSION}`);
log('start: ' + directoryList.get_n_items() + ' items');
// Replace file content.
GLib.timeout_add(0, 1000, () => {
let items = [];
for (let [i, item] = [0, null]; (item = directoryList.get_item(i)); i++)
items.push(item.get_attribute_object('standard::file').get_basename());
log('list items: ' + items);
log('replace contents...');
directory.get_child('test-file').replace_contents('new contents', null, false, Gio.FileCreateFlags.NONE, null);
return true;
});
GLib.MainLoop.new(null, true).run();
/*
Gjs-Message: 16:14:22.438: JS LOG: GTK 4.0.3
Gjs-Message: 16:14:22.438: JS LOG: start: 0 items
Gjs-Message: 16:14:23.440: JS LOG: list items:
Gjs-Message: 16:14:23.440: JS LOG: replace contents...
Gjs-Message: 16:14:23.442: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:14:23.442: JS LOG: monitor-changed: test-file,,CHANGED
Gjs-Message: 16:14:23.443: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:14:23.443: JS LOG: list-items-changed: 0,0,1 => 1 items
Gjs-Message: 16:14:24.442: JS LOG: list items: test-file
Gjs-Message: 16:14:24.442: JS LOG: replace contents...
Gjs-Message: 16:14:24.443: JS LOG: monitor-changed: .goutputstream-TERU00,,CREATED
Gjs-Message: 16:14:24.444: JS LOG: monitor-changed: .goutputstream-TERU00,,CHANGES_DONE_HINT
Gjs-Message: 16:14:24.444: JS LOG: monitor-changed: .goutputstream-TERU00,,ATTRIBUTE_CHANGED
Gjs-Message: 16:14:24.444: JS LOG: monitor-changed: .goutputstream-TERU00,,CHANGED
Gjs-Message: 16:14:24.445: JS LOG: monitor-changed: .goutputstream-TERU00,,CHANGES_DONE_HINT
Gjs-Message: 16:14:24.445: JS LOG: monitor-changed: .goutputstream-TERU00,,DELETED
Gjs-Message: 16:14:24.445: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:14:24.446: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:14:24.446: JS LOG: list-items-changed: 1,0,1 => 2 items
Gjs-Message: 16:14:24.446: JS LOG: list-items-changed: 1,1,1 => 2 items
Gjs-Message: 16:14:24.446: JS LOG: list-items-changed: 2,0,1 => 3 items
Gjs-Message: 16:14:25.443: JS LOG: list items: test-file,.goutputstream-TERU00,test-file
Gjs-Message: 16:14:25.444: JS LOG: replace contents...
Gjs-Message: 16:14:25.445: JS LOG: monitor-changed: .goutputstream-NFQU00,,CREATED
Gjs-Message: 16:14:25.445: JS LOG: monitor-changed: .goutputstream-NFQU00,,CHANGES_DONE_HINT
Gjs-Message: 16:14:25.445: JS LOG: monitor-changed: .goutputstream-NFQU00,,ATTRIBUTE_CHANGED
Gjs-Message: 16:14:25.445: JS LOG: monitor-changed: .goutputstream-NFQU00,,CHANGED
Gjs-Message: 16:14:25.446: JS LOG: monitor-changed: .goutputstream-NFQU00,,CHANGES_DONE_HINT
Gjs-Message: 16:14:25.446: JS LOG: monitor-changed: .goutputstream-NFQU00,,DELETED
Gjs-Message: 16:14:25.446: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:14:25.446: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:14:25.447: JS LOG: list-items-changed: 3,0,1 => 4 items
Gjs-Message: 16:14:25.447: JS LOG: list-items-changed: 3,1,1 => 4 items
Gjs-Message: 16:14:25.447: JS LOG: list-items-changed: 4,0,1 => 5 items
Gjs-Message: 16:14:26.445: JS LOG: list items: test-file,.goutputstream-TERU00,test-file,.goutputstream-NFQU00,test-file
Gjs-Message: 16:14:26.445: JS LOG: replace contents...
Gjs-Message: 16:14:26.446: JS LOG: monitor-changed: .goutputstream-RESU00,,CREATED
Gjs-Message: 16:14:26.446: JS LOG: monitor-changed: .goutputstream-RESU00,,CHANGES_DONE_HINT
Gjs-Message: 16:14:26.446: JS LOG: monitor-changed: .goutputstream-RESU00,,ATTRIBUTE_CHANGED
Gjs-Message: 16:14:26.447: JS LOG: monitor-changed: .goutputstream-RESU00,,CHANGED
Gjs-Message: 16:14:26.447: JS LOG: monitor-changed: .goutputstream-RESU00,,CHANGES_DONE_HINT
Gjs-Message: 16:14:26.447: JS LOG: monitor-changed: .goutputstream-RESU00,,DELETED
Gjs-Message: 16:14:26.447: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:14:26.447: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:14:26.448: JS LOG: list-items-changed: 5,0,1 => 6 items
Gjs-Message: 16:14:26.448: JS LOG: list-items-changed: 5,1,1 => 6 items
Gjs-Message: 16:14:26.448: JS LOG: list-items-changed: 6,0,1 => 7 items
...
*/
The increment is +2 for each replacement: 1 'test-file' file and 1 '.goutputsream-...' file.
I noted that 'goutputsream' files are correctly ignored when the 'attributes' property contains 'standard::name'. So the increment is "only" +1:
...
const directoryList = new Gtk.DirectoryList({ file: directory, attributes: 'standard::name' });
...
Gjs-Message: 16:39:31.933: JS LOG: GTK 4.0.3
Gjs-Message: 16:39:31.933: JS LOG: start: 0 items
Gjs-Message: 16:39:32.935: JS LOG: list items:
Gjs-Message: 16:39:32.935: JS LOG: replace contents...
Gjs-Message: 16:39:32.937: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:39:32.937: JS LOG: monitor-changed: test-file,,CHANGED
Gjs-Message: 16:39:32.937: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:39:32.938: JS LOG: list-items-changed: 0,0,1 => 1 items
Gjs-Message: 16:39:33.937: JS LOG: list items: test-file
Gjs-Message: 16:39:33.937: JS LOG: replace contents...
Gjs-Message: 16:39:33.938: JS LOG: monitor-changed: .goutputstream-TVSI00,,CREATED
Gjs-Message: 16:39:33.938: JS LOG: monitor-changed: .goutputstream-TVSI00,,CHANGES_DONE_HINT
Gjs-Message: 16:39:33.938: JS LOG: monitor-changed: .goutputstream-TVSI00,,ATTRIBUTE_CHANGED
Gjs-Message: 16:39:33.939: JS LOG: monitor-changed: .goutputstream-TVSI00,,CHANGED
Gjs-Message: 16:39:33.939: JS LOG: monitor-changed: .goutputstream-TVSI00,,CHANGES_DONE_HINT
Gjs-Message: 16:39:33.940: JS LOG: monitor-changed: .goutputstream-TVSI00,,DELETED
Gjs-Message: 16:39:33.940: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:39:33.940: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:39:33.940: JS LOG: list-items-changed: 1,0,1 => 2 items
Gjs-Message: 16:39:34.939: JS LOG: list items: test-file,test-file
Gjs-Message: 16:39:34.939: JS LOG: replace contents...
Gjs-Message: 16:39:34.940: JS LOG: monitor-changed: .goutputstream-HIRI00,,CREATED
Gjs-Message: 16:39:34.940: JS LOG: monitor-changed: .goutputstream-HIRI00,,CHANGES_DONE_HINT
Gjs-Message: 16:39:34.940: JS LOG: monitor-changed: .goutputstream-HIRI00,,ATTRIBUTE_CHANGED
Gjs-Message: 16:39:34.941: JS LOG: monitor-changed: .goutputstream-HIRI00,,CHANGED
Gjs-Message: 16:39:34.941: JS LOG: monitor-changed: .goutputstream-HIRI00,,CHANGES_DONE_HINT
Gjs-Message: 16:39:34.941: JS LOG: monitor-changed: .goutputstream-HIRI00,,DELETED
Gjs-Message: 16:39:34.942: JS LOG: monitor-changed: test-file,,CREATED
Gjs-Message: 16:39:34.942: JS LOG: monitor-changed: test-file,,CHANGES_DONE_HINT
Gjs-Message: 16:39:34.942: JS LOG: list-items-changed: 2,0,1 => 3 items
...