baseline

yet another open-source distributed versioning control system
Log | Files | Refs

commit 9ea49a139ac0c786f9f2e4a03c8fdcabbdcfb53d
parent a7b172257f8a12ec768cdad95013486ba761ab22
Author: Mohamed Aslan <maslan@sce.carleton.ca>
Date:   Wed, 18 Jun 2014 02:21:14 -0400

return the responsibility of generating IDs back to the OBJDB layer

Diffstat:
Mcmd-log.c | 58----------------------------------------------------------
Mobjdb-fs.c | 170++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mobjects.c | 129++-----------------------------------------------------------------------------
Mobjects.h | 4----
4 files changed, 168 insertions(+), 193 deletions(-)

diff --git a/cmd-log.c b/cmd-log.c @@ -25,67 +25,9 @@ int cmd_log(int argc, char **argv) { - char *x; struct session s; baseline_session_begin(&s, 0); - struct commit tmp = { - .id = "deadbeaf", - .dir = "badcode", - .n_parents = 0, - .author.name = "mohamed", - .author.email = "maslan@maslan.info", - .committer.name = "mohamed", - .committer.email = "maslan@maslan.info", - .message = "Hello World!" - }; - x = baseline_commit_serialize(&tmp); - printf("%s", x); - - struct dirent ent2 = { - .id = "02", - .name = "dir2.txt", - .type = T_DIR, - .mode = 1777, - .next = NULL - }; - struct dirent ent1 = { - .id = "01", - .name = "file1.txt", - .type = T_FILE, - .mode = 777, - .next = &ent2 - }; -/* - struct dir d = { - .id = "f0cd", - .children = &ent1 - }; -*/ - //struct dir d = {.children = NULL}; - struct dir *d = baseline_dir_new(); - baseline_dir_append(d, &ent1); - baseline_dir_append(d, &ent2); - x = baseline_dir_serialize(d); - printf("%s", x); - x = baseline_gen_id(d, O_DIR); - printf("%s\n", x); - baseline_dir_free(d); - - struct file f1 = { - .id = "00001", - .loc = ON_MEM, - }; - f1.buffer = strdup("hello"); - x = baseline_gen_id(&f1, O_FILE); - printf("%s\n", x); - struct file f2 = { - .id = "00002", - .loc = ON_FS, - }; - f2.fd = open("hi.txt", O_RDONLY); - x = baseline_gen_id(&f2, O_FILE); - printf("%s\n", x); baseline_session_end(&s); return EXIT_SUCCESS; diff --git a/objdb-fs.c b/objdb-fs.c @@ -99,6 +99,168 @@ get_objdb_dir(struct objdb_ctx *ctx) return db_dir_name; } +/* + * converts struct commit to char* + */ +char* +commit_serialize(struct commit *comm) +{ + char *raw = NULL; + + if (comm == NULL) + goto ret; + if (comm->n_parents == 0) + asprintf(&raw, "dir %s\nauthor %s <%s> %llu\ncommitter %s <%s> %llu\n%s\n", + comm->dir, comm->author.name, comm->author.email, comm->author.timestamp, + comm->committer.name, comm->committer.email, comm->committer.timestamp, comm->message); + else if (comm->n_parents == 1) + asprintf(&raw, "dir %s\nparent %s\nauthor %s <%s> %llu\ncommitter %s <%s> %llu\n%s\n", + comm->dir, comm->parents[0], comm->author.name, comm->author.email, comm->author.timestamp, + comm->committer.name, comm->committer.email, comm->committer.timestamp, comm->message); + /* TODO: support more than 1 parent */ +ret: + return raw; +} + +/* + * converts struct dir to char* + */ +char* +dir_serialize(struct dir *dir) +{ + char *entry = NULL, *raw = NULL, *ptr, ch = ' '; + size_t size = 1, newsize; + struct dirent *it; + + if (dir == NULL) + goto ret; + raw = (char *)malloc(sizeof(char)); + *raw = '\0'; + if (dir->children == NULL) + goto ret; + for (it = dir->children ; it != NULL ; it = it->next) { + if (it->type == T_FILE) + ch = 'F'; + else if (it->type == T_DIR) + ch = 'D'; + /* assuming asprintf() uses realloc() */ + /* free(entry); */ + asprintf(&entry, "%c %s %06o %s\n", ch, it->id, it->mode, it->name); + /* allocation failed, need to do something! */ + if (entry == NULL) + return NULL; + newsize = size + strlen(entry); + if ((ptr = realloc(raw, newsize)) == NULL) { + /* allocation failed, need to do something! */ + return NULL; + } + raw = ptr; + size = newsize; + strlcat(raw, entry, size); + } + free(entry); +ret: + return raw; +} + +static char * +file_gen_id(struct file *obj) +{ + char **objid = NULL, *ptr; + char buf[4096]; + int i, n; + off_t offset; + u_int8_t digest[SHA256_DIGEST_LENGTH]; + SHA2_CTX hash_ctx; + + SHA256Init(&hash_ctx); + /* TODO: locking */ + if (((struct file *)obj)->loc == ON_FS) { + /* save file offset */ + offset = lseek(obj->fd, 0, SEEK_CUR); + do { + n = read(obj->fd, buf, sizeof(buf)); + if (n == -1) + return NULL; + SHA256Update(&hash_ctx, buf, n); + if (n <= sizeof(buf)) + break; + } while (1); + /* restore file offset */ + lseek(obj->fd, offset, SEEK_SET); + } + else { + SHA256Update(&hash_ctx, obj->buffer, strlen(obj->buffer)); + } + objid = &(obj->id); + SHA256Final(digest, &hash_ctx); + *objid = (char *)malloc(SHA256_DIGEST_LENGTH * 2 + 1); + for (i=0, ptr=*objid ; i<SHA256_DIGEST_LENGTH ; i++, ptr+=2) { + snprintf(ptr, 3, "%02x", digest[i]); + } + return *objid; +} + +static char * +commit_gen_id_and_serialize(struct commit *obj, char **raw) +{ + char **objid = NULL, *ptr, *serialized = NULL; + int i; + u_int8_t digest[SHA256_DIGEST_LENGTH]; + SHA2_CTX hash_ctx; + + SHA256Init(&hash_ctx); + serialized = commit_serialize(obj); + SHA256Update(&hash_ctx, serialized, strlen(serialized)); + objid = &(obj->id); + SHA256Final(digest, &hash_ctx); + *objid = (char *)malloc(SHA256_DIGEST_LENGTH * 2 + 1); + for (i=0, ptr=*objid ; i<SHA256_DIGEST_LENGTH ; i++, ptr+=2) { + snprintf(ptr, 3, "%02x", digest[i]); + } + *raw = serialized; + return *objid; +} + +static char * +commit_gen_id(struct commit *obj) +{ + char *raw; + char *id = commit_gen_id_and_serialize(obj, &raw); + free(raw); + return id; +} + +static char * +dir_gen_id_and_serialize(struct dir *obj, char **raw) +{ + char **objid = NULL, *ptr, *serialized = NULL; + int i; + u_int8_t digest[SHA256_DIGEST_LENGTH]; + SHA2_CTX hash_ctx; + + SHA256Init(&hash_ctx); + serialized = dir_serialize(obj); + SHA256Update(&hash_ctx, serialized, strlen(serialized)); + objid = &(obj->id); + SHA256Final(digest, &hash_ctx); + *objid = (char *)malloc(SHA256_DIGEST_LENGTH * 2 + 1); + for (i=0, ptr=*objid ; i<SHA256_DIGEST_LENGTH ; i++, ptr+=2) { + snprintf(ptr, 3, "%02x", digest[i]); + } + *raw = serialized; + return *objid; +} + +static char * +dir_gen_id(struct dir *obj) +{ + char *raw; + char *id = dir_gen_id_and_serialize(obj, &raw); + free(raw); + return id; +} + static int objdb_bl_open(struct objdb_ctx **ctx, const char *db_name, const char *db_path) { @@ -165,7 +327,7 @@ objdb_bl_insert_file(struct objdb_ctx *ctx, struct file *file) goto ret; } asprintf(&full_path, "%s/%s", db_dir_name, "files"); - obj_hash = baseline_gen_id(file, O_FILE); + obj_hash = file_gen_id(file); /* create a temp file */ asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); if ((tmpfd = mkstemp(tmp_file_name)) == -1) { @@ -221,8 +383,7 @@ objdb_bl_insert_dir(struct objdb_ctx *ctx, struct dir *dir) goto ret; } asprintf(&full_path, "%s/%s", db_dir_name, "dirs"); - data = baseline_dir_serialize(dir); - obj_hash = baseline_gen_id(dir, O_DIR); + obj_hash = dir_gen_id_and_serialize(dir, &data); /* create a temp file */ asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); @@ -274,8 +435,7 @@ objdb_bl_insert_commit(struct objdb_ctx *ctx, struct commit *comm) goto ret; } asprintf(&full_path, "%s/%s", db_dir_name, "commits"); - data = baseline_commit_serialize(comm); - obj_hash = baseline_gen_id(comm, O_COMMIT); + obj_hash = commit_gen_id_and_serialize(comm, &data); /* create a temp file */ asprintf(&tmp_file_name, "%s/tmp.XXXXXX", full_path); diff --git a/objects.c b/objects.c @@ -16,14 +16,10 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <unistd.h> /* read(2) */ - -#include <sha2.h> #include "objects.h" -struct file * +struct file* baseline_file_new() { struct file *file = (struct file *)calloc(1, sizeof(struct file)); @@ -41,7 +37,7 @@ baseline_file_free(struct file *file) free(file); } -struct commit * +struct commit* baseline_commit_new() { struct commit *comm = (struct commit *)calloc(1, sizeof(struct commit)); @@ -62,30 +58,7 @@ baseline_commit_free(struct commit *comm) free(comm); } -/* - * converts struct commit to char* - */ -char* -baseline_commit_serialize(struct commit *comm) -{ - char *raw = NULL; - - if (comm == NULL) - goto ret; - if (comm->n_parents == 0) - asprintf(&raw, "dir %s\nauthor %s <%s> %llu\ncommitter %s <%s> %llu\n%s\n", - comm->dir, comm->author.name, comm->author.email, comm->author.timestamp, - comm->committer.name, comm->committer.email, comm->committer.timestamp, comm->message); - else if (comm->n_parents == 1) - asprintf(&raw, "dir %s\nparent %s\nauthor %s <%s> %llu\ncommitter %s <%s> %llu\n%s\n", - comm->dir, comm->parents[0], comm->author.name, comm->author.email, comm->author.timestamp, - comm->committer.name, comm->committer.email, comm->committer.timestamp, comm->message); - /* TODO: support more than 1 parent */ -ret: - return raw; -} - -struct dir * +struct dir* baseline_dir_new() { struct dir *dir = (struct dir *)calloc(1, sizeof(struct dir)); @@ -129,99 +102,3 @@ baseline_dir_append(struct dir *dir, struct dirent *ent) ent->next = NULL; } -/* - * converts struct dir to char* - */ -char* -baseline_dir_serialize(struct dir *dir) -{ - char *entry = NULL, *raw = NULL, *ptr, ch = ' '; - size_t size = 1, newsize; - struct dirent *it; - - if (dir == NULL) - goto ret; - raw = (char *)malloc(sizeof(char)); - *raw = '\0'; - if (dir->children == NULL) - goto ret; - for (it = dir->children ; it != NULL ; it = it->next) { - if (it->type == T_FILE) - ch = 'F'; - else if (it->type == T_DIR) - ch = 'D'; - /* assuming asprintf() uses realloc() */ - entry = NULL; - asprintf(&entry, "%c %s %06o %s\n", ch, it->id, it->mode, it->name); - /* allocation failed, need to do something! */ - if (entry == NULL) - return NULL; - newsize = size + strlen(entry); - if ((ptr = realloc(raw, newsize)) == NULL) { - /* allocation failed, need to do something! */ - return NULL; - } - raw = ptr; - size = newsize; - strlcat(raw, entry, size); - } - free(entry); -ret: - return raw; -} - -char* -baseline_gen_id(void *obj, enum objtype type) -{ - char **objid = NULL, *ptr, *serialized = NULL; - char buf[4096]; - int i, n; - off_t offset; - u_int8_t digest[SHA256_DIGEST_LENGTH]; - SHA2_CTX hash_ctx; - - SHA256Init(&hash_ctx); - switch (type) { - case O_COMMIT: - serialized = baseline_commit_serialize((struct commit *)obj); - SHA256Update(&hash_ctx, serialized, strlen(serialized)); - free(serialized); - objid = &(((struct commit *)obj)->id); - break; - case O_DIR: - serialized = baseline_dir_serialize((struct dir *)obj); - SHA256Update(&hash_ctx, serialized, strlen(serialized)); - free(serialized); - objid = &(((struct dir *)obj)->id); - break; - case O_FILE: - if (((struct file *)obj)->loc == ON_FS) { - /* save file offset */ - offset = lseek(((struct file *)obj)->fd, 0, SEEK_CUR); - do { - n = read(((struct file *)obj)->fd, buf, sizeof(buf)); - if (n == -1) - return NULL; - SHA256Update(&hash_ctx, buf, n); - if (n <= sizeof(buf)) - break; - } while (1); - /* restore file offset */ - lseek(((struct file *)obj)->fd, offset, SEEK_SET); - } - else { - SHA256Update(&hash_ctx, ((struct file *)obj)->buffer, strlen(((struct file *)obj)->buffer)); - } - objid = &(((struct file *)obj)->id); - break; - default: - break; - } - SHA256Final(digest, &hash_ctx); - *objid = (char *)malloc(SHA256_DIGEST_LENGTH * 2 + 1); - for (i=0, ptr=*objid ; i<SHA256_DIGEST_LENGTH ; i++, ptr+=2) { - snprintf(ptr, 3, "%02x", digest[i]); - } - return *objid; -} - diff --git a/objects.h b/objects.h @@ -80,13 +80,9 @@ void baseline_file_free(struct file *); /* commit ops */ struct commit* baseline_commit_new(); void baseline_commit_free(struct commit *); -char* baseline_commit_serialize(struct commit *); /* dir ops */ struct dir* baseline_dir_new(); void baseline_dir_free(struct dir *); void baseline_dir_append(struct dir *, struct dirent *); -char* baseline_dir_serialize(struct dir *); -/* id ops */ -char *baseline_gen_id(void *, enum objtype); #endif