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}