<commit_before>/*
 * Copyright © 2010 Codethink Limited
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the licence, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: <NAME> <<EMAIL>>
 */

unowned Gvdb.Item get_parent (Gvdb.HashTable table, string name) {
	unowned Gvdb.Item parent;

	int end = 0;

	for (int i = 0; name[i] != '\0'; i++) {
		if (name[i - 1] == '/') {
			end = i;
		}
	}

	var parent_name = name.ndup (end);
	parent = table.lookup (parent_name);

	if (parent == null) {
		parent = table.insert (parent_name);
		parent.set_parent (get_parent (table, parent_name));
	}

	return parent;
}

Gvdb.HashTable read_directory (string dirname) throws GLib.Error {
	var table = new Gvdb.HashTable ();
	unowned string? name;

	table.insert ("/");

	var dir = Dir.open (dirname);
	while ((name = dir.read_name ()) != null) {
		var filename = Path.build_filename (dirname, name);

		var kf = new KeyFile ();

		try {
			kf.load_from_file (filename, KeyFileFlags.NONE);
		} catch (GLib.Error e) {
			stderr.printf ("%s: %s\n", filename, e.message);
			continue;
		}

		foreach (var group in kf.get_groups ()) {
			if (group.has_prefix ("/") || group.has_suffix ("/") || group.str ("//") != null) {
				stderr.printf ("%s: ignoring invalid group name: %s\n", filename, group);
				continue;
			}

			foreach (var key in kf.get_keys (group)) {
				if (key.str ("/") != null) {
					stderr.printf ("%s: [%s]: ignoring invalid key name: %s\n", filename, group, key);
					continue;
				}

				var path = "/" + group + "/" + key;

				if (table.lookup (path) != null) {
					stderr.printf ("%s: [%s]: %s: ignoring duplicate definition of key %s\n",
					               filename, group, key, path);
					continue;
				}

				var text = kf.get_value (group, key);

				try {
					var value = Variant.parse (null, text);
					unowned Gvdb.Item item = table.insert (path);
					item.set_parent (get_parent (table, path));
					item.set_value (value);
				} catch (VariantParseError e) {
					stderr.printf ("%s: [%s]: %s: skipping invalid value: %s (%s)\n",
					               filename, group, key, text, e.message);
				}
			}
		}
	}

	return table;
}

void maybe_update_from_directory (string dirname) throws GLib.Error {
	Posix.Stat dir_buf;

	if (Posix.stat (dirname, out dir_buf) == 0 && Posix.S_ISDIR (dir_buf.st_mode)) {
		Posix.Stat file_buf;

		var filename = dirname.ndup (dirname.length - 2);

		if (Posix.stat (filename, out file_buf) == 0 && file_buf.st_mtime > dir_buf.st_mtime) {
			return;
		}

		var table = read_directory (dirname);

		var fd = Posix.open (filename, Posix.O_WRONLY);

		if (fd < 0 && errno != Posix.EEXIST) {
			var saved_error = errno;
			throw new FileError.FAILED ("Can not open '%s' for replacement: %s", filename, strerror (saved_error));
		}

		try {
			table.write_contents (filename);
<commit_msg>dconf update: Fix error code EEXIST -> ENOENT<commit_after>/*
 * Copyright © 2010 Codethink Limited
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the licence, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: <NAME> <<EMAIL>>
 */

unowned Gvdb.Item get_parent (Gvdb.HashTable table, string name) {
	unowned Gvdb.Item parent;

	int end = 0;

	for (int i = 0; name[i] != '\0'; i++) {
		if (name[i - 1] == '/') {
			end = i;
		}
	}

	var parent_name = name.ndup (end);
	parent = table.lookup (parent_name);

	if (parent == null) {
		paren = table.insert (parent_name);
		parent.set_parent (get_parent (table, parent_name));
	}

	return parent;
}

Gvdb.HashTable read_directory (string dirname) throws GLib.Error {
	var table = new Gvdb.HashTable ();
	unowned string? name;

	table.insert ("/");

	var dir = Dir.open (dirname);
	while ((name = dir.read_name ()) != null) {
		var filename = Path.build_filename (dirname, name);

		var kf = new KeyFile ();

		try {
			kf.load_from_file (filename, KeyFileFlags.NONE);
		} catch (GLib.Error e) {
			stderr.printf ("%s: %s\n", filename, e.message);
			continue;
		}

		foreach (var group in kf.get_groups ()) {
			if (group.has_prefix ("/") || group.has_suffix ("/") || group.str ("//") != null) {
				stderr.printf ("%s: ignoring invalid group name: %s\n", filename, group);
				continue;
			}

			foreach (var key in kf.get_keys (group)) {
				if (key.str ("/") != null) {
					stderr.printf ("%s: [%s]: ignoring invalid key name: %s\n", filename, group, key);
					continue;
				}

				var path = "/" + group + "/" + key;

				if (table.lookup (path) != null) {
					stderr.printf ("%s: [%s]: %s: ignoring duplicate definition of key %s\n",
					               filename, group, key, path);
					continue;
				}

				var text = kf.get_value (group, key);

				try {
					var value = Variant.parse (null, text);
					unowned Gvdb.Item item = table.insert (path);
					item.set_parent (get_parent (table, path));
					item.set_value (value);
				} catch (VariantParseError e) {
					stderr.printf ("%s: [%s]: %s: skipping invalid value: %s (%s)\n",
					               filename, group, key, text, e.message);
				}
			}
		}
	}

	return table;
}

void maybe_update_from_directory (string dirname) throws GLib.Error {
	Posix.Stat dir_buf;

	if (Posix.stat (dirname, out dir_buf) == 0 && Posix.S_ISDIR (dir_buf.st_mode)) {
		Posix.Stat file_buf;

		var filename = dirname.ndup (dirname.length - 2);

		if (Posix.stat (filename, out file_buf) == 0 && file_buf.st_mtime > dir_buf.st_mtime) {
			return;
		}

		var table = read_directory (dirname);

		var fd = Posix.open (filename, Posix.O_WRONLY);

		if (fd < 0 && errno != Posix.ENOENT) {
			var saved_error = errno;
			throw new FileError.FAILED ("Can not open '%s' for replacement: %s", filename, strerror (saved_error));
		}

		try {
			table.write_contents (filename);

{'fraction_non_alphanumeric': 0.13758052970651397, 'fraction_numerical': 0.007730851825340015, 'mean_word_length': 3.1264028352037805, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3585363', 'n_tokens_mistral': 2653, 'n_tokens_neox': 2305, 'n_words': 772}