#include #include #include #include #include #include #include #include #include #include #include "config.h" #include "git.h" #include "macros.h" git_repo *add_repo(git_repository *repo, git_repo **first, git_repo **last) { git_repo *new_repo = calloc(1, sizeof(git_repo)); (*last != NULL) ? ((*last)->next = new_repo) : (*first = new_repo); new_repo->repo = repo; *last = new_repo; return new_repo; } int find_ignore_file(const char *path) { DIR *root = opendir(path); struct dirent entry, *result; while (readdir_r(root, &entry, &result) == 0 && result != NULL) { /* Is this entry a regular file, and is it the ignore file? */ if (entry.d_type == DT_REG && strcasecmp(entry.d_name, "pullreqd-ignore") == 0) { return 1; } } return 0; } void cleanup_linked_list(git_repo *root) { if (root != NULL) { git_repo *repo = root; cleanup_linked_list(root->next); repo->repo = NULL; repo->next = NULL; free(repo); } } void cleanup_git_repos(git_repository **repos) { for (int i = 0; repos[i] != NULL; i++) { git_repository_free(repos[i]); repos[i] = NULL; } free(repos); } void cleanup_git(git_repository **repos) { cleanup_git_repos(repos); git_libgit2_shutdown(); } git_repository **init_git(config *cfg) { git_repository **repos = NULL; git_repository *repo = NULL; git_repo *first = NULL, *last = NULL, *current = NULL; DIR *root = opendir(cfg->git_root); struct dirent entry, *result; int repo_count = 0; log(LOG_INFO, "Initializing libgit2."); int ret = git_libgit2_init(); log(LOG_INFO, "Searching \"%s\" for repositories.", cfg->git_root); /* Find all git repos in the git root. */ while (readdir_r(root, &entry, &result) == 0 && result != NULL) { log(LOG_DEBUG, "entry.d_name %s, result->d_name: %s", entry.d_name, result->d_name); /* Is this entry a directory? */ if (entry.d_type == DT_DIR) { /* Is the entry neither ".", nor ".."? */ if (strcmp(entry.d_name, ".") && strcmp(entry.d_name, "..")) { char *repo_dir = calloc(strlen(cfg->git_root) + strlen(entry.d_name) + 1, sizeof(char)); /* Append the directory name to the git root. */ /* Could also do this: * memcpy(repo_dir, cfg->git_root, strlen(cfg->git_repo)); * strcat(repo_dir, entry.d_name); */ sprintf(repo_dir, "%s%s", cfg->git_root, entry.d_name); /* Was no ignore file found? */ if (!find_ignore_file(repo_dir)) { /* Did we fail to open the git repo? */ if (git_repository_open(&repo, repo_dir)) { log(LOG_ERR, "Failed to open git repository %s, ignoring.", entry.d_name); } else { log(LOG_INFO, "Successfully opened git repository %s", entry.d_name); current = add_repo(repo, &first, &last); repo_count++; } } free(repo_dir); } } } /* Did we find any repos? */ if (repo_count) { log(LOG_INFO, "Found, and opened %i repositories.", repo_count); /* Allocate repo_count + 1 git repos, since we need a NULL entry to denote the end. */ repos = calloc(repo_count+1, sizeof(git_repository *)); /* Add the repos to the array. */ int i = 0; for (git_repo *r = first; r != NULL; /*repos[i] = r->repo,*/ r = r->next, i++) { repos[i] = r->repo; } cleanup_linked_list(first); first = NULL; last = NULL; current = NULL; } else { log(LOG_ERR, "Couldn't find, and/or open any repositories."); } return repos; }