My pretty neat website
git clone git://soophie.de/soso
blob: 060847774c3d57ed7e55b8936a715b90e1454b82 (9286 bytes)[raw]
1
#include <git2.h>2
#include <git2/types.h>3
#include "git_repo.h"5
#include "../templ/duc_git_repo.h"7
static orb_rc_t init(orb_module_t *self) {8
duc_git_repo_t *data = self->data;9
git_repo_param_list_t *param_list = self->param_list;10
if (param_list) {11
data->repo = (git_repo_t) {12
.path = param_list->repo_path,13
.meta = {0},14
.handle = NULL,15
.flag_ref_oid = param_list->flag_ref_oid,16
.flag_oid = param_list->flag_oid,17
.flag_path = param_list->flag_path,18
.ref_head = NULL,19
.ref = NULL,20
.ref_list = NULL,21
.ref_list_len = 0,22
};23
data->repo.meta.name = param_list->repo_name;24
data->tab_mode = param_list->tab_mode;25
}26
return ORB_OK;27
}29
static int _fetch_read_text_file(char *filename, char **content) {30
FILE *fd = fopen(filename, "r");31
if (fd == NULL) return 1;32
fseek(fd, 0, SEEK_END);33
size_t len = ftell(fd);34
fseek(fd, 0, SEEK_SET);35
*content = calloc(1, sizeof(char) * (len + 1));36
fread(*content, sizeof(char), len, fd);37
(*content)[len] = '\0';38
fclose(fd);39
return 0;40
}42
static int _fetch_read_git_file(char *repo_path, char *filename, char **content) {43
size_t file_path_len = strlen(repo_path) + strlen(filename) + 2;44
char file_path[file_path_len];45
snprintf(file_path, file_path_len, "%s/%s", repo_path, filename);46
return _fetch_read_text_file(file_path, content);47
}49
static bool _fetch_git_file_exists(char *repo_path, char *filename) {50
size_t file_path_len = strlen(repo_path) + strlen(filename) + 2;51
char file_path[file_path_len];52
snprintf(file_path, file_path_len, "%s/%s", repo_path, filename);53
FILE *fp = fopen(file_path, "r");54
if (!fp) return false;55
fclose(fp);56
return true;57
}59
static char *_fetch_git_file_oid(git_repository *repo, char *ref_name, char *filename) {60
size_t spec_len = strlen(ref_name) + strlen(filename) + 2;61
char spec[spec_len];62
snprintf(spec, spec_len, "%s:%s", ref_name, filename);63
git_object *obj_handle = NULL;64
if (git_revparse_single(&obj_handle, repo, spec) != 0) return NULL;65
char oid_str[GIT_OID_HEXSZ + 1];66
git_oid_tostr(oid_str, sizeof(oid_str), git_object_id(obj_handle));67
git_object_free(obj_handle);68
return strdup(oid_str);69
}71
static orb_rc_t fetch(orb_module_t *self) {72
duc_git_repo_t *data = self->data;73
git_repo_param_list_t *param_list = self->param_list;74
if (!param_list->repo_path) return ORB_FATAL(1);75
bool is_public = _fetch_git_file_exists(param_list->repo_path, "git-daemon-export-ok");76
if (!is_public) return ORB_FATAL(2);77
git_repository *repo_handle = NULL;78
int code = git_repository_open(&repo_handle, param_list->repo_path);79
if (code < 0 || repo_handle == NULL) return ORB_FATAL(code);80
data->repo.handle = repo_handle;81
_fetch_read_git_file(data->repo.path, "description", &data->repo.meta.description);82
_fetch_read_git_file(data->repo.path, "owner", &data->repo.meta.owner);83
data->repo.meta.is_public = is_public;84
data->repo.meta.is_archive = _fetch_git_file_exists(data->repo.path, ".archive");85
data->repo.meta.is_fork = _fetch_git_file_exists(data->repo.path, ".fork");86
git_reference *ref_head_handle = NULL;87
git_repository_head(&ref_head_handle, data->repo.handle);88
if (ref_head_handle) {89
data->repo.ref_head = calloc(1, sizeof(git_repo_ref_t));90
git_repo_ref_t *ref = data->repo.ref_head;91
const git_oid *oid = git_reference_target(ref_head_handle);92
char oid_str[GIT_OID_HEXSZ + 1];93
git_oid_tostr(oid_str, sizeof(oid_str), oid);94
ref->oid = strdup(oid_str);95
const char *ref_name = git_reference_name(ref_head_handle);96
if (git_reference_is_branch(ref_head_handle)) {97
ref->name = strdup(ref_name + strlen("refs/heads/"));98
ref->type = "branch";99
}100
if (git_reference_is_tag(ref_head_handle)) {101
ref->name = strdup(ref_name + strlen("refs/tags/"));102
ref->type = "tag";103
}104
if (git_reference_is_remote(ref_head_handle)) {105
ref->name = strdup(ref_name + strlen("refs/remotes/"));106
ref->type = "remote";107
}108
if (!ref->name) {109
ref->name = strdup(ref_name);110
}111
git_reference_free(ref_head_handle);112
data->repo.readme_oid = _fetch_git_file_oid(repo_handle, ref->name, "README.md");113
data->repo.license_oid = _fetch_git_file_oid(repo_handle, ref->name, "LICENSE");114
git_reference_iterator *iter = NULL;115
git_reference *ref_handle = NULL;116
git_reference_iterator_new(&iter, data->repo.handle);117
while (git_reference_next(&ref_handle, iter) == 0) {118
data->repo.ref_list = realloc(data->repo.ref_list, sizeof(git_repo_ref_t) * (data->repo.ref_list_len + 1));119
git_repo_ref_t *ref = &data->repo.ref_list[data->repo.ref_list_len];120
memset(ref, 0, sizeof(git_repo_ref_t));121
const git_oid *oid = git_reference_target(ref_handle);122
char oid_str[GIT_OID_HEXSZ + 1];123
git_oid_tostr(oid_str, sizeof(oid_str), oid);124
ref->oid = strdup(oid_str);125
const char *ref_name = git_reference_name(ref_handle);126
if (git_reference_is_branch(ref_handle)) {127
ref->name = strdup(ref_name + strlen("refs/heads/"));128
ref->type = "branch";129
}130
if (git_reference_is_tag(ref_handle)) {131
ref->name = strdup(ref_name + strlen("refs/tags/"));132
ref->type = "tag";133
}134
if (git_reference_is_remote(ref_handle)) {135
ref->name = strdup(ref_name + strlen("refs/remotes/"));136
ref->type = "remote";137
}138
if (!ref->name) {139
ref->name = strdup(ref_name);140
}141
git_reference_free(ref_handle);142
data->repo.ref_list_len++;143
}144
git_reference_iterator_free(iter);145
}146
if (data->repo.ref_head && data->repo.flag_ref_oid && strcmp(data->repo.ref_head->oid, data->repo.flag_ref_oid) != 0) {147
git_oid ref_oid;148
if (git_oid_fromstr(&ref_oid, data->repo.flag_ref_oid) == 0) {149
git_reference_iterator *iter = NULL;150
git_reference *ref_handle = NULL;151
git_reference_iterator_new(&iter, data->repo.handle);152
while (git_reference_next(&ref_handle, iter) == 0) {153
const git_oid *oid = git_reference_target(ref_handle);154
if (oid && git_oid_equal(oid, &ref_oid)) {155
data->repo.ref = calloc(1, sizeof(git_repo_ref_t));156
git_repo_ref_t *ref = data->repo.ref;157
ref->oid = strdup(data->repo.flag_ref_oid);158
const char *ref_name = git_reference_name(ref_handle);159
if (git_reference_is_branch(ref_handle)) {160
ref->name = strdup(ref_name + strlen("refs/heads/"));161
ref->type = "branch";162
}163
if (git_reference_is_tag(ref_handle)) {164
ref->name = strdup(ref_name + strlen("refs/tags/"));165
ref->type = "tag";166
}167
if (git_reference_is_remote(ref_handle)) {168
ref->name = strdup(ref_name + strlen("refs/remotes/"));169
ref->type = "remote";170
}171
if (!ref->name) {172
ref->name = strdup(ref_name);173
}174
}175
git_reference_free(ref_handle);176
}177
git_reference_iterator_free(iter);178
if (!data->repo.ref) {179
git_object *obj_handle = NULL;180
if (git_object_lookup(&obj_handle, data->repo.handle, &ref_oid, GIT_OBJECT_COMMIT) == 0) {181
git_object_free(obj_handle);182
data->repo.ref_list = realloc(data->repo.ref_list, sizeof(git_repo_ref_t) * (data->repo.ref_list_len + 1));183
git_repo_ref_t *ref = &data->repo.ref_list[data->repo.ref_list_len];184
memset(ref, 0, sizeof(git_repo_ref_t));185
ref->oid = strdup(data->repo.flag_ref_oid);186
ref->name = strdup(data->repo.flag_ref_oid);187
ref->type = "commit";188
data->repo.ref_list_len++;189
data->repo.ref = calloc(1, sizeof(git_repo_ref_t));190
ref = data->repo.ref;191
ref->oid = strdup(data->repo.flag_ref_oid);192
ref->name = strdup(data->repo.flag_ref_oid);193
ref->type = "commit";194
}195
}196
}197
}198
return ORB_OK;199
}201
static orb_rc_t render(orb_module_t *self, void *out) {202
return ORB_ERR(duc_git_repo_render(out, (duc_git_repo_t *) self->data));203
}205
static void cleanup(orb_module_t *self) {206
duc_git_repo_t *data = self->data;207
if (data->repo.handle) {208
git_repository_free(data->repo.handle);209
data->repo.handle = NULL;210
}211
if (data->repo.meta.description) free(data->repo.meta.description);212
if (data->repo.meta.owner) free(data->repo.meta.owner);213
if (data->repo.ref_head) {214
free(data->repo.ref_head->oid);215
free(data->repo.ref_head->name);216
free(data->repo.ref_head);217
data->repo.ref_head = NULL;218
}219
if (data->repo.ref) {220
free(data->repo.ref->oid);221
free(data->repo.ref->name);222
free(data->repo.ref);223
data->repo.ref = NULL;224
}225
if (data->repo.readme_oid) free(data->repo.readme_oid);226
if (data->repo.license_oid) free(data->repo.license_oid);227
if (data->repo.ref_list && data->repo.ref_list_len > 0) {228
for (size_t i = 0; i < data->repo.ref_list_len; i++) {229
git_repo_ref_t *ref = &data->repo.ref_list[i];230
free(ref->oid);231
free(ref->name);232
}233
free(data->repo.ref_list);234
data->repo.ref_list = NULL;235
data->repo.ref_list_len = 0;236
}237
}239
const orb_module_type_t GIT_REPO_TYPE = {240
.size = sizeof(duc_git_repo_t),241
.init = init,242
.fetch = fetch,243
.render = render,244
.cleanup = cleanup,245
};