so://phie

soso

My pretty neat website
git clone git://soophie.de/soso

blob: f20159b9b6823098f259e2d5abe6633606e29171 (3628 bytes)[raw]

1#include <git2.h>

2#include "git_repo.h"

3#include "git_repo_tree.h"

4

5#include "../templ/duc_git_repo_tree.h"

6

7static orb_rc_t init(orb_module_t *self) {

8 duc_git_repo_tree_t *data = self->data;

9 git_repo_tree_param_list_t *param_list = self->param_list;

10 if (param_list) {

11 data->repo = param_list->repo;

12 }

13 return ORB_OK;

14}

15

16static int _fetch_tree_cb(const char *root, const git_tree_entry *entry_handle, void *data) {

17 git_repo_tree_cb_t *handle = data;

18 const char *name = git_tree_entry_name(entry_handle);

19 git_filemode_t mode_handle = git_tree_entry_filemode(entry_handle);

20 if (mode_handle != GIT_FILEMODE_TREE) {

21 *handle->entry_list = realloc(*handle->entry_list, sizeof(git_repo_tree_entry_t) * (*handle->entry_list_len + 1));

22 git_repo_tree_entry_t *entry = &(*handle->entry_list)[*handle->entry_list_len];

23 memset(entry, 0, sizeof(git_repo_tree_entry_t));

24 const git_oid *oid = git_tree_entry_id(entry_handle);

25 char oid_str[GIT_OID_HEXSZ + 1];

26 git_oid_tostr(oid_str, sizeof(oid_str), oid);

27 entry->oid = strdup(oid_str);

28 size_t filepath_len = strlen(root) + strlen(name);

29 char filepath[filepath_len + 1];

30 snprintf(filepath, sizeof(filepath), "%s%s", root, name);

31 entry->name = strdup(filepath);

32 entry->mode = strdup((mode_handle == GIT_FILEMODE_BLOB_EXECUTABLE) ? "-rwx-xr-x" : (mode_handle == GIT_FILEMODE_TREE) ? "d---------" : "-rw-r--r--");

33 git_object_t obj_type = git_tree_entry_type(entry_handle);

34 if (obj_type == GIT_OBJECT_BLOB) {

35 git_object *obj_handle = NULL;

36 git_tree_entry_to_object(&obj_handle, handle->repo_handle, entry_handle);

37 git_blob *blob_handle = (git_blob *) obj_handle;

38 entry->size = (size_t) git_blob_rawsize(blob_handle);

39 git_object_free(obj_handle);

40 }

41 (*handle->entry_list_len)++;

42 }

43 return 0;

44}

45

46static orb_rc_t fetch(orb_module_t *self) {

47 duc_git_repo_tree_t *data = self->data;

48 if (!data->repo) return ORB_ERR(1);

49 char *ref_oid = NULL;

50 if (data->repo->ref_head) ref_oid = data->repo->ref_head->oid;

51 if (data->repo->ref) ref_oid = data->repo->ref->oid;

52 if (!ref_oid) return ORB_ERR(2);

53 const char *spec_suffix = "^{commit}";

54 size_t spec_len = strlen(ref_oid) + strlen(spec_suffix) + 1;

55 char spec[spec_len];

56 snprintf(spec, spec_len, "%s%s", ref_oid, spec_suffix);

57 git_object *obj = NULL;

58 if (git_revparse_single(&obj, data->repo->handle, spec) == 0) {

59 git_commit *commit_handle = (git_commit *) obj;

60 git_tree *tree_handle = NULL;

61 if (git_commit_tree(&tree_handle, commit_handle) == 0) {

62 git_tree_walk(tree_handle, GIT_TREEWALK_PRE, _fetch_tree_cb, &((git_repo_tree_cb_t) {

63 .repo_handle = data->repo->handle,

64 .entry_list = &data->entry_list,

65 .entry_list_len = &data->entry_list_len,

66 }));

67 git_tree_free(tree_handle);

68 }

69 git_object_free(obj);

70 }

71 return ORB_OK;

72}

73

74static orb_rc_t render(orb_module_t *self, void *out) {

75 return ORB_ERR(duc_git_repo_tree_render(out, (duc_git_repo_tree_t *) self->data));

76}

77

78static void cleanup(orb_module_t *self) {

79 duc_git_repo_tree_t *data = self->data;

80 if (data->entry_list && data->entry_list_len > 0) {

81 for (size_t i = 0; i < data->entry_list_len; i++) {

82 git_repo_tree_entry_t *entry = &data->entry_list[i];

83 free(entry->oid);

84 free(entry->name);

85 free(entry->mode);

86 }

87 free(data->entry_list);

88 data->entry_list = NULL;

89 data->entry_list_len = 0;

90 }

91}

92

93const orb_module_type_t GIT_REPO_TREE_TYPE = {

94 .size = sizeof(duc_git_repo_tree_t),

95 .init = init,

96 .fetch = fetch,

97 .render = render,

98 .cleanup = cleanup,

99};