Adding initial commit.

This commit is contained in:
sergiotarxz 2022-07-06 14:38:12 +02:00
parent eb643cc0da
commit 81b3d61d1d
4 changed files with 271 additions and 0 deletions

41
meson.build Normal file
View File

@ -0,0 +1,41 @@
project('me.sergiotarxz.owlpath', 'vala')
compiler = meson.get_compiler('c')
vapidir = meson.project_source_root() / 'vapi'
is_windows = false
ws = '/'
if compiler.has_header('windows.h')
ws = '\\\\'
is_windows = true
endif
config_h = configure_file (
output : 'config.h',
configuration : {
'WS': f'"@ws@"',
},
)
owlpath_deps = [
dependency('glib-2.0'),
dependency('gio-2.0'),
meson.get_compiler('vala').find_library('config', dirs : vapidir),
]
sources = [
'src/owlpath.vala',
]
owlpath_lib = library('owlpath',
sources,
dependencies : owlpath_deps,
install : true,
install_dir: [true, true, true],
)
executable('owlpath-test',
['test/00-owlpath.test.vala'],
dependencies : owlpath_deps,
link_with: [owlpath_lib]
)

156
src/owlpath.vala Normal file
View File

@ -0,0 +1,156 @@
namespace Owl {
public delegate bool VisitFileLambda (Owl.Path file);
public class Path {
static string ALPHABET_STRING = "abcdefghijklmnopqrstuvwxyz";
GLib.File file;
bool is_tmp;
private static string get_random_string () {
var random_generator = new GLib.Rand ();
string final_string = "valatmp-";
for (uint64 i = 0; i < 12; i++) {
var random_number = random_generator.next_int () % ALPHABET_STRING.length;
final_string += ALPHABET_STRING[random_number].to_string ();
}
return final_string;
}
public Path (GLib.File file) {
this.file = file;
}
public Path.tempdir () throws GLib.Error {
this.is_tmp = true;
var file = GLib.File.new_for_path(GLib.Environment.get_tmp_dir () + Config.WS + get_random_string ());
while (file.query_exists ()) {
file = GLib.File.new_for_path(GLib.Environment.get_tmp_dir () + Config.WS + get_random_string ());
}
file.make_directory ();
this.file = file;
}
~Path () {
if (this.is_tmp) {
try {
this.@delete ();
} catch (GLib.Error error) {
GLib.critical (error.message);
}
}
}
public void spew (string content) throws GLib.Error {
GLib.FileUtils.set_contents (this.get_path (), content);
}
public string slurp () throws GLib.Error {
string output;
GLib.FileUtils.get_contents (this.get_path (), out output);
return output;
}
public GLib.FileOutputStream replace () throws GLib.Error {
return this.file.replace (null, false, GLib.FileCreateFlags.PRIVATE);
}
public GLib.FileOutputStream create () throws GLib.Error {
return this.file.create (GLib.FileCreateFlags.PRIVATE);
}
public Owl.Path child (string relative_path) throws GLib.Error {
GLib.File child_file = this.file.resolve_relative_path (relative_path);
return new Owl.Path (child_file);
}
public void mkpath () throws GLib.Error {
this.file.make_directory_with_parents ();
}
public bool exists () {
return this.file.query_exists ();
}
public Owl.Path parent () {
return new Owl.Path (this.file.get_parent ());
}
public void @delete () throws GLib.Error {
if (!this.is_dir ()) {
this.file.delete ();
return;
}
foreach (Owl.Path inner_file in this.children ()) {
inner_file.delete ();
}
this.file.delete ();
}
public GLib.File get_file () {
return this.file;
}
public string? get_path () {
return this.file.get_path ();
}
public string basename () {
return this.file.get_basename ();
}
public GLib.List<Owl.Path> children() {
var children = new GLib.List<Owl.Path> ();
if (!this.is_dir ()) {
GLib.critical ("You cannot list children if the target is not a directory.\n");
return children;
}
try {
GLib.FileEnumerator enumerator = this.file.enumerate_children (
"standard::*",
FileQueryInfoFlags.NONE);
GLib.FileInfo info;
while ((info = enumerator.next_file (null)) != null) {
GLib.File inner_file = file.resolve_relative_path (info.get_name ());
children.append (new Owl.Path (inner_file));
}
} catch (GLib.Error error) {
GLib.critical (error.message);
return children;
}
return children;
}
public bool visit (bool recursive, Owl.VisitFileLambda lambda, bool visit_upper_dir = true) {
if (!this.is_dir ()) {
GLib.critical ("Unable to visit non directory\n");
return false;
}
if (visit_upper_dir) {
bool continue_visit = lambda (this);
if (!continue_visit) {
return false;
}
}
foreach (Owl.Path inner_file in this.children ()) {
bool continue_visit = lambda (inner_file);
if (!continue_visit) {
return false;
}
if (recursive && inner_file.is_dir ()) {
continue_visit = inner_file.visit (true, lambda, false);
if (!continue_visit) {
return false;
}
}
}
return true;
}
public bool is_dir () {
return this.query () == GLib.FileType.DIRECTORY;
}
private GLib.FileType query () {
return this.file.query_file_type (GLib.FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
}
}
}

70
test/00-owlpath.test.vala Normal file
View File

@ -0,0 +1,70 @@
delegate void ContextLambda ();
const string S = Config.WS;
int main (string[] args) {
GLib.Test.init (ref args);
GLib.Test.add_func ("/test/owl/path-tempdir", () => {
Owl.Path file = null;
ContextLambda inner_context = () => {
Owl.Path tmp;
try {
tmp = new Owl.Path.tempdir ();
assert (tmp.exists ());
file = new Owl.Path (GLib.File.new_for_path (tmp.get_path ()));
} catch (GLib.Error error) {
GLib.Test.fail_printf ("%s\n", error.message);
}
};
inner_context ();
assert (!file.exists ());
});
GLib.Test.add_func ("/test/owl/path-mkpath", () => {
try {
var tmp = new Owl.Path.tempdir ();
var child = tmp.child (@"a$(S)b$(S)c");
child.mkpath();
assert (child.exists ());
} catch (GLib.Error error) {
GLib.Test.fail_printf ("%s\n", error.message);
}
});
GLib.Test.add_func ("/test/owl/path-spew-slurp", () => {
try {
var tmp = new Owl.Path.tempdir ();
var child = tmp.child (@"a$(S)b$(S)c");
child.mkpath();
var file_txt = child.child ("file.txt");
string contents = "hola mundo\nadios hola\nadios mundo";
file_txt.spew (contents);
assert (contents == file_txt.slurp ());
} catch (GLib.Error error) {
GLib.Test.fail_printf ("%s\n", error.message);
}
});
GLib.Test.add_func ("/test/owl/path-visit", () => {
try {
var hashmap = new GLib.HashTable<string, bool> (str_hash, str_equal);
var tmp = new Owl.Path.tempdir ();
var file1 = tmp.child(@"a$(S)b$(S)c$(S)/file1.txt");
var file2 = tmp.child(@"a$(S)c$(S)b$(S)/file2.txt");
file1.parent ().mkpath ();
file2.parent ().mkpath ();
file1.spew ("hola");
file2.spew ("hola");
tmp.visit (true, (file) => {
if (file.basename () == "a") {
hashmap.@set(file.basename (), true);
}
if (!file.is_dir ()) {
hashmap.@set(file.basename (), true);
}
return true;
});
assert (hashmap.@get("file1.txt"));
assert (hashmap.@get("file2.txt"));
assert (hashmap.@get("a"));
} catch (GLib.Error error) {
GLib.Test.fail_printf ("%s\n", error.message);
}
});
return GLib.Test.run ();
}

4
vapi/config.vapi Normal file
View File

@ -0,0 +1,4 @@
[CCode (cheader_filename = "config.h", lower_case_cprefix = "")]
namespace Config {
public const string WS;
}