login

local ffi = require "ffi"
local git = require "git"

ffi.cdef[[
typedef unsigned long ino_t;
typedef unsigned long off_t;
struct dirent {
    ino_t          d_ino;       /* Inode number */
    off_t          d_off;       /* Not an offset; see below */
    unsigned short d_reclen;    /* Length of this record */
    unsigned char  d_type;      /* Type of file; not supported
                                  by all filesystem types */
    char           d_name[256]; /* Null-terminated filename */
};
int scandir(const char *restrict dirp,
    struct dirent ***restrict namelist,
    int (*filter)(const struct dirent *),
    int (*compar)(const struct dirent **,
        const struct dirent **));
int alphasort(const struct dirent **a, const struct dirent **b);
enum {
    DT_UNKNOWN  =  0,
    DT_FIFO     =  1,
    DT_CHR      =  2,
    DT_DIR      =  4,
    DT_BLK      =  6,
    DT_REG      =  8,
    DT_LNK      = 10,
    DT_SOCK     = 12,
};
]]
local C = ffi.C

local function listdir(path, filter)
    local c_filter = filter and function (entry)
        return filter(entry)
    end
    local pentries = ffi.new("struct dirent **[1]")
    local n = C.scandir(path, pentries, c_filter, C.alphasort)
    local entries = pentries[0]
    local list = {}
    for i = 1, n do
        table.insert(list, ffi.string(entries[i-1].d_name))
    end
    return list
end

local function scanrepos(path)
    local folders = listdir(path, function (e)
        return e.d_type == C.DT_DIR and ffi.string(e.d_name):sub(1, 1) ~= "."
    end)
    local groups = {}
    for _, folder in ipairs(folders) do
        local group_path = path.."/"..folder
        local git_folders = listdir(group_path, function (e)
            return e.d_type == C.DT_DIR and (ffi.string(e.d_name):match(".*%.git$") ~= nil)
        end)
        local group = {}
        for _, git_folder in ipairs(git_folders) do
            local repo_path = group_path.."/"..git_folder
            local repo_name = git_folder:match("(.*)%.git$")
            group[repo_name] = git.open(repo_path)
        end
        groups[folder] = group
    end
    return groups
end

return {scanrepos=scanrepos}