commit - 4684ea103757f25b8ac4aab872d9de45ae7d942e
commit + 0ffeb3c2d8dbe6ae565c5a4ae78d63c74897d102
blob - d993168dde3b77d1059065694c266b38c255c701
blob + d13b60b4636e8d6487f381e4411f9f4167864c19
--- include/got_object.h
+++ include/got_object.h
char *dummy;
};
+struct got_tree_entry {
+ SIMPLEQ_ENTRY(got_tree_entry) entry;
+ mode_t mode;
+ char *name;
+ struct got_object_id id;
+};
+
struct got_tree_object {
- char *dummy;
+ int nentries;
+ SIMPLEQ_HEAD(, got_tree_entry) entries;
};
struct got_parent_id {
const struct got_error *got_object_commit_open(struct got_commit_object **,
struct got_repository *, struct got_object *);
void got_object_commit_close(struct got_commit_object *);
-
+const struct got_error *got_object_tree_open(struct got_tree_object **,
+ struct got_repository *, struct got_object *);
+void got_object_tree_close(struct got_tree_object *);
blob - f24b83d937d8f42d22bbce3b29d61394aca28678
blob + f4cdddb788293a815d8951ca973ba1e28f3dedfb
--- lib/object.c
+++ lib/object.c
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/stat.h>
#include <sys/queue.h>
#include <stdio.h>
done:
if (err)
got_object_commit_close(*commit);
+ return err;
+}
+
+static void
+tree_entry_close(struct got_tree_entry *te)
+{
+ free(te->name);
+ free(te);
+}
+
+static const char *
+mode_trailer(mode_t mode)
+{
+ if (S_ISDIR(mode))
+ return "/";
+
+ return "";
+}
+
+static const struct got_error *
+parse_tree_entry(struct got_tree_entry **te, size_t *elen, char *buf,
+ size_t maxlen)
+{
+ char *p = buf, *space;
+ const struct got_error *err = NULL;
+ char hex[SHA1_DIGEST_STRING_LENGTH];
+
+ *te = calloc(1, sizeof(**te));
+ if (*te == NULL)
+ return got_error(GOT_ERR_NO_MEM);
+
+ *elen = strlen(buf) + 1;
+ if (*elen > maxlen) {
+ free(*te);
+ return got_error(GOT_ERR_BAD_OBJ_DATA);
+ }
+
+ space = strchr(buf, ' ');
+ if (space == NULL) {
+ free(*te);
+ return got_error(GOT_ERR_BAD_OBJ_DATA);
+ }
+ while (*p != ' ') {
+ if (*p < '0' && *p > '7') {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ (*te)->mode <<= 3;
+ (*te)->mode |= *p - '0';
+ p++;
+ }
+
+ (*te)->name = strdup(space + 1);
+ if (*elen > maxlen || maxlen - *elen < SHA1_DIGEST_LENGTH) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+ buf += strlen(buf) + 1;
+ memcpy((*te)->id.sha1, buf, SHA1_DIGEST_LENGTH);
+ *elen += SHA1_DIGEST_LENGTH;
+
+ printf("%s %s%s\n", got_object_id_str(&(*te)->id, hex, sizeof(hex)),
+ (*te)->name, mode_trailer((*te)->mode));
+done:
+ if (err)
+ tree_entry_close(*te);
return err;
}
static const struct got_error *
+open_tree_recursive(struct got_object_id *id, struct got_repository *repo)
+{
+ struct got_object *obj;
+ struct got_tree_object *tree;
+ const struct got_error *err;
+
+ err = got_object_open(&obj, repo, id);
+ if (err)
+ return err;
+ if (obj->type != GOT_OBJ_TYPE_TREE)
+ return got_error(GOT_ERR_OBJ_TYPE);
+
+ err = got_object_tree_open(&tree, repo, obj);
+ if (err) {
+ got_object_close(obj);
+ return err;
+ }
+
+ got_object_tree_close(tree);
+ got_object_close(obj);
+ return NULL;
+}
+
+static const struct got_error *
+parse_tree_object(struct got_tree_object **tree, struct got_repository *repo,
+ char *buf, size_t len)
+{
+ size_t remain = len;
+ int nentries;
+
+ *tree = calloc(1, sizeof(**tree));
+ if (*tree == NULL)
+ return got_error(GOT_ERR_NO_MEM);
+
+ SIMPLEQ_INIT(&(*tree)->entries);
+
+ while (remain > 0) {
+ struct got_tree_entry *te;
+ size_t elen;
+
+ parse_tree_entry(&te, &elen, buf, remain);
+ (*tree)->nentries++;
+ SIMPLEQ_INSERT_TAIL(&(*tree)->entries, te, entry);
+ if (S_ISDIR(te->mode)) {
+ const struct got_error *err;
+ err = open_tree_recursive(&te->id, repo);
+ if (err) {
+ got_object_tree_close(*tree);
+ return err;
+ }
+ }
+ buf += elen;
+ remain -= elen;
+ }
+ printf("\n");
+
+ if (remain != 0) {
+ got_object_tree_close(*tree);
+ return got_error(GOT_ERR_BAD_OBJ_DATA);
+ }
+
+ return NULL;
+}
+
+static const struct got_error *
read_commit_object(struct got_commit_object **commit,
struct got_repository *repo, struct got_object *obj, const char *path)
{
free(commit->logmsg);
free(commit);
}
+
+static const struct got_error *
+read_tree_object(struct got_tree_object **tree,
+ struct got_repository *repo, struct got_object *obj, const char *path)
+{
+ const struct got_error *err = NULL;
+ FILE *f;
+ struct got_zstream_buf zb;
+ size_t len;
+ char *p;
+ int i, ret;
+
+ f = fopen(path, "rb");
+ if (f == NULL)
+ return got_error(GOT_ERR_BAD_PATH);
+
+ err = inflate_init(&zb, 8192);
+ if (err) {
+ fclose(f);
+ return err;
+ }
+
+ do {
+ err = inflate_read(&zb, f, &len);
+ if (err || len == 0)
+ break;
+ } while (len < obj->hdrlen + obj->size);
+
+ if (len < obj->hdrlen + obj->size) {
+ err = got_error(GOT_ERR_BAD_OBJ_DATA);
+ goto done;
+ }
+
+ /* Skip object header. */
+ len -= obj->hdrlen;
+ err = parse_tree_object(tree, repo, zb.outbuf + obj->hdrlen, len);
+done:
+ inflate_end(&zb);
+ fclose(f);
+ return err;
+}
+
+const struct got_error *
+got_object_tree_open(struct got_tree_object **tree,
+ struct got_repository *repo, struct got_object *obj)
+{
+ const struct got_error *err = NULL;
+ char *path = NULL;
+
+ if (obj->type != GOT_OBJ_TYPE_TREE)
+ return got_error(GOT_ERR_OBJ_TYPE);
+
+ err = object_path(&path, &obj->id, repo);
+ if (err)
+ return err;
+
+ err = read_tree_object(tree, repo, obj, path);
+ free(path);
+ return err;
+}
+
+void
+got_object_tree_close(struct got_tree_object *tree)
+{
+}
blob - 8c1fcd816103828141db98729cf464427feca200
blob + 2044938135e906df60393fc61d80b70c7c452e9a
--- regress/repository/repository_test.c
+++ regress/repository/repository_test.c
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/stat.h>
#include <sys/queue.h>
#include <stdio.h>
}
static const struct got_error *
+print_tree_object(struct got_object *obj, struct got_repository *repo)
+{
+ struct got_tree_object *tree;
+ const struct got_error *err;
+
+ err = got_object_tree_open(&tree, repo, obj);
+ if (err != NULL)
+ return err;
+
+ got_object_tree_close(tree);
+ return NULL;
+}
+
+static const struct got_error *
print_commit_object(struct got_object *obj, struct got_repository *repo)
{
struct got_commit_object *commit;
struct got_parent_id *pid;
char buf[SHA1_DIGEST_STRING_LENGTH];
const struct got_error *err;
+ struct got_object* treeobj;
err = got_object_commit_open(&commit, repo, obj);
if (err != NULL)
printf("committer: %s\n", commit->committer);
printf("log: %s\n", commit->logmsg);
+ err = got_object_open(&treeobj, repo, &commit->tree_id);
+ if (err != NULL)
+ return err;
+ if (treeobj->type == GOT_OBJ_TYPE_TREE)
+ print_tree_object(treeobj, repo);
+ got_object_close(treeobj);
+
err = print_parent_commits(commit, repo);
got_object_commit_close(commit);