v-yarotsky/prj

View on GitHub
ext/prj/fast_traverse.c

Summary

Maintainability
Test Coverage
#include <ruby.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fts.h>

void Init_fast_traverse();

VALUE prj_fast_traverse_traverse_m(VALUE self, VALUE projects_root, VALUE search_nested_repositories);

VALUE Prj, FastTraverse;

void Init_fast_traverse() {
    Prj = rb_define_module("Prj");
    FastTraverse = rb_define_module_under(Prj, "FastTraverse");
    rb_define_singleton_method(FastTraverse, "traverse", prj_fast_traverse_traverse_m, 2);
}

VALUE prj_fast_traverse_traverse_m(VALUE self, VALUE projects_root, VALUE search_nested_repositories) {
    FTS *fs        = NULL;
    FTSENT *child  = NULL;
    FTSENT *parent = NULL;
    VALUE parent_path, child_name;

    char *paths[] = { StringValueCStr(projects_root), NULL };
    fs = fts_open(paths, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT, NULL);

    if (fs == NULL) {
        return Qnil;
    }

    while ((parent = fts_read(fs)) != NULL) {
        child = fts_children(fs, 0);
        while(child != NULL) {
            parent_path = rb_str_new(parent->fts_path, parent->fts_pathlen);
            child_name = rb_str_new(child->fts_name, child->fts_namelen);
            if (child->fts_info == FTS_D && rb_block_given_p() && RTEST(rb_yield_values(2, parent_path, child_name))) {
                fts_set(fs, (RTEST(search_nested_repositories) ? child : parent), FTS_SKIP);
            }
            child = child->fts_link;
        }
    }

    fts_close(fs);
    return Qnil;
}